我试图从文本文件中读入链接列表.文本文件具有书籍,作者和年份的标题,以":"分隔.每本书都在一个单独的行上.文本文件条目如下所示:
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)
您的代码现在有多个问题.
第一个(我不是你的孩子)是代码格式和缩进.您粘贴的样本没有常规格式或缩进.即使在诸如此类的短样本中,遵循代码流也更加困难.总是缩进你的代码,并选择一种编码风格(有几种)并坚持下去.
关于代码流,第一个问题是错误检查.即,您检查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,author和year然后指向这个附加存储.这样,您不会在循环的下一次迭代中覆盖其他BookNode的内容.而且您只需要一个free即可释放整个节点.
我可能没有列出你的代码中的所有问题.或许不是另一次重写,你应该首先尝试解决一个较小的子问题,比如stdin从那里读取一个条目并从中构建?
| 归档时间: |
|
| 查看次数: |
2113 次 |
| 最近记录: |