将CSV文件读入结构体数组

3
我开始学习C语言编程,我的代码如下:

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

#define MAX_STR_LEN 256
#define MAX_BOOKS 256

struct book{
    int ID;
    char *name;
    char *dateIn;
    char *dateOut;
};

struct book books[MAX_BOOKS];

/* PROTOTYPE OF FUNCTIONS */
int readBookFile();
void printBookList();


int main(int argc, char **argv)
{   
    int isOK = 0;

    isOK = readBookFile();

    printBookList();

    system("pause");
    return 0;
}

int readBookFile()
{
    /* FileStream for the Library File */
    FILE *bookFile;

    /* allocation of the buffer for every line in the File */
    char *buf = malloc(MAX_STR_LEN);
    char *tmp; 

    /* if the space could not be allocaed, return an error */
    if (buf == NULL) {
        printf ("No memory\n");
        return 1;
    }

    if ( ( bookFile = fopen( "library.dat", "r" ) ) == NULL ) //Reading a file
    {
        printf( "File could not be opened.\n" );
    }

    int i = 0;
    while (fgets(buf, 255, bookFile) != NULL)
    {
        if ((strlen(buf)>0) && (buf[strlen (buf) - 1] == '\n'))
            buf[strlen (buf) - 1] = '\0';       

        tmp = strtok(buf, ";");
        books[i].ID = atoi(tmp);

        tmp = strtok(NULL, ";");
        books[i].name = tmp;

        tmp = strtok(NULL, ";");
        books[i].dateIn = tmp;

        tmp = strtok(NULL, ";");
        books[i].dateOut = tmp;

        //tempBook.ID = atoi(buf);
        printf("index i= %i  ID: %i, %s, %s, %s \n",i, books[i].ID , books[i].name, books[i].dateIn , books[i].dateOut);

        i++;
    }
    //free(buf);
    fclose(bookFile);
    return 0;
}

void printBookList()
{

    int i;
    //i = sizeof(books) / sizeof(books[0]);
    //printf ("%i \n", i);


    for (i = 0; i <= sizeof(books); i++)
    {
        if (books[i].ID != 0)
        printf("index i= %i  ID: %i, %s, %s, %s \n",i, books[i].ID , books[i].name, books[i].dateIn , books[i].dateOut);
        else
            break;
    }

}

问题是,在readBookFile()结束后,我的结构体数组中充满了输入文件的最后一个值。

我的输入文件是:

1;das erste Buch; 12122013; 13122013
2;das Zweite Buch; 12122013; 13122013
3;das dritte Buch; 12122013; 13122013
4;das vierte Buch; 12122013; 13122013
5;das fünfte Buch; 12122013; 13122013
6;das sechste Buch; 12122013; 13122013

在readBookFile函数中,printf返回了正确的值,但在printBooksList()函数中,所有的值似乎都变成了输入文件的最后一行。 我的控制台输出 有人能解释一下这是为什么,并可能指引我正确的方向吗?
非常感谢 Hagbart
3个回答

3
问题出在你的结构体:
struct book{
    int ID;
    char *name;
    char *dateIn;
    char *dateOut;
};

name、dateIn和dateOut是“指针”,它们只是指向某些东西,你不需要为它们分配空间。
你所做的只是将它们指向 tmp(buf)

因此,在printBookList()函数中,你只是打印相同的字符串块,而ID是正常的,因为它不是指针。

为了解决这个问题,你需要为它们分配空间,你可以使用strdup()函数,但一定要释放它们。


1
在 while 循环中:
while (fgets(buf, 255, bookFile) != NULL)

你正在将文件中的新内容复制到缓冲区的内存位置。由于 tmp 指向缓冲区中的某个位置,因此它的内容也被替换了。
 tmp = strtok(NULL, ";");
 books[i].name = tmp;

你应该为数组中的每个结构分配内存,然后使用strcpy。
你可以在这里找到关于strcpy和strdup之间的区别的解释:strcpy vs strdup

0

原因是在类似于这样的编程中

books[i].name = tmp;

你实际上并没有将字符串从tmp复制到books[i].name中:你只是让它们都指向同一个位置——在buf缓冲区的某个地方。

尝试使用strdup,例如:

books[i].name = strdup(tmp);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接