提问人:dirthogger 提问时间:9/28/2023 最后编辑:chqrliedirthogger 更新时间:9/28/2023 访问量:78
链表在第二次迭代期间打印符号而不是单词
Linked List prints symbols instead of words during second iteration
问:
我是 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,因为我想了解为什么程序会做他们所做的事情来帮助未来的努力。
答:
在第一次迭代期间释放了链表,因此第二次迭代具有未定义的行为,因为该指针已成为无效指针,并且列表节点的内存内容已更改。从它们读取具有未定义的行为,任何事情都可能发生,包括程序因无效的内存访问而停止或您观察到的随机输出。head
您应该编写函数:一个用于打印列表内容,另一个用于释放列表。将这些操作组合在一起会造成混淆,并导致诸如此类的逻辑错误。
另请注意以下备注:
的返回类型为 。修改语句,在错误和成功时返回,即:正常操作。
main
int
return
1
0
printf("File (%s) does not exist\n", argv[1])
可能不是正确的诊断:文件可能存在,但如果进程没有适当的访问权限,则文件将失败。您可以使用并输出相应的错误消息:fopen
errno
#include <errno.h> #include <string.h> [...] if (f == NULL) { fprintf(stderr, "cannot open %s: %s\n", argv[1], strerror(errno)); return 1; }
而不是您应该测试执行两个转换是否成功:它应该返回 .更好的是:一次读取一行输入,并用于转换行内容,并使用包含违规输入行的显式消息报告转换错误。
fscanf(f, "%s %d", line->word, &(line->frequency)) != EOF
fscanf()
2
fgets
sscanf()
head
被释放两次:最后必须删除。free(current)
这是修改后的版本:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.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;
} else {
struct WordFreq *current = head;
while (current->next != NULL) {
current = current->next;
}
current->next = newNode;
}
newNode->next = NULL;
}
void print_list(const struct WordFreq *node) {
while (node != NULL) {
printf("%s %d\n", node->word, node->frequency);
node = node->next;
}
}
void free_list(struct WordFreq *node) {
while (node != NULL) {
struct WordFreq *temp = node;
node = node->next;
free(temp);
}
}
int main(int argc, char *argv[]) {
char line[WORD_MAX_LENGTH + 20];
if (argc != 2) {
fprintf(stderr, "Please run as %s [filename]\n", argv[0]);
return 1;
}
FILE *f = fopen(argv[1], "r");
if (f == NULL) {
fprintf(stderr, "Cannot open %s: %s\n", argv[1], strerror(errno));
return 1;
}
printf("File content in %s:\n", argv[1]);
while (fgets(line, sizeof line, f)) {
struct WordFreq *node = malloc(sizeof(*node));
if (node == NULL) {
fprintf(stderr, "Cannot allocate node for %s\n", line);
fclose(f);
return 1;
}
if (sscanf(line, "%254s %d", node->word, &node->frequency) == 2) {
printf("%s %d\n", node->word, node->frequency);
insert(node);
} else {
fprintf(stderr, "invalid line: %s\n", line);
free(node);
}
}
fclose(f);
printf("\nContent of linked list:\n");
print_list(head);
// ...
free_list(head);
return 0;
}
评论
head
next
word
free
评论
free
free