struct data {
int date;
int temperature;
char day[11];
struct data *next;
};
typedef struct data Data;
int from_file_to_list(File *fp, Data **list) {
Data *p;
int cnt = 0;
*list = p;
p = malloc(sizeof(Data));
while (fscanf(fp, "%d" "%s" "%d", &(p->date), p->day, &(p->temperature)) == 3) {
p->next = malloc(sizeof(Data));
p = p->next;
cnt++;
}
return cnt;
}
我有一个函数,它用文本文件的数据创建一个链接列表,它返回列表中的链接数量,它工作得很好,但它在最后为一个额外的空链接分配内存,有什么方法可以阻止这种情况吗?因为如果我有一个函数,在最后添加一个链接,可能会有问题,对吧?
对于初学者来说,似乎有一个打字错误
int from_file_to_list(File *fp, Data **list) {
^^^^
应该有
int from_file_to_list(FILE *fp, Data **list) {
^^^^
我有一个函数,它用文本文件,它返回列表中的链接数,并且它工作罚款,
你错了。函数具有未定义的行为。在本声明中,
int from_file_to_list(File *fp, Data **list) {
Data *p;
int cnt = 0;
*list = p;
//..
将未初始化的指针CCD_ 1分配给指针*list
。也就是说,在退出函数之后,main中的指针list
将具有这个不确定的值。
该功能可以定义,例如至少以下方式
#include <stdlib.h>
#include <string.h>
//...
size_t from_file_to_list( FILE *fp, Data **list )
{
size_t cnt = 0;
int date;
int temperature;
char day[11];
while ( fscanf( fp, "%d" "%s" "%d", &date, day, &temperature ) == 3 &&
( *list = malloc( sizeof( Data ) ) ) != NULL )
{
( *list )->date = date;
( *list )->temperature = temperature;
strcpy( ( *list )->day, day );
( *list )->next = NULL;
list = &( *list )->next;
++cnt;
}
return cnt;
}
或者,在从文件创建新列表之前,最好先释放列表
size_t from_file_to_list( FILE *fp, Data **list )
{
while ( *list )
{
Data *tmp = *list;
*list = ( *list )->next;
free( tmp );
}
size_t cnt = 0;
int date;
int temperature;
char day[11];
while ( fscanf( fp, "%d" "%s" "%d", &date, day, &temperature ) == 3 &&
( *list = malloc( sizeof( Data ) ) ) != NULL )
{
( *list )->date = date;
( *list )->temperature = temperature;
strcpy( ( *list )->day, day );
( *list )->next = NULL;
list = &( *list )->next;
++cnt;
}
return cnt;
}
如果你要写一个单独的函数来清除像这样的列表
void clear( Data **list )
{
while ( *list )
{
Data *tmp = *list;
*list = ( *list )->next;
free( tmp );
}
}
那么上面的函数可以像一样编写
size_t from_file_to_list( FILE *fp, Data **list )
{
clear ( list );
size_t cnt = 0;
int date;
int temperature;
char day[11];
while ( fscanf( fp, "%d" "%s" "%d", &date, day, &temperature ) == 3 &&
( *list = malloc( sizeof( Data ) ) ) != NULL )
{
( *list )->date = date;
( *list )->temperature = temperature;
strcpy( ( *list )->day, day );
( *list )->next = NULL;
list = &( *list )->next;
++cnt;
}
return cnt;
}
您在设置p
之前设置*list = p;
,因此您有UB(未定义的行为(。
修复后,您的代码将无法正确处理空列表。
最好将值读入temp
变量,并仅在存在有效数据行的情况下执行malloc
。
不要对下一个记录执行malloc
。在文件的最后一行,您将获得额外的struct
分配。
下面是一些重构的代码。它带有注释。我已经编译了它,但没有测试它:
#include <stdio.h>
#include <stdlib.h>
struct data {
int date;
int temperature;
char day[11];
struct data *next;
};
typedef struct data Data;
int
from_file_to_list(FILE *fp, Data **list)
{
Data temp;
Data *prev;
Data *cur;
int cnt = 0;
// make the list empty
*list = NULL;
prev = NULL;
// loop on all lines/records in the file
while (fscanf(fp, "%d" "%s" "%d",
&temp.date, temp.day, &temp.temperature) == 3) {
// allocate new record
cur = malloc(sizeof(*cur));
// copy in the data we just read
*cur = temp;
// append to non-empty list
if (prev != NULL)
prev->next = cur;
// the first record
else
*list = cur;
// remember the previous record
prev = cur;
// advance the count of number of records
cnt++;
}
return cnt;
}