C:将文本读入链表

0 c linked-list fgets

我试图从文本文件中读入链接列表.文本文件具有书籍,作者和年份的标题,以":"分隔.每本书都在一个单独的行上.文本文件条目如下所示:

Absalom, Absalom!:William Faulkner:1936
After Many a Summer Dies the Swan:Aldous Huxley:1939    
Ah, Wilderness!:Eugene O'Neill:1933
Run Code Online (Sandbox Code Playgroud)

我从头开始重写它.评论将不胜感激.

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

struct BookNode
{
    char linebuffer[128];
    char delim[]=":";
    char * Title[50];
    char * Author[50];
    char * Year[5];
    struct BookNode *next;
//    char *token = NULL;
};

int main(void)
{
    static const char booklist[]= "booklist.txt";
FILE *fr=fopen("booklist.txt", "r");
if ( fr != NULL)

{
char Title[50];
char Author[50];
char Year[5]
struct BookNode Booknode;
while (fgets(linebuffer,128, fr) != NULL &&
    sscanf(line, "%49s %49s %4s", 
        &BookNode.Title, BookNode.Author, BookNode.Year)==3)
    {
         printf("%50s %50s %5s", 
                BookNode.Title, BookNode.Author, BookNode.Year);
    }
}
Run Code Online (Sandbox Code Playgroud)

eq-*_*eq- 5

您的代码现在有多个问题.

第一个(我不是你的孩子)是代码格式和缩进.您粘贴的样本没有常规格式或缩进.即使在诸如此类的短样本中,遵循代码流也更加困难.总是缩进你的代码,并选择一种编码风格(有几种)并坚持下去.

关于代码流,第一个问题是错误检查.即,您检查fopen返回状态,但如果打开文件失败,请不要采取足够的操作.

第二个问题是概念问题.您似乎没有意识到N个字符的数组只能容纳长度为N-1的字符串.因此,char[4]几乎不是一种适合将年份存储为字符串的格式.

现在已经解决了这些问题,以下是阻止您的代码在任何情况下工作的实际缺陷:

1)该fgets函数将读取,直到它填充缓冲区或到达行尾或文件结束字符.然而,您仍然需要fgets三次尝试读取文件中的单行条目.你不想做什么.你必须重新思考循环的内容.

2)您的"主要"循环条件可能存在缺陷.这是对使用feof&co的一个非常普遍的误解.假设您的数据文件最后包含一个换行符(并且它只是常规的),您的循环将执行一次太多.

最好像这样构建你的行读取循环:

while (fgets(buffer, BUF_SIZE, stdin)) { /* parse buffer */ }
Run Code Online (Sandbox Code Playgroud)

3)您的代码中存在内存管理的基本问题:即,该函数addEntry无法分配内存来存储您的记录.相反,链接列表中的所有条目最终都将指向您在main函数中分配的相同共享缓冲区.

有几种方法可以解决这个问题.一种是使用多次打电话给malloc你的每个成员BookNode结构(title,author,和year).另一种可能更好的方法是使用可变大小的结构,如下所示:

struct BookNode {
    char *title;
    char *author;
    char *year;
    struct BookNode *next;
    char buffer[]; // this shorthand requires C99
};
Run Code Online (Sandbox Code Playgroud)

对于每个struct BookNode人,在他们之后分配足够的存储空间,以便您可以在那里复制共享缓冲区的内容.title,authoryear然后指向这个附加存储.这样,您不会在循环的下一次迭代中覆盖其他BookNode的内容.而且您只需要一个free即可释放整个节点.

我可能没有列出你的代码中的所有问题.或许不是另一次重写,你应该首先尝试解决一个较小的子问题,比如stdin从那里读取一个条目并从中构建?