I'm attempting to create a linked list using a struct from a txt file. Initially, I'm testing it with a txt file with only one line of information. This code compiles correctly, however when I run it, it returns "Line...didn't scan properly". As an aside, if I remove the if statement that returns such a value I get complete gibberish. I have no clue why the line isn't being scanned correctly, however I feel as though it may having something to do with the hyphen/plus sign in two of the terms that I tried to scan as strings. Thank you very much for any help you can provide.
This is the txt file:
1 20959U 90103A 14091.58762725 -.00000015 00000-0 00000+0 0 3197
This is the tester.c file:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct noradData {
// line one
int lineNum;
char * satNum;
char * intDesig;
float epoch;
float firstTimeDeriv;
char * secondTimeDeriv;
char * drag;
int zero;
int set;
struct noradData * next;
} Data;
Data * first = NULL, * last = NULL;
int main() {
char line[80], secondTimeDeriv[7], drag[7], satNum[6], intDesig[6];
int lineNum, zero, set;
float epoch, firstTimeDeriv;
FILE * fIn;
Data * node;
fIn = fopen("data1.txt", "r");
if (fIn == NULL) {
printf("Cannot open file\n");
return 1;
}
while (fgets(line, sizeof(line), fIn) != NULL) {
// Check line for various problems (too short, too long).
if (line[0] == '\0') {
printf ("Line too short\n");
return 1;
}
if (line[strlen (line)-1] != '\n') {
printf ("Line starting with '%s' is too long\n", line);
return 1;
}
line[strlen (line)-1] = '\0';
// Scan the individual fields.
if (scanf("%d %s %s %f %f %s %s %d %d", &lineNum, satNum, intDesig,
&epoch, &firstTimeDeriv, secondTimeDeriv, drag, &zero, &set)
!= 9) {
printf ("Line '%s' didn't scan properly\n", line);
return 1;
}
node = malloc(sizeof(Data));
if (node == NULL) {
printf ("Ran out of memory\n");
return 1;
}
node->lineNum = lineNum;
node->satNum = strdup(satNum);
node->intDesig = strdup (intDesig);
node->epoch = epoch;
node->firstTimeDeriv = firstTimeDeriv;
node->secondTimeDeriv = strdup(secondTimeDeriv);
node->drag = strdup(drag);
node->zero = zero;
node->set = set;
node->next = NULL;
if (first != NULL) {
last->next = node;
last = node;
}
else {
first = node;
last = node;
}
}
fclose (fIn);
node = first;
while (node != NULL) {
printf("%d %s %s %f %f %s %s %d %d", node->lineNum, node->satNum,
node->intDesig, node->epoch, node->firstTimeDeriv,
node->secondTimeDeriv, node->drag, node->zero, node->set);
node = node->next;
}
return 0;
}
First of all change size of character arrays satnum and intdDesig to 7
that is satnum[7] and intDesig[7]. You want to store 6 characters in these leave last index for null value.
if (line[strlen (line)-1] != '\n') {
printf ("Line starting with '%s' is too long\n", line);
return 1;
}
This if statement instead of line[strlen(line)-1]!='\n' put this-
line[strlen(line)-1]=='\n'
and statement goes like this
if (line[strlen (line)-1]=='\n') {
printf ("Line starting with '%s' is too long\n", line);
return 1;
}
And remove this line
line[strlen (line)-1] = '\0';
Then line will not be returned twice .
Related
So, I have to print a linked list from a file input, which I've managed to get working:
#include <stdio.h>
#include <stdlib.h>
typedef struct Vehicle{
int option;
char make [30];
char model[30];
int car_manufacture_date;
float maximum_velocity;
float mass;
int seats;
struct Vehicle *next;//linked list node
} vehicle_t;
int main (){
FILE* fp;
fp = fopen("vehicles.crash.txt", "r");
vehicle_t* first_car = malloc(sizeof(vehicle_t));
if (first_car == NULL){
printf("Error. Failed to allocate memory to first_car\n");
exit(1);
}
vehicle_t* current_vehicle = malloc(sizeof(vehicle_t));
if (current_vehicle == NULL){
printf("Error. Failed to allocate memory to current_vehicle\n");
exit(1);
}
vehicle_t* new_vehicle = malloc(sizeof(vehicle_t));
if (new_vehicle == NULL){
printf("Error. Failed to allocate memory to new_vehicle\n");
exit(1);
}
printf("GOOD1\n");
current_vehicle = first_car;
new_vehicle = first_car;
printf("GOOD2\n");
//Loading vehicles from file to linked list
if (fp != NULL)
{
printf("GOOD3\n");
while (fscanf(fp,"%d %s %s %d %f %f %d", &new_vehicle->option, new_vehicle->make, new_vehicle->model, &new_vehicle->car_manufacture_date,
&new_vehicle->maximum_velocity, &new_vehicle->mass, &new_vehicle->seats) != EOF)
{
printf("GOOD4\n");
current_vehicle->next = new_vehicle;
current_vehicle = current_vehicle->next;
new_vehicle = malloc(sizeof(vehicle_t));
if (first_car == NULL){
printf("Error. Failed to allocate memory\n");
new_vehicle->next=NULL;
exit(1);
}
printf("GOOD5\n");
}
close(fp);
printf("Input completed\n");
}
else
printf("Error! couldn't find file\n");
current_vehicle = first_car;
while (current_vehicle != NULL)
{
printf("Option: %d\tMake: %s\tModel: %s\tManufactured: %d\tMax Velocity: %.2f\tMass: %.2f\tSeats: %d\n",
current_vehicle->option, current_vehicle->make, current_vehicle->model, current_vehicle->car_manufacture_date,
current_vehicle->maximum_velocity, current_vehicle->mass, current_vehicle->seats);
new_vehicle = current_vehicle->next;
current_vehicle = current_vehicle->next;
};
printf("Printing completed");
return 0;
}
Everything works fine right until the last file item is printed out, after which the program crashes. From what I've seen in other posts, the while loop matches them all.
The printed "GOOD" statements are just checkpoints
The text in the file is formatted as: 1 Toyota Camry 2010 200.0 1100.0 5
I think you forget to set the ->next field of the last list node to NULL. You just called malloc, so the value could be anything random, making your printing failed.
The main reason for the infinite loop was failing to set the final next to NULL [as others have mentioned].
But, I think this is easier to see with the code simplified as yours, although mostly correct, was more complicated than it needed to be.
Anyway, this compiles but I didn't test it [please pardon the gratuitous style cleanup]:
#include <stdio.h>
#include <stdlib.h>
typedef struct Vehicle {
int option;
char make[30];
char model[30];
int car_manufacture_date;
float maximum_velocity;
float mass;
int seats;
struct Vehicle *next; // linked list node
} vehicle_t;
int
main()
{
FILE *fp;
fp = fopen("vehicles.crash.txt", "r");
if (fp == NULL) {
printf("Error! couldn't find file\n");
exit(1);
}
vehicle_t *first_car = NULL;
vehicle_t *previous_vehicle = NULL;
// Loading vehicles from file to linked list
while (1) {
vehicle_t *new_vehicle = malloc(sizeof(vehicle_t));
if (new_vehicle == NULL) {
printf("Error. Failed to allocate memory to new_vehicle\n");
exit(1);
}
// NOTE: the lack of this [in your equivalent code] was the reason
// for the infinite loop
new_vehicle->next = NULL;
if (fscanf(fp, "%d %s %s %d %f %f %d",
&new_vehicle->option, new_vehicle->make, new_vehicle->model,
&new_vehicle->car_manufacture_date, &new_vehicle->maximum_velocity,
&new_vehicle->mass, &new_vehicle->seats) == EOF) {
free(new_vehicle);
break;
}
if (first_car == NULL)
first_car = new_vehicle;
else
previous_vehicle->next = new_vehicle;
previous_vehicle = new_vehicle;
}
fclose(fp);
vehicle_t *current_vehicle = first_car;
while (current_vehicle != NULL) {
printf("Option: %d\tMake: %s\tModel: %s\tManufactured: %d\tMax Velocity: %.2f\tMass: %.2f\tSeats: %d\n",
current_vehicle->option, current_vehicle->make,
current_vehicle->model, current_vehicle->car_manufacture_date,
current_vehicle->maximum_velocity, current_vehicle->mass,
current_vehicle->seats);
current_vehicle = current_vehicle->next;
};
printf("Printing completed");
return 0;
}
I am new to programming in C and for an assignment for one of my classes, we are to write code that would read in a text file, put all the words in a linked list with a counter, and output that linked list into a text file.
I'm not sure what I am doing wrong in my below code, it only counts some of the words and seems to skip others. (I added many extra prints to try and see where the words are lost)
I then attempted to make all the words lowercase when they were added to the linked list, but that seemed to make it read even less words and I have no clue why.
Any help/suggestions would be greatly appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef struct s_words {
char *str; //word
int count; //number of times word occurs
struct s_words* next; //pointer to next word
} words;
words* create_words(char* word) {
//+allocate space for the structure
printf("%lu ", strlen(word));
words* newWord = malloc(sizeof(words));
if (NULL != newWord)
{
//+allocate space for storing the new word in "str"
//+if str was array of fixed size, storage wud be wasted
newWord->str = (char *)malloc((strlen(word))+1);
strcpy(newWord->str, word); //+copy “word” into newWord->str
newWord->str[strlen(word)]='\0';
printf(" Create: %s ", newWord->str);
//+initialize count to 1;
newWord->count = 1;
//+initialize next;
newWord->next = NULL;
}
return newWord;
}
words* add_word(words* wordList, char* word)
{
int found=0;
words *temp=wordList;
//+ search if word exists in the list; if so, make found=1
while (temp != NULL)
{
if (strcmp(temp->str, word) == 0)
{ //+use strcmp command
found=1;
temp->count = temp->count+1; //+increment count;
return wordList;
}
else
{
//+update temp
temp = temp->next;
}
}
if (found==0)
{ //new word
//printf("%s ", word);
words* newWord = create_words(word);
if (NULL != newWord)
{
//+?? Insert new word at the head of the list
newWord->next = wordList;
printf(" NEW WORD: %s\n ", newWord->str);
}
return newWord;
}
//return wordList; //code never gets here, just added in case of error
}
int main(int argc, char* argv[])
{
words *mywords; //+head of linked list containing words
mywords=NULL;
FILE *myFile;
FILE *myOutput;
char* filename = argv[1];
char* outputfile = argv[2];
myFile = fopen(filename, "r"); //+first parameter is input file
if (myFile==0)
{
printf("file not opened\n");
return 1;
}
else
{
printf("file opened \n");
}
//+start reading file character by character;
//+when word has been detected; call the add_word function
int ch = 0, word = 1, k = 0;
char thisword[100];
//ch = putchar(tolower(ch));
//ch = fgetc(myFile);
while ((ch = fgetc(myFile)) != EOF )
{
//error handling
if (ch == '.' || ch == ' ' || ch == ',' || ch == ':' || ch == ';' || ch == '\n') //+detect new word? Check if ch is a delimiter
{ //when above if is true, new word created in next if:
if ( word == 1 ) //+make sure previous character was not delimiter
{
word = 0;
//+make the kth character of thisword as \0
thisword[k] = '\0';
//+now call add_word to add thisword into the list
printf(" Add:%s ", thisword);
mywords = add_word(mywords, thisword);
printf(" Added:%s\n", mywords->str);
k=0;
}
}
else
{
word = 1;
//make ch lowercase
//ch = putchar(toupper(ch));
//+?? //make the kth character of thisword equal to ch
thisword[k] = ch;
thisword[k] = putchar(tolower(thisword[k]));
k++;
}
}
if (word == 1)
{
thisword[k] = '\0';
//add thisword into the list
printf("Last Word:%s ", thisword);
mywords = add_word(mywords, thisword);
}
words *currword;
printf("printing list\n");
//+Traverse list and print each word and its count to outputfile
//+output file is second parameter being passed
myOutput = fopen(outputfile, "w+"); //+first parameter is input file
if (myOutput == 0)
{
printf("output file not opened \n");
return 1;
}
else
{
printf("output file opened \n");
}
currword = mywords;
while (currword->next != NULL)
{
//add word name then word count to file, then move to next
fprintf(myOutput, "%s %d \n", currword->str, currword->count);
printf("%s ", currword->str);
currword = currword->next;
}
return 0;
}
You sure like making things hard on yourself... Your four biggest issues were (1) not passing the address of mywords to add_words, (2) failing to handle the New/Empty list case in add_words, (3) adding the new nodes to the head of the list, and (4) overwriting your list address every time you called add_word (e.g. mywords = add_words...)
Fixing each of those problems and tidying up parsing a bit, you should be able to find all of your words in your list. Look over/test the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef struct s_words {
char *str; //word
int count; //number of times word occurs
struct s_words *next; //pointer to next word
} words;
words *create_words (char *word)
{
//+allocate space for the structure
printf ("%lu ", strlen (word));
words *newWord = malloc (sizeof (words));
if (NULL != newWord) {
//+allocate space for storing the new word in "str"
//+if str was array of fixed size, storage wud be wasted
newWord->str = (char *) malloc ((strlen (word)) + 1);
strcpy (newWord->str, word); //+copy “word” into newWord->str
newWord->str[strlen (word)] = '\0';
printf (" Create: %s ", newWord->str);
//+initialize count to 1;
newWord->count = 1;
//+initialize next;
newWord->next = NULL;
}
return newWord;
}
words *add_word (words **wordList, char *word)
{
if (!*wordList) { /* handle EMPTY list */
printf ("NEW LIST\n");
return *wordList = create_words (word);
}
words *temp = *wordList;
//+ search if word exists in the list; if so, make found=1
while (temp->next != NULL) { /* iterate while temp->next != NULL */
if (strcmp (temp->str, word) == 0) { //+use strcmp command
temp->count = temp->count + 1; //+increment count;
return *wordList;
}
else
temp = temp->next; //+update temp
}
words *newWord = create_words (word);
if (NULL != newWord) { /* insert at TAIL of list */
temp->next = newWord;
printf (" NEW WORD: %s\n ", newWord->str);
}
return newWord;
}
int main (int argc, char *argv[]) {
words *mywords; //+head of linked list containing words
mywords = NULL;
char *delim = ". ,:;\t\n";
FILE *myFile;
FILE *myOutput;
char *filename = argv[1];
char *outputfile = argv[2];
if (argc != 3) {
fprintf (stderr, "error: insufficient input. usage: %s ifile ofile\n",
argv[0]);
return 1;
}
myFile = fopen (filename, "r"); //+first parameter is input file
if (myFile == 0) {
printf ("file not opened\n");
return 1;
} else {
printf ("file opened \n");
}
//+start reading file character by character;
//+when word has been detected; call the add_word function
int ch = 0, word = 1, k = 0;
char thisword[100];
while ((ch = fgetc (myFile)) != EOF) { /* for each char */
if (strchr (delim, ch)) { /* check if delim */
if (word == 1) { /* if so, terminate word, reset */
word = 0;
thisword[k] = '\0';
printf ("\nadd_word (mywords, %s)\n", thisword);
/* do NOT overwrite list address each time,
* you must send ADDRESS of list to add_word
* to handle EMPTY list case.
*/
if (add_word (&mywords, thisword))
printf (" added: %s\n", mywords->str);
else
fprintf (stderr, "error: add_word failed.\n");
k = 0;
}
}
else { /* if not delim, add char to string, set word 1 */
word = 1;
thisword[k++] = tolower (ch); /* make ch lowercase */
}
}
if (word == 1) { /* handle non-POSIX line-end */
thisword[k] = '\0';
//add thisword into the list
printf ("\nadd_word (mywords, %s) (last)\n", thisword);
if (add_word (&mywords, thisword)) /* same comment as above */
printf (" added: %s\n", mywords->str);
else
fprintf (stderr, "error: add_word failed.\n");
}
words *currword;
printf ("printing list\n");
//+Traverse list and print each word and its count to outputfile
//+output file is second parameter being passed
myOutput = fopen (outputfile, "w+"); //+first parameter is input file
if (myOutput == 0) {
printf ("output file not opened \n");
return 1;
} else {
printf ("output file opened \n");
}
currword = mywords;
while (currword != NULL) { /* just test currword here */
//add word name then word count to file, then move to next
fprintf (myOutput, "%s %d \n", currword->str, currword->count);
printf ("%s ", currword->str);
currword = currword->next;
}
putchar ('\n');
return 0;
}
Input File
$ cat ../dat/captnjack.txt
This is a tale
Of Captain Jack Sparrow
A Pirate So Brave
On the Seven Seas.
Test Use
$ ./bin/llwordcount ../dat/captnjack.txt dat/llout.txt
Output File
$ cat dat/llout.txt
this 1
is 1
a 2
tale 1
of 1
captain 1
jack 1
sparrow 1
pirate 1
so 1
brave 1
on 1
the 1
seven 1
seas 1
note: for printing/output, you simply want while (currword != NULL) to traverse the list.
Now with that said, you should really consider using line-oriented input (fgets or getline) and parsing each line of data into words rather than reading character-by-character and looking for delimiters. It is much easier and less error prone to read/parse a line-at-a-time. Since line-oriented input is buffered, it is also a much faster read. You can read a character at a time, it is just slower and there are a lot more pitfalls along the way.
Digest the changes (commented above with /* ... */) and let me know if you have any questions.
I don't get any error yet when I am trying to get value from array the program fails. The program contains a function to read products from file and store them in array of of type typedef structure item.
This is how the program looks like:
item *displayProducts(int balance){
int row=0;
char line[MAX_LINE_SIZE + 1]; // ptr to the current input line
static item products[8];
FILE *fp;
fp = fopen("machinedata.txt", "r");
if (fp == NULL)
{
printf("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
while (fgets(line, MAX_LINE_SIZE, fp)) {
char *next_ptr = NULL;
char *next_item = strtok_s(line, ",;", &next_ptr);
while (next_item != NULL){
char *item_ptr = NULL;
char *name = strtok_s(next_item, "-", &item_ptr);
if (name == NULL)
{
fprintf(stderr, "Failed to scan name out of [%s]\n", next_item);
break;
}
int price;
next_item = strtok_s(NULL, " ,", &item_ptr);
//assert(next_item != NULL);
if (strcmp(name," ")){
if (sscanf(next_item, "%d", &price) != 1)
fprintf(stderr, "Failed to convert [%s] to integer\n", next_item);
else if (balance > price){
products[row].name = name;
products[row].price = price;
products[row].product_code = row + 1;
printf("%d) %s:%d\n",products[row].product_code, products[row].name, products[row].price);
row++;
}
next_item = strtok_s(NULL, ",;", &next_ptr);
}
}
}
fclose(fp);
return products;
}
void main( int argc, char *argv[]){
int *ptr_to_balance;
int balance = atoi(argv[2]);
ptr_to_balance = &balance;
item *ptr_to_products;
Init(argv[1], balance);
ptr_to_products = displayProducts(balance);
printf("%s", *(ptr_to_products[2].name));
}
the program will print out all of the products from the file but for some reason the last line of the program fails. Any idea why?
I think, you need to change
printf("%s", *(ptr_to_products[2].name));
to
printf("%s", ptr_to_products[2].name);
as %s expects a pointer-to-null-terminated char array.
All the pointers in your products array point into the line array. This has two problems:
This array is local to displayProducts, and it's destroyed when the function returns.
Each element of products is has pointers to the same line array. So when you read a new line from the file, you're overwriting the values that were saved in the previous elements of products.
You need to make a copy of name in the heap before you save it in products[row].
char *name_copy = malloc(strlen(name)+1);
strcpy(name_copy, name);
products[row].name = name_copy;
You also need to fix the printing code, as in the other answer:
printf("%s", ptr_to_products[2].name);
I am trying to write a C program to parse an input file so that individual lines are parsed, and in each line, the individual characters are then parsed further and stored in different variables in a struct. Here is my code so far (I have managed to parse individual characters without considering which line they are on):
/* create struct instances */
/* file open code */
...
int currentChar = fscanf(fp, "%s", storageArray);
while (currentChar != EOF) {
printf("%s\n", storageArray);
currentChar = fscanf(fp, "%s", storageArray);
}
...
/* file close code */
How can I adapt my code so that, instead of having each individual character print to the screen, I get behaviour like the following: (Note: in my program I assume the user input will have three characters to a line.)
INPUT FILE:
a b c
f e d
LINE STRUCT 1:
char1 = a
char2 = b
char3 = c
LINE STRUCT 2:
char1 = f
char2 = e
char3 = d
I feel like the solution might involve nested loops similar to the while I have written, where the outer one keeps track of lines and the inner one keeps track of characters.
Or try this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define READ_OPTIONS "r"
struct line {
char char1;
char char2;
char char3;
struct line* next;
};
struct line* g_lines = NULL;
int main(int argc, char** argv) {
char buf[8] = {0};
struct line* newline, *iter, *head;
int counter = 1;
FILE* fp = fopen("file.txt", READ_OPTIONS);
if(NULL != fp) {
while(fgets(buf, 8, fp)) {
newline = malloc(sizeof(struct line));
if(NULL != newline) {
memset(newline, 0, sizeof(struct line));
sscanf(buf, "%c %c %c",
&newline->char1,
&newline->char2,
&newline->char3);
if(NULL != g_lines) {
for(iter = g_lines;
NULL != iter->next;
iter = iter->next);
iter->next = newline;
} else g_lines = newline;
}
}
fclose(fp);
} else return -1;
/* print the contents */
for(iter = g_lines;
NULL != iter;
iter = iter->next,
++counter)
printf("Line %d: char1=%c char2=%c char3=%c\n",
counter, iter->char1, iter->char2,
iter->char3);
/*
now to free memory before returning
control to the operating system
*/
for(iter = g_lines;
NULL != iter;)
{
head = iter->next;
free(iter);
iter = head;
}
return 0;
}
Try This
int i=1,j-1;
printf("Line STRUCT 1: ");
while( ( ch = fgetc(fp) ) != EOF ){
if(ch=='\n'){
printf("Line STRUCT %d \n",++i);
j=1;
}
printf("Char %d = %c \n",ch,j++);
}
Do this:
for (int i=0; !feof(fp); i++)
fscanf(fp,"%c %c %c ",
&storageArray[i].char1,
&storageArray[i].char2,
&storageArray[i].char3);
I have a text file with data in the form:
Lee AUS 2 103 2 62 TRUE
Check AUS 4 48 0 23 FALSE
Mills AUS 8 236 0 69 FALSE
I need to each line into a struct like, however I'd like to avoid using fixed length arrays (the problem with fgets as far as I can tell):
struct Data
{
char *sname;
char *country;
int *a;
int *b;
int *c;
int *d;
char *hsisno;
};
I am very new to C. Should I use fscanf, or fgets?
fscanf stands for "file scan formatted" and user data is about as unformatted as you can get.
You should never use naked "%s" format strings on data where you don't have absolute control over what can be read.
The best solution is to use fgets to read a line since this allows you to prevent buffer overflow.
Then, once you know the size of your line, that's the maximum size of each string that you will require. Use sscanf to your heart's content to get the actual fields.
One final thing. It's probably a bit wasteful having int* types for the integers, since you know they have a specific maximum size already. I'd use the non-pointer variant, something like:
struct Data {
char *sname; char *country;
int a; int b; int c; int d;
char *hsisno;
};
By way of example, here's some safe code:
#include <stdio.h>
#include <string.h>
// Here's all the stuff for a linked list of your nodes.
typedef struct sData {
char *sname; char *country; char *hsisno;
int a; int b; int c; int d;
struct sData *next;
} Data;
Data *first = NULL; Data *last = NULL;
#define MAXSZ 100
int main (void) {
char line[MAXSZ], sname[MAXSZ], country[MAXSZ], hsisno[MAXSZ];
int a, b, c, d;
FILE *fIn;
Data *node;
// Open the input file.
fIn = fopen ("file.in", "r");
if (fIn == NULL) {
printf ("Cannot open file\n");
return 1;
}
// Process every line.
while (fgets (line, sizeof(line), fIn) != NULL) {
// Check line for various problems (too short, too long).
if (line[0] == '\0') {
printf ("Line too short\n");
return 1;
}
if (line[strlen (line)-1] != '\n') {
printf ("Line starting with '%s' is too long\n", line);
return 1;
}
line[strlen (line)-1] = '\0';
// Scan the individual fields.
if (sscanf (line, "%s %s %d %d %d %d %s",
sname, country, &a, &b, &c, &d, hsisno) != 7)
{
printf ("Line '%s' didn't scan properly\n", line);
return 1;
}
// Allocate a new node to hold data.
node = malloc (sizeof (Data));
if (node == NULL) {
printf ("Ran out of memory\n");
return 1;
}
node->sname = strdup (sname);
node->country = strdup (country);
node->a = a;
node->b = b;
node->c = c;
node->d = d;
node->hsisno = strdup (hsisno);
node->next = NULL;
if (first != NULL) {
last->next = node;
last = node;
} else {
first = node;
last = node;
}
}
fclose (fIn);
// Output the list for debugging.
node = first;
while (node != NULL) {
printf ("'%s' '%s' %d %d %d %d '%s'\n",
node->sname, node->country, node->a, node->b,
node->c, node->d, node->hsisno);
node = node->next;
}
return 0;
}
which reads in your file and stores it in a linked list. It outputs:
'Lee' 'AUS' 2 103 2 62 'TRUE'
'Check' 'AUS' 4 48 0 23 'FALSE'
'Mills' 'AUS' 8 236 0 69 'FALSE'
at the end, as expected.
I've done a whole series of answers on the pitfalls of using *scanf functions on non-controlled data (enter user:14860 fgets into the search box above), some of which (here, here and here, for example) include a perennial favourite function of mine, getLine, for safer user input.