我有一个我实现的链表,适用于各种文件输入(它逐行读取并插入它们。)
void insert_words(FILE* file, node_type* list)
{
char buffer[12];
int length = 0;
while (!feof(file)){
fscanf(file, "%s", buffer);//buffer contains the string/name
length = strlen(buffer);
if (length != 0) {
insert_sorted(list, buffer);
}
} //while
}
鉴于此代码,我发现在读取'fff'之后使用给定的样本输入执行fscanf时出现的问题似乎很糟糕。
one
two
three ee
fff
ee
正在解析ee:
list = 0x009dfac0 {name=0x009dfac0 "one" next=0x00c98c08 {name=0x00c98c08 "three" next=0x00c98ba0 {name=0x00c98ba0 "two" ...} } }
下一个标记后:
list = 0x009dfac0 {name=0x009dfac0 "ee" next=0x009df068 {name=0x009df068 "È”ü\xf\x1" next=0x0ff7caa0 {msvcr110d.dll!_except_handler4(_EXCEPTION_RECORD *, _EXCEPTION_REGISTRATION_RECORD *, _CONTEXT *, void *)} {...} }
检查我的列表时,fscanf被触发后,'next'指针立即被破坏。有什么可能的原因?
根据要求插入排序:
void insert_sorted(node_type* list, char* value)
{
// Copy our pointer so we can move around
node_type *n = (node_type*) malloc(sizeof *n);
node_type *loc = NULL;
node_type *tmp;
node_type dat;
node_type* prev = list;
node_type* head = list;
n->next = NULL;
strcpy(n->name, value);
// First element, assign immediately
if( strcmp(list->name, "") == 0 )
{
*list = *n;
return;
}
while(head != NULL)
{
// We should do a comparison to see if one is greater than another
int cmp_result = strcmp(value, head->name);
// If the value is bigger, this means the value needs to be inserted after
if(cmp_result > 0)
{
loc = head;
}
else if (cmp_result < 0) // this needs to be ahead
{
if(prev == head)
{
dat = *head;
*head = *n;
head->next = &dat;
return;
}
prev->next = n;
n->next = head;
return;
}
else if(cmp_result == 0)
{
free(n);
return; // duplicate, die
}
// Advance to the next pointer
prev = head;
head = head->next;
}
// You've reached the end, that must mean you've succesfully reached the point to insert
tmp = loc->next; // get the value we're going to end up detaching
n->next = tmp; // link the two together
loc->next = n;
}
答案 0 :(得分:2)
将循环修改为
while (fscanf(file, "%s", buffer) == 1) {
length = strlen(buffer);
// ...
}
因为feof(file)
在上次成功0
后仍然返回fscanf()
。在第一个失败后,它返回非0 fscanf()
。
关于insert_sorted()
,请查看以下几行:
head->next = &dat;
return;
由于dat
是本地对象,因此一旦函数返回,保存其地址会导致无效地址。
答案 1 :(得分:1)
您没有正确测试文件结尾。一般来说,使用feof是不正确的,而是测试从文件中读取的函数的返回值。
fscanf返回它能够读取的实体数量。因此,在您的情况下,您将测试它返回1,这表示成功读取。为避免缓冲区溢出,您可以使用%和s之间的数字限制要读取的字符数。
没有理由对你的缓冲区大小这么吝啬。
所以:
void insert_words(FILE* file, node_type* list)
{
char buffer[128];
while (fscanf(file, "%127s", buffer) == 1) {
insert_sorted(list, buffer);
}
}
顺便说一下,你不是“逐行”阅读,而是“用空格分隔的字符串以空格分隔的字符串”。要逐行阅读文件,您可以使用fgets。
在你说“那不是问题”之前,先试试吧。这是这个功能可能产生的唯一问题。