Reputation: 31
The .txt file consists of id, name, gender, occupation, age. Now I need to read from the file and create a linked list and print the list. The code should be in C language.
below is the code which I am trying, but only a string/ word is printing. Do I need to use fscanf function in while loop instead of fgets function? I need to print all the contents of text file, which has both integer and character type in it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct list {
char *string;
struct list *next;
};
typedef struct list LIST;
int main(void) {
FILE *fp;
char line[128];
LIST *current, *head;
head = current = NULL;
fp = fopen("hello.txt", "r");
while(fgets(line, sizeof(line), fp)){
LIST *node = malloc(sizeof(LIST));
node->string = strdup(line);
node->next =NULL;
if(head == NULL){
current = head = node;
} else {
printf("%s", current->string);
current = current->next = node;
}
}
fclose(fp);
for(current = head; current ; current=current->next){
// printf("%s", current->string);
}
return 0;
}
Upvotes: 2
Views: 129
Reputation: 117298
This is wrong since it will never print the last line you read:
if(head == NULL){
current = head = node;
} else {
printf("%s", current->string); // prints the previous line
current = current->next = node;
}
If you want all lines to be printed, do the printing after you've assigned current
:
if(head == NULL){
current = head = node;
} else {
current = current->next = node;
}
printf("%s", current->string);
Or before assigning current
, using node
:
printf("%s", node->string);
if(head == NULL){
current = head = node;
} else {
current = current->next = node;
}
I would also suggest organizing the code and make use of functions.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct list LIST;
struct list {
char *string;
LIST *next; // I moved the typedef above the struct list definition
};
// A function to read and populate a list from a stream:
LIST *list_read(FILE *fp) {
char line[128];
LIST *head, **tail = &head;
while (fgets(line, sizeof line, fp)) {
LIST *node = malloc(sizeof *node);
node->string = strdup(line);
// simplification of your `if(head == NULL)` code. No `if`s needed:
*tail = node;
tail = &node->next;
}
*tail = NULL;
return head;
}
// A function to free the resources allocated by a list
void list_free(LIST *head) {
for (LIST *current = head, *next; current; current = next) {
next = current->next;
free(current->string);
free(current);
}
}
// A function to print a list
void list_print(LIST *head) {
for (LIST *current = head; current; current = current->next) {
printf("%s", current->string);
}
}
int main(void) {
FILE *fp = fopen("hello.txt", "r");
if (fp == NULL) return 1;
LIST *head = list_read(fp);
fclose(fp);
list_print(head);
list_free(head);
}
If you want the list to be sorted in alphabetical order, you could add a function that inserts a node in the correct position in the list:
void list_insert(LIST **lp, char *str) {
LIST *node = malloc(sizeof *node);
node->string = strdup(str);
// find insertion point for the list to be in alphabetical order
while(*lp && strcmp(str, (*lp)->string) > 0) {
lp = &(*lp)->next;
}
// link the new node:
node->next = *lp;
*lp = node;
}
and change list_read
accordingly:
LIST *list_read(FILE *fp) {
char line[128];
LIST *head = NULL;
while (fgets(line, sizeof line, fp)) {
list_insert(&head, line);
}
return head;
}
Upvotes: 1