Thread: Reading data from a file and adding them to a list

  1. #1
    Registered User
    Join Date
    Jun 2014
    Posts
    1

    Reading data from a file and adding them to a list

    Hello everyone! I've been trying to write my homework assignment (a list of countries, their codes and their capitals) and I've done most of it but I'm stuck at this: I have to open a file, read it and if there are data, add them to the list. So far I've created an element of the structure, queue list, printed the list on the screen and freed the memory. I thought that for reading the file and adding the data I could first open the file (of course) with fopen and after that use a for loop (i=0;i=!EOF;i++) to scan the whole file and fscanf(fp,"%s",result->country),etc in the loop to add the data to the structure of the element and finally insert that element to the queue list. However, when I try to do these operations, I only get to writing the name of the file and the program crashes. Can you help me figure out what I'm doing wrong?
    Here's my code (I've copied it without the function for reading though)

    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
     
    struct List 
    {
          char country[20]; 
          char code[5]; 
          char capital[20]; 
          struct List*next; 
    };
    typedef struct List LIST; 
     
    LIST *head; 
    LIST *current; 
     
    LIST *new_item();
    LIST *create_queue_list(int size);
    void find_item_cap(LIST *head,char *criteriaCap);
    void find_item_country(LIST *head,char *criteriaCountry);
    void print(LIST *head);
    void free_list(LIST *head);
     
    int main()
    {
          LIST *head=NULL;
          int size;
          char criteriaCap[20];
          char criteriaCountry[20];
     
          printf("How many countries? ");
          scanf("%d",&size);
          head=create_queue_list(size);
     
          printf("\nList is: \n");
          print(head);
     
          printf("\nEnter the capital: ");
          fflush(stdin);
          gets(criteriaCap);
          find_item_cap(head,criteriaCap);
     
          printf("\nEnter the country: ");
          fflush(stdin);
          gets(criteriaCountry);
          find_item_country(head,criteriaCountry);
     
          free_list(head);
          return 0;
    }
    LIST *new_item() 
    {
          LIST *result=NULL;
          char country[20];
          char code[5];
          char capital[20];
     
          result=(LIST*)malloc(sizeof(LIST)); 
          if(result==NULL)
          {
                printf("\nNot enough memory."); 
          }
          else
          {
                printf("\nEnter the country: ");
                fflush(stdin);
                gets(country);
                printf("Enter the country's code: ");
                fflush(stdin);
                gets(code);
                printf("Enter the country's capital: ");
                fflush(stdin);
                gets(capital);
                strcpy(result->country,country);
                strcpy(result->code,code);
                strcpy(result->capital,capital);
                result->next=NULL;
          }
          return result;
    }
    LIST *create_queue_list(int size)
    {
          LIST *res_root=NULL;
          LIST *end_item=NULL;
          int i;
         
          for(i=0;i<size;i++)
          {
                if(res_root==NULL)
                {
                      res_root=new_item();
                      end_item=res_root;
                }
                else
                {
                      end_item->next=new_item();
                      end_item=end_item->next;
                }
          }
          return res_root;
    }
    void find_item_cap(LIST *head,char *criteriaCap)
    {
          LIST *curr_item=head;
     
          while(curr_item!=NULL)
          {
                if(strcmp(curr_item->capital,criteriaCap)==0)
                {
                      printf("%s is %s's capital.\n",criteriaCap,curr_item->country);
                }
                curr_item=curr_item->next;
          }
    }
    void find_item_country(LIST *head,char *criteriaCountry)
    {
          LIST *curr_item=head;
     
          while(curr_item!=NULL)
          {
                if(strcmp(curr_item->country,criteriaCountry)==0)
                {
                      printf("%s's capital is %s.\n",criteriaCountry,curr_item->capital);
                }
                curr_item=curr_item->next;
          }
    }
     
    void print(LIST *head)
    {
          LIST *curr_item=head;
     
          while(curr_item!=NULL)
          {
                printf("%s   %s   %s\n",curr_item->code,curr_item->country,curr_item->capital);
                curr_item=curr_item->next;
          }
    }
    void free_list(LIST *head)
    {
          LIST *curr_item=head;
         
          while(head!=NULL)
          {
                head=head->next;
                free(curr_item);
                curr_item=head;
          }
    }

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    The first thing to do is to stop declaring global variables: head should probably be declared within the main function, and current should be declared in each function that needs it.

    I suggest that instead of:
    Code:
    struct List
    {
        char country[20];
        char code[5];
        char capital[20];
        struct List*next;
    };
    typedef struct List LIST;
    You declare:
    Code:
    struct CountryNode_
    {
        char name[20];
        char code[5];
        char capital[20];
        struct CountryNode_ *next;
    };
    typedef struct CountryNode_ CountryNode;
    
    typedef struct
    {
        CountryNode *head;
    } CountryList;
    This way, you distinguish between the concept of a node in a linked list and the linked list itself (and now it is easier if you want to add a tail pointer for the linked list, which seems to be the case as I see end_item). Furthermore, I have chosen to use the name List rather than LIST because fully capitalised names are conventionally used for macro names and constants. Of course, when you do this, you should then rename head to list (or a more descriptive name like countries or country_list).

    Note that fflush(stdin) results in undefined behaviour and gets is vulnerable to buffer overflow. For now, assume that the user will not enter more characters than there is space (the assumption that you are making with gets anyway), and then use fgets without fflush(stdin). Later, you can change the code to handle a situation where the user enters more input than can be stored.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Reading Data From File to Linked List
    By jeanermand in forum C Programming
    Replies: 5
    Last Post: 12-04-2011, 04:08 PM
  2. Adding data to existing data in an input file?
    By matthayzon89 in forum C Programming
    Replies: 4
    Last Post: 11-20-2010, 11:23 PM
  3. Adding data from linked list to string
    By Panserbjorn in forum C Programming
    Replies: 2
    Last Post: 10-28-2007, 04:15 PM
  4. reading data from a file - link list
    By peter_hii in forum C++ Programming
    Replies: 7
    Last Post: 10-25-2006, 09:11 AM
  5. Adding data to list boxes
    By Bazz in forum Windows Programming
    Replies: 1
    Last Post: 10-15-2001, 06:35 AM