我试图从一个文本文件读入一个链接列表。文本文件的书名、作者和年份用“:”分隔。每本书都在一个单独的行上。文本文件条目如下所示:
Absalom, Absalom!:William Faulkner:1936
After Many a Summer Dies the Swan:Aldous Huxley:1939
Ah, Wilderness!:Eugene O'Neill:1933
我从头开始重写。如有意见,将不胜感激。
#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);
}
}
最佳答案
你的代码现在有很多问题。
第一个(我没骗你)是代码格式化和缩进。粘贴的示例没有常规格式或缩进。即使在这样的短示例中,也很难遵循代码流。总是缩进你的代码,选择一个编码风格(有几个)并坚持它。
关于代码流,第一个问题是错误检查。即,检查fopen
返回状态,但如果打开文件失败,则不采取足够的操作。
第二个问题是概念问题。你似乎没有意识到N个字符的数组只能容纳长度为N-1的字符串。因此,char[4]
几乎不适合作为字符串存储年份。
既然已经解决了这些问题,下面是在任何情况下都会阻止代码工作的实际缺陷:
1)函数将一直读取,直到它填满缓冲区或到达行尾或文件尾字符为止。然而,您仍然需要调用fgets
三次来尝试读取文件中的一行条目。你不太可能想做什么。你必须重新考虑你的循环内容。
2)您的“主”回路状态可能有缺陷。对于fgets
&co的使用,这是一个非常常见的误解。假设您的数据文件在结尾处包含一个换行符(并且只有这样做才是正常的),那么您的循环将执行过多的一次。
最好这样构造读线循环:
while (fgets(buffer, BUF_SIZE, stdin)) { /* parse buffer */ }
3)代码中的内存管理存在基本问题:即函数
feof
无法分配内存来存储记录。相反,链接列表中的所有条目将指向在addEntry
函数中分配的相同共享缓冲区。有几种方法可以解决这个问题。一种是为
main
结构的每个成员(malloc
、BookNode
和title
)使用多个对author
的调用。另一种可能更可取的方法是使用可变大小的结构,例如:struct BookNode {
char *title;
char *author;
char *year;
struct BookNode *next;
char buffer[]; // this shorthand requires C99
};
为每个
year
分配足够的存储空间,以便可以在其中复制共享缓冲区的内容。struct BookNode
、title
和author
然后指向此附加存储。这样就不会在循环的下一次迭代中覆盖其他BookNodes的内容。只需要一个year
就可以释放整个节点。我可能没有在这里列出你代码中的所有问题。也许您应该首先尝试处理一个较小的子问题,比如从
free
读取一个条目并从中构建,而不是另一个重写?关于c - C:将文字读入链表,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10870235/