我是一个C语言的初学者,所以我知道我的代码可能看起来像垃圾。我想做的就是用一个结构体做一个链表,这个结构体包含一个字符数组和int
作为频率。它从测试文件中读取行并简单地打印出文件。它正确地读取文件,第一次遍历链表并正确地打印出来。然而,在链表的第二次迭代中,它打印出正确的行数和正确的整数,但单词被符号取代。我到处都找过了,我只是需要一些帮助。这是我的代码。
#include <stdio.h>
#include <stdlib.h>
#define Word_MAX_LENGTH 255
struct WordFreq
{
char word[Word_MAX_LENGTH];
int frequency;
struct WordFreq *next;
} WordFreq;
struct WordFreq *head = NULL;
void insert(struct WordFreq *newNode)
{
if (head == NULL)
{
head = newNode;
newNode->next = NULL;
return;
}
struct WordFreq *current = head;
while (current->next != NULL)
{
current = current->next;
}
current->next = newNode;
newNode->next = NULL;
}
void main(int argc, char *argv[])
{
if (argc != 2)
{
printf("Please run as %s [filename]\n", argv[0]);
return;
}
FILE *f;
f = fopen(argv[1], "r");
if (f == NULL)
{
printf("File (%s) does not exist\n", argv[1]);
return;
}
struct WordFreq *line = malloc(sizeof(struct WordFreq));
if (line == NULL)
{
printf("Cannot do dynamic memory managment\n");
return;
}
printf("File content in %s:\n", argv[1]);
while (fscanf(f, "%s %d", line->word, &(line->frequency)) != EOF)
{
printf("%s %d\n", line->word, line->frequency);
insert(line);
line = malloc(sizeof(struct WordFreq));
if (line == NULL)
{
printf("Cannot do dynamic memory management");
return;
}
}
fclose(f);
// To keep head intact for sorting portion
struct WordFreq *current = head;
printf("\nContent of linked list:\n");
while (current != NULL)
{
printf("%s %d\n", current->word, current->frequency);
struct WordFreq *temp = current;
current = current->next;
free(temp);
}
printf("\n\n\n");
current = head;
while (current != NULL)
{
printf("%s %d\n", current->word, current->frequency);
current = current->next;
}
free(current);
free(line);
}
非常感谢任何帮助。很遗憾,我已经编程了一段时间,但我想学习C,因为我想了解程序为什么要做它们所做的事情,以帮助未来的努力。
1条答案
按热度按时间wpx232ag1#
在第一次迭代中释放了链表,所以第二次迭代具有未定义的行为,因为
head
已成为无效指针,并且列表节点的内存内容已更改。从它们阅读具有未定义的行为,任何事情都可能发生,包括程序因无效的内存访问或随机输出而停止。你应该写函数:一个用于打印列表内容,另一个用于释放列表。将这些操作组合在一起会造成混乱,并导致像下面这样的逻辑错误。
还要注意这些备注:
main
的返回类型是int
。修改return
语句,在错误时返回1
,在成功时返回0
,即:正常运行。printf("File (%s) does not exist\n", argv[1])
可能不是正确的诊断:该文件可能存在,但fopen
将失败,如果该进程没有适当的访问权限。您可以使用errno
并输出相应的错误消息:fscanf(f, "%s %d", line->word, &(line->frequency)) != EOF
,您应该在执行以下两种转换时测试fscanf()
是否成功:它应该返回2
。更好的是:使用fgets
一次读取一行输入,然后使用sscanf()
转换行内容,并使用包含违规输入行的显式消息报告转换错误。head
被释放两次:free(current)
在结束时必须删除。以下是修改后的版本: