int main(){
FILE *file;
char line[100];
char name[26],code[4],donator[10],shipment[10], quantity[10];
int count = 0;
file = fopen("donation.txt","r");
if(!file){
printf("File does not exist!");
return 1;
}
while (!feof(file)){
fgets(line,100,file);
count ;
}
char *list[count][5];
memset(list,0,sizeof(list));
fseek(file,0,SEEK_SET);
count=0;
int count2=0;
char dtm[sizeof(line)];
while (!feof(file)){
fgets(line,100,file);
if (count>0){
strcpy(dtm,line);
printf("%s",dtm);
count2=0;
for(char *p = strtok(dtm,"|");p ; p=strtok(NULL,"|")){
printf("\n %d %s",count2,p);
list[count-1][count2]=p;
printf("\n%s",list1[count-1][count2]);
count2 ;
}
}
count ;
}
for(int i =0; i<count-1 ;i ){
for(int k=0;k<count2;k )
printf("\n%d %d %s",i,k,list[i][k]);
}
fclose(file);
return 0;
}
.
Contactless Thermommeter | CT | Japan | 1 | 1
Hand Sanitizer | HS | USA | 1 | 1
Face Mask | FM | China | 1 | 1
Surgical Mask | SM | China | 1 | 1
Oxygen Mask | OM | Saudi Arabia | 1 | 1
for loop's expected output snippet:
0 0 Contactless Thermometer<br/>
0 1 CT<br/>
0 2 Japan<br/>
0 3 1<br/>
0 4 1<br/>
1 0 Hand Sanitizer<br/>
1 1 HS<br/>
1 2 USA<br/>
1 3 1<br/>
1 4 1<br/>
for loop's output snippet:
0 0 Oxygen Mask<br/>
0 1 OM<br/>
0 2 Saudi Arabia<br/>
0 3 1<br/>
0 4 1<br/>
1 0 Oxygen Mask<br/>
1 1 OM<br/>
1 2 Saudi Arabia<br/>
1 3 1<br/>
1 4 1<br/>
I just started C after learning Python in my pre-U and I am very grateful if anyone here can guide me on what went wrong with my code. In the file reading process, I used strtok to break down the lines in the txt file and store in list[i][k]
, as shown in How to store tokens(strtok) in a pointer on an array. It shows the intended value but in the next for loop, list[i][k]
only showed the last set of values as the picture below.
CodePudding user response:
Ok, the code is a bit messy, you simply want to map your file in a 2D array.
There are several troubles :
if (count>0){
Why ? You want to have every lines in your array, don't skip the first one.
list[count-1][count2]=p;
Skip the -1. It has nothing to do there.
list[count-1][count2]=p;
Yes, two problems in the same line.
You assign in your array a pointer on a string that will change. And pointer aliasing. strtok returns a pointer to the actual string. It does not reallocate memory.
The solution is simply to strdup your string, so it has a fresh new memory that is not going to be changed on the next loop cycle.
list[count][count2] = strdup(p);
Don't forget to free that later. Don't forget to check if your strdup did not fail :)
Other notes : You have unused variables. The newline remains in the string, in the last token. You may want to remove that.
CodePudding user response:
strtok()
returns a pointer into the original array, this array will be overwritten by the next call to fgets()
so you should allocate a copy of the string. You can use strdup()
for that:
list[count][count2] = strdup(p);
Also note that while (!feof(file))
is not a reliable way to test if another line is available from the file. You should just call fgets()
and check the return value:
while (fgets(line, 100, file)) { ...
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
FILE *file;
char line[100];
char name[26], code[4], donator[10], shipment[10], quantity[10];
int count = 0;
file = fopen("donation.txt", "r");
if (!file) {
printf("File does not exist!");
return 1;
}
/* count the number of lines */
while (fgets(line, sizeof line, file)) {
count ;
}
/* allocate the 2D array of tokens and the per line token counts 8/
char *list[count][5];
int listlen[count];
/* restart parsing at the beginning of the file */
fseek(file, 0, SEEK_SET);
count = 0;
while (fgets(line, sizeof line, file)) {
count2 = 0;
/* split the line on |, also stripping the trailing newline
* note however that strtok() does not allow for empty tokens */
for (char *p = strtok(line, "|\n"); count2 < 5 && p != NULL; p = strtok(NULL, "|\n")) {
list[count][count2] = strdup(p);
count2 ;
}
listlen[count] = count2;
count ;
}
for (int i = 0; i < count; i ) {
for (int k = 0; k < listlen[count]; k )
printf("%d %d %s\n", i, k, list[i][k]);
}
fclose(file);
return 0;
}