Jared Aaron Loo
Jared Aaron Loo

Reputation: 678

C - How to store 2nd column of file in an array?

I have a file which stores data in a comma delimited file (Countries.txt) in the following format (this is just a small sample) :

AD,Andorra,AN,AD,AND,20.00,Andorra la Vella,Europe,Euro,EUR,67627.00
AE,United Arab Emirates,AE,AE,ARE,784.00,Abu Dhabi,Middle East,UAE Dirham,AED,2407460.00
AF,Afghanistan,AF,AF,AFG,4.00,Kabul,Asia,Afghani,AFA,26813057.00
AG,Antigua and Barbuda,AC,AG,ATG,28.00,Saint John's,Central America and the Caribbean,East Caribbean Dollar,XCD,66970.00
AI,Anguilla,AV,AI,AIA,660.00,The Valley,Central America and the Caribbean,East Caribbean Dollar,XCD,12132.00

I want to store the second field of each line such that my array contains only the country names like so:

char *countriesArray[4096];
countriesArray[0] = "Andorra"
countriesArray[1] = "United Arab Emirates"
countriesArray[2] = "Afghanistan"
countriesArray[3] = "Antigua and Barbuda"
countriesArray[4] = "Anguilla"

But each time I run my code, my array doesn't get populated correctly. I'm quite sure the issue doesn't lie with the tokenizing algorithm, as I can display each token properly once I remove the if statement. Here is my code :

FILE * fp;
char * line = NULL;
size_t len = 0;

int count=0;
ssize_t read;
char *countriesArray[4096];

fp = fopen("Countries.txt", "r");
if (fp == NULL)
   exit(EXIT_FAILURE);

   while ((read = getline(&line, &len, fp)) != -1) 
   {
       printf("First while loop iterating");


       printf("%s", line);





       int index=0;
       char * pch;
       pch = strtok (line,",");
       int i;

       for (i=0; i<2; i++)
       {
           printf("Second while loop iterating");
           printf ("\npch is :%s\n",pch);


           if (index == 1)
           {    
               printf ("\nGoing to assign this to countriesArray:%s\n",pch);
               printf ("\nVariable count is:%d\n",count);
               countriesArray[count]=pch;
           }


           pch = strtok (NULL, ",");
           index++;




       }

       count++;


    }

    printf("countriesArray at index 0 is :%s\n", countriesArray[0]);
    printf("countriesArray at index 1 is :%s\n", countriesArray[1]);
    printf("countriesArray at index 2 is :%s\n", countriesArray[2]);
    printf("countriesArray at index 3 is :%s\n", countriesArray[3]);

    int i;
    for (i=0; i<count; i++)
    {
        free (countriesArray[i]);
    }

       if (line)
           free(line);
           exit(EXIT_SUCCESS);

Output :

First while loop iteratingAD,Andorra,AN,AD,AND,20.00,Andorra la Vella,Europe,Euro,EUR,67627.00
Second while loop iterating
pch is :AD
Second while loop iterating
pch is :Andorra

Going to assign this to countriesArray:Andorra

Variable count is:0
First while loop iteratingAE,United Arab Emirates,AE,AE,ARE,784.00,Abu Dhabi,Middle East,UAE Dirham,AED,2407460.00
Second while loop iterating
pch is :AE
Second while loop iterating
pch is :United Arab Emirates

Going to assign this to countriesArray:United Arab Emirates

Variable count is:1
First while loop iteratingAF,Afghanistan,AF,AF,AFG,4.00,Kabul,Asia,Afghani,AFA,26813057.00
Second while loop iterating
pch is :AF
Second while loop iterating
pch is :Afghanistan

Going to assign this to countriesArray:Afghanistan

Variable count is:2
First while loop iteratingAG,Antigua and Barbuda,AC,AG,ATG,28.00,Saint John's,Central America and the Caribbean,East Caribbean Dollar,XCD,66970.00
Second while loop iterating
pch is :AG
Second while loop iterating
pch is :Antigua and Barbuda

Going to assign this to countriesArray:Antigua and Barbuda

Variable count is:3
First while loop iteratingAI,Anguilla,AV,AI,AIA,660.00,The Valley,Central America and the Caribbean,East Caribbean Dollar,XCD,12132.00
Second while loop iterating
pch is :AI
Second while loop iterating
pch is :Anguilla

Going to assign this to countriesArray:Anguilla

Variable count is:4
countriesArray at index 0 is :Anguilla
countriesArray at index 1 is :Anguilla
countriesArray at index 2 is :Anguilla
countriesArray at index 3 is :Anguilla
*** Error in `./chef': free(): invalid pointer: 0x09c1c173 ***
Aborted (core dumped)

I'm really new to C Programming so please give me a chance to learn!

EDIT : I've made some progress(see edited code above), now my variables pch and count are showing correct values inside the if statement. But countriesArray is still not populating properly

Upvotes: 1

Views: 111

Answers (2)

Jared Aaron Loo
Jared Aaron Loo

Reputation: 678

Managed to get it to work, thanks to the recommendation provided by @BLUEPIXY. Turns out all I was missing was strdup

Code :

FILE * fp;
char * line = NULL;
size_t len = 0;

int count=0;
ssize_t read;


fp = fopen("Countries.txt", "r");
if (fp == NULL)
    exit(EXIT_FAILURE);

       while ((read = getline(&line, &len, fp)) != -1) 
       {

           int index=0;
           char * pch;
           pch = strtok (line,",");
           int i;

           for (i=0; i<2; i++)
           {



              if (index == 1)
              { 
                    countriesArray[count]=strdup(pch);
              }


              pch = strtok (NULL, ",");
              index++;




           }

       count++;


       }





 if (line)
    free(line);

Upvotes: 0

Serge Ballesta
Serge Ballesta

Reputation: 148890

You use repetedly getline which allocates a buffer for line, and only free one line at the end. For any serious program, it leads to what is called memory leak : you allocate a piece of memory and loose the pointer that could allow to free it. You should have a char *lines[4096] array to keep all those lines to be able to correctly free them at the end.

char *lines[4096];
while ((read = getline(&line, &len, fp)) != -1) 
{
    lines[count] = line;

and at end of program :

for(int i=0; i<count; i++) {
    free(lines[i];
}

(only that ; do not try to free countriesArray elements as thay are just pointers inside allocated elements, the allocated elements are in lines)

But at least, all your countriesArray elements point to different memory places.

The real problem in this code is that you set index to 0 outside of first loop, like count. That's correct for count but index must be reset to 0 on each iteration of first loop.

Upvotes: 2

Related Questions