程序规范非常简单,只需读取单词的输入文件并创建一个链表,其中每个节点都包含整个字符串。
这是我的节点结构:
typedef struct wordNode{
char *word;
token_type type;
struct wordNode *next;
} wordNode;
令牌类型将在我完成 LL 基础知识工作后发挥作用。
main 的一般过程是打开输入文件,用第一个单词设置 head,然后使用第二个节点指针"current"遍历输入文件的其余部分。然后,使用打印列表功能从头部指针打印列表。
void printList(wordNode *head)
{
while(head != NULL)
{
printf("%s ", head->word);
head = head->next;
}
}
int main()
{
//Open input file
FILE *input = fopen("input.txt", "r");
char nextWord[12] = "";
//Scan in first word for head node
fscanf(input, "%s", nextWord);
//create head, fill it in with the first word, and create current
wordNode *head = malloc(sizeof(wordNode));
head->next = malloc(sizeof(wordNode));
head->word = nextWord;
printf("%s ", head->word);
wordNode *current = head->next;
//Begin Iteration
while(fscanf(input, "%s", nextWord) != EOF)
{
current = (wordNode*)malloc(sizeof(wordNode));
current->word = nextWord;
current->next = NULL;
printf("%s ", current->word);
current = current->next;
}
printList(head);
}
main 中的那些 printfs 一起会给我我想要的输出,所以字符串似乎在迭代过程中被正确保存,但是 printList 函数给出的输出是列表中最后一个单词重复了几次,后跟垃圾值。
我认为头部以某种方式与当前绑定,并且在迭代过程中不会停留在列表的开头,但我不确定它如何或为什么移动。
另外,我应该使用 strcpy 将字符串保存到节点吗?我之前尝试过,但当我尝试时它会导致崩溃。
nextWord
应该是一个更大的数组(例如 nextWord[200]
),或者您应该限制fscanf
存储的字符数,例如
fscanf(input, "%11s", nextWord);
或者使用更大的数组并限制字符数。
您需要在将每个字符串读入 nextWord
数组后创建其副本。代码当前只是将nextWord
数组的地址分配给每个word
指针。因此,链表中的每个节点都指向相同的字符串,这将是从文件中读取的最后一个字符串。要复制字符串,您需要分配内存,然后strcpy
.strdup
功能将为您执行此操作,但并非所有系统都支持strdup
。
当代码创建head
时,它会为两个结构分配内存。相反,它应该为一个结构分配内存,并将head->next
设置为 NULL。
变量current
一团糟,例如,您设置current->next = NULL
,两行后设置current = current->next
。为了使代码正常工作,您需要两个变量,我将它们称为tail
和current
。 tail
应指向链表中的最后一个节点。所以最初,tail
指向head
.创建新节点时,代码应如下所示
current = (wordNode*)malloc(sizeof(wordNode));
current->word = strdup( nextWord );
current->next = NULL;
tail->next = current;
tail = current;
另外,不要检查fscanf
是否有EOF
。相反,请检查fscanf
是否返回预期的转化次数。原因是,如果在到达文件末尾之前转换失败,fscanf
可能会陷入无限循环。所以while
循环应该是
while(fscanf(input, "%11s", nextWord) == 1)
您需要为 char *
分配内存:
int main()
{
//Open input file
FILE *input = fopen("input.txt", "r");
char nextWord[12] = "";
//Scan in first word for head node
fscanf(input, "%s", nextWord);
//create head, fill it in with the first word, and create current
wordNode *head = malloc(sizeof(wordNode));
head->next = malloc(sizeof(wordNode));
head->word = (char *)calloc(strlen(nextWord) + 1);
strcpy(head->word, nextWord);
printf("%s ", head->word);
wordNode *current = head->next;
//Begin Iteration
while(fscanf(input, "%s", nextWord) != EOF)
{
current = (wordNode*)malloc(sizeof(wordNode));
current->word = (char *)calloc(strlen(nextWord) + 1);
strcpy(current->word, nextWord);
current->next = NULL;
printf("%s ", current->word);
current = current->next;
}
printList(head);
}
因为您没有保存输入。只有他们的地址保存在链表中。
当您断言时head->word = nextWord
作为本地 aray 正在分配的nextWord
的地址。
您需要在结构中留出足够的空间,例如char Word[SIZE]
或使用动态分配char *Word = malloc( SIZE )
并且应该使用 strcpy 来复制输入。
head->word = malloc(SIZE);
strcpy(heap->word, nextWord);
还有一个小错误
wordNode *head = malloc(sizeof(wordNode));
head->next = malloc(sizeof(wordNode)); /* (1) Allocated */
head->word = nextWord;
printf("%s ", head->word);
wordNode *current = head->next; /* current points allocated memory (1) */
//Begin Iteration
while(fscanf(input, "%s", nextWord) != EOF)
{
current = (wordNode*)malloc(sizeof(wordNode)); /*re-allocation
and (1) is allocated but not used memory you can not access it anymore*/
current->word = nextWord;
current->next = NULL;
printf("%s ", current->word);
current = current->next;
}
printList(head);
}