c-如何停止创建链表的循环,再创建一个空链接


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;
}

最新更新