#include <stdlib.h>
#define NULL 0
struct student
{
int id;
char name[20];
float marks;
struct student *next
};
typedef struct student node;
void main()
{
node *head;
void read(node *p);
void create(node *p);
int count(node *p);
void print(node *p);
head=(node *)malloc(sizeof(node));
read(head);
printf("n");
print(head);
}
void read(node *list)
{
FILE *fp;
char filename[30];
printf("input file name: ");
scanf("%s",filename);
fp=fopen(filename,"r");
if(fp == NULL)
{
return; // file doesn't exist
}
while(fscanf(fp, "%s %d %f", list->name, &list->id, &list->marks) == 3)
{
printf("%s t%d t%fn", list->name,list->id,list->marks);//check
list->next=(node*)malloc(sizeof(node));//create next node
}
fclose(fp);
return;
}
void print(node*list)
{
if(list->next!=NULL)
{
printf("ID=%dn",list->id);
printf("Name=%sn",list->name);
printf("Marks=%fn",list->marks);
printf("n");
if(list->next->next==NULL)
{
printf("%d",list->next->id);
}
print(list->next);
}
return;
}
看起来它打印了最后一行和下一行(这是垃圾)。我认为问题出在读取功能上?因为我觉得我检查它的方式不准确。 无论如何,我无法解决此问题,因此如果有人可以教我故障在哪里以及更好的解决方法,那将非常有帮助。
输出:
input file name: input.txt.txt
student01 1 95.000000
student03 3 90.000000
student05 5 86.000000
student07 7 83.000000
student09 9 98.000000
student10 10 93.000000
student08 8 92.000000
student06 6 96.000000
student04 4 93.000000
student02 2 88.000000
ID=2
Name=student02
Marks=88.000000
ID=11552328
░ame=P
Marks=13640062821560266000000000000000000.000000
Process returned -1073741819 (0xC0000005) execution time : 6.737 s
Press any key to continue.
看起来它打印了最后一行和下一行(这是垃圾)。我认为问题出在读取功能上?
这是正确的。
原因如下:
while(fscanf(fp, "%s %d %f", list->name, &list->id, &list->marks) == 3)
{
printf("%s t%d t%fn", list->name,list->id,list->marks);//check
list->next=(node*)malloc(sizeof(node));//create next node
}
在此循环中,您始终读取列表第一个元素中的所有数据。 您分配了一些新节点,但从不为其分配任何内容。 您甚至不会通过将NULL
分配给list->next->next
来终止列表。
这会导致各种问题:
- 您可以为每个迭代分配内存,但只有最后一次可以通过
list->next
访问。所有其他内存块都将丢失。 - 您有一个未终止的列表,当您尝试在打印期间遍历所有节点时,该列表会导致未定义的行为。
- 您将所有数据读取到 1 个位置,这意味着您丢失了文件中除最后一行之外的所有数据。
要解决此问题,您需要像这样更改它:
while(fscanf(fp, "%s %d %f", list->name, &list->id, &list->marks) == 3)
{
printf("%s t%d t%fn", list->name,list->id,list->marks);//check
list->next=(node*)malloc(sizeof(node));//create next node
if (list->next != NULL)
{
list = list->next; // Advance to new node
list->next = NULL; // Terminate list at this node (until a new one is added)
}
else
{
// error handling
exit(1);
}
}
除此之外:
- 您显然没有使用嵌入式系统,其中
main
可能具有void
返回类型。对于所有托管环境,它必须返回int
. - 为什么要定义标准宏
NULL
?您应该包括定义它的 C 标准标头。除此之外,NULL
是一个指针值。为什么使用整数类型?
以下建议的代码:
- 干净地编译
- 执行大多数错误检查
- 实际生成
struct student
的链表 - 文档为什么包含每个头文件
- 消除了大部分"魔术"数字
- 正确初始化
next
字段 - 无法将分配的内存区域传递给
free()
- 将
head
的地址正确传递给read()
函数,以便当列表为空时,可以使用指向第一个node
的指针更新head
的内容 - 正确初始化指向 NULL 的
head
指针 - 将每个新节点正确链接到前一个节点
现在,建议的代码:
#include <stdlib.h> // FILE, fopen, fclose, scanf(), fscanf(), printf()
#include <stdio.h> // malloc(), free(), exit(), EXIT_FAILURE
#include <string.h> // memcpy()
#define MAX_NAME_LEN 20
#define MAX_FILENAME_LEN 30
struct student
{
int id;
char name[ MAX_NAME_LEN ];
float marks;
struct student *next;
};
typedef struct student node;
void read_echo_records (node **p);
void create(node *p);
int count (node *p);
void print (node *p);
int main( void )
{
node *head = NULL;
read_echo_records( &head);
printf("n");
print(head);
}
void read_echo_records(node **list)
{
FILE *fp;
char filename[ MAX_FILENAME_LEN ];
printf("input file name: ");
scanf("%29s",filename);
fp = fopen( filename, "r" );
if( fp == NULL )
{
perror( "fopen failed" );
exit( EXIT_FAILURE );
}
node *current = *list;
node *prior = *list;
node workspace;
workspace.next = NULL;
while(fscanf(fp, "%s %d %f", workspace.name, &workspace.id, &workspace.marks) == 3)
{
printf("%s t%d t%fn", workspace.name, workspace.id, workspace.marks);//check
if( ! (current = malloc(sizeof(node))) )//create next node
{
perror( "malloc failed" );
fclose( fp );
exit( EXIT_FAILURE );
}
memcpy( current, &workspace, sizeof( node ) );
*prior->next = current;
prior = current;
}
fclose(fp);
return;
}
void print(node*list)
{
node *current = list;
if( ! current )
{
printf( "%sn", "list is empty" );
return;
}
while( current->next )
{
printf( "ID=%dn", current->id );
printf( "Name=%sn", current->name );
printf( "Marks=%fn", current->marks );
printf( "n");
current = current->next;
}
}