c语言 - 为什么我的"打印"功能只读取最后一个元素和垃圾然后停止响应?


#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是一个指针值。为什么使用整数类型?

以下建议的代码:

  1. 干净地编译
  2. 执行大多数错误检查
  3. 实际生成struct student的链表
  4. 文档为什么包含每个头文件
  5. 消除了大部分"魔术"数字
  6. 正确初始化next字段
  7. 无法将分配的内存区域传递给free()
  8. head的地址正确传递给read()函数,以便当列表为空时,可以使用指向第一个node的指针更新head
  9. 的内容
  10. 正确初始化指向 NULL 的head指针
  11. 将每个新节点正确链接到前一个节点

现在,建议的代码:

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

相关内容

  • 没有找到相关文章

最新更新