Reputation: 678
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
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
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