Previously stored strings are overwritten by fgets

泄露秘密 提交于 2019-12-25 17:16:03

问题


I'm reading records from a CSV file using fgets() to read the file one line at a time, and strtok() to parse the fields in each line. I'm encountering a problem where fgets() overwrites a string that was previously written, in favor of the new string.
Here's an example of what I mean by that:

record.csv (This is the file I'm reading in)

John,18
Johann,29

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct customer {
    char *name;
    int age;
} Customer;

int main(void) 
{
    FILE *csv_data;
    char line[100], *token;
    Customer newData[2];

    csv_data = fopen("record.csv", "r");
    // Index 0 for John's data, index 1 for Johann's data
    int i = 0;

    /* loops until end of file */
    while(fgets(line, 100, csv_data)) {

        /* name field */
        token = strtok(line, ",");
        if (token != NULL) {
            newData[i].name = token;        
        }

        /* age field */
        token = strtok(NULL, ",");
        if (token != NULL) {
            // atoi() converts ascii char to integer
            newData[i].age = atoi(token);
        }
        i++;
    }
    /* print John's records */
    printf("%s\n", newData[0].name);
    printf("%d\n", newData[0].age);

    /* print Johann's records */
    printf("%s\n", newData[1].name);
    printf("%d\n", newData[1].age);

    return 0;
}


When we compile and execute this, it prints out:

Johann
18
Johann 
29

"John" in newData[0].name gets overwritten with "Johann" during the second iteration of the while loop. Notice however that only the strings get mixed up, but not the integers. I suspect this has to do with fgets because when I modified the above source to only run fgets once, the output for "John" was as it should be.
Maybe I'm misusing fgets (or perhaps my assumption is wrong), but could someone give me some pointers on why the strings are being overwritten with each calls to fgets?

Second Update: Thank-you very much again to all the commenters and the answerers. Good to know those things which I was not aware of. The source works perfect now.


回答1:


You are not copy the string but the pointer to the string.

A very simple way to copy the string, but note that this limit the size of the string at 99 characters.

typedef struct customer {
    char name[100];
    int age;
} Customer;

strcpy(newData[i].name, token);   



回答2:


Do:

newData[i].name = malloc( strlen( token ) + 1 );
strcpy( newData[i].name, token );

or define name member as char name[64]; and then again strcpy( newData[i].name, token ); without malloc. The 64 bytes for name can be more or less.



来源:https://stackoverflow.com/questions/44790786/previously-stored-strings-are-overwritten-by-fgets

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!