C语言问题:有关文件读写与单链表

文件读写时想实现的是“学号 姓名 成绩一 成绩二 成绩三 总分”这样的形式,而程序运行后文件里和运行显示的样子同下图一样,会出现两个名字,不知道为什么会出现这种情况,帮解决一下,谢谢

img

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//学生结构体 
typedef struct Student{
    char sno[8];    //8位学号 
    char name[20];  //姓名 
    float Score[3];    //以此表示数学成绩、英语成绩、C语言成绩
    float total;         //总分 
}STU;

//学生结点 
typedef struct node{
    STU data;   //学生数据 
    struct node* next;
}Node;

//链表 
typedef struct list{
    Node* head;   //头指针 
}List;
//初始化
void InitList(List* ls){
    ls->head=NULL;
    //以读的方式打开文件,要求文件必须存在 
    FILE* file=fopen("C:\\Users\\admin\\Desktop\\students'score.txt","rb");
    if(file==NULL)
    {
        printf("文件打开失败!!\n");
        return; 
    }
    STU stu;
    while(!feof(file)){
        fscanf(file,"%s %s %f %f %f %f",&stu.sno,&stu.name,&stu.Score[0],&stu.Score[1],&stu.Score[2],&stu.total);
        if(feof(file))
           break;
        Add(ls,stu);
    }
    fclose(file);   //关闭文件 
    printf("初始化成功!"); 
} 

void main(){
    List ls;
    InitList(&ls);
    STU stu; 
    int choice = 0,i;
    char sno[8];
    Menu();
    scanf("%d",&choice);
    while(choice!=0){
        switch(choice){
            case 1:
                Display(&ls);
                break;
            case 2:
                printf("请输入要查询的学号:");
                scanf("%s",sno);
                Inquire(&ls,sno);
                break;
            case 3:
                printf("请输入学号:");
                scanf("%s",stu.sno);
                printf("请输入姓名:");
                scanf("%s",stu.name);
                printf("请输入三科成绩:\n");
                for(i=0; i<3; i++){
                    printf("请输入第%d科成绩:",i+1);
                    scanf("%f",&stu.Score[i]);
                }
                stu.total=stu.Score[0]+stu.Score[1]+stu.Score[2];
                Add(&ls,stu);
                printf("学生信息添加成功。\n");
                Save(&ls); 
                break;
            case 4:
                printf("请输入要删除学生信息的学号:");
                scanf("%s",sno);
                Delete(&ls,sno);
                printf("删除成功!\n");
                Save(&ls);
                break;
            case 5:
                printf("请输入要修改某个学生成绩的学号:");
                scanf("%s",sno);
                Modify(&ls,sno);
                Save(&ls); 
                break;
            case 6:
                Statistics(&ls);
                break;
            default:
            printf("输入有误请重新输入!!!\n");
            break;     
        }
        Menu();
        scanf("%d",&choice);
    }
}

//菜单 
void Menu(){
    printf("\n\n"); 
    printf("------------------学生成绩管理系统------------------\n");
    printf("   1.显示学生成绩;\n");
    printf("   2.查询学生成绩;\n");
    printf("   3.添加学生成绩;\n");
    printf("   4.删除学生成绩;\n");
    printf("   5.修改学生成绩;\n");
    printf("   6.统计学生成绩;\n");
    printf("   0.退出程序\n");
    printf("----------------------------------------------------\n");
    printf("请选择要完成的操作:"); 
}

//显示
void Display(List* ls){
    Node* p=ls->head;
    if(p==NULL){
        printf("学生信息为空!!!\n");
        return;
    }
    printf("学号       姓名       数学       英语       C语言       总分\n");
    while(p!=NULL){
        printf("%s %s %.2f  %.2f  %.2f   %.2f\n",p->data.sno,p->data.name,p->data.Score[0],p->data.Score[1],p->data.Score[2],p->data.total);
        p=p->next;
    }
}

char sno[8] 长度扩大,比实际值多1,用于存放'\0'结束符。否则程序认为字符串没结束,继续往后读到了后面的姓名。

  • 这有个类似的问题, 你可以参考下: https://ask.csdn.net/questions/7720511
  • 我还给你找了一篇非常好的博客,你可以看看是否有帮助,链接:C语言:定义一个包含学生信息(学号,姓名,成绩)的顺序表和链表,使其具有如下功能:
  • 除此之外, 这篇博客: 海大12年编程题1:现有30个学生记录包括以下信息: 学号,姓名,性别,年龄,三门课成绩,平均成绩。 设计一个完整的C语言程序,完成以下功能: 1.定义结构体数组,包含以上所有信息; 2.定义函数用来中的 一、解题思路 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 思路:
    注释部分标准的比较清晰了,大家看代码的注释部分即可理解。

  • 您还可以看一下 包东华老师的C语言学生信息管理系统课程中的 以成绩顺序排序,以学号顺序排序小节, 巩固相关知识点
  • 以下回答由chatgpt基于相关博客总结生成:

    根据参考资料和问题描述,可以看出可能存在以下问题和解决方案:

    1. 单链表中出现重复姓名的问题: 可能原因:在插入节点时没有进行重复姓名的判断。 解决方案:在插入节点前先遍历整个链表,判断是否存在相同姓名的节点。可以通过比较字符串的方式或者使用哈希表来进行判断。

    示例代码(使用比较字符串的方式判断):

    typedef struct Node {
        char name[MAX_NAME_LENGTH];
        // other fields
        struct Node* next;
    } Node;
    
    Node* head = NULL;
    
    void insertNode(char* name) {
        Node* curr = head;
    
        // check if node with same name already exists
        while (curr != NULL) {
            if (strcmp(curr->name, name) == 0) {
                printf("Node with same name already exists\n");
                return;
            }
            curr = curr->next;
        }
    
        // create new node and insert into list
        Node* newNode = (Node*)malloc(sizeof(Node));
        strcpy(newNode->name, name);
        // initialize other fields
        newNode->next = NULL;
    
        // insert newNode at the end of the list
        if (head == NULL) {
            head = newNode;
        } else {
            Node* temp = head;
            while (temp->next != NULL) {
                temp = temp->next;
            }
            temp->next = newNode;
        }
    }
    
    1. 文件读写中出现相同姓名两次的问题: 可能原因:在文件读写过程中,没有判断是否已经遍历到文件尾部。 解决方案:在读取文件数据时,需要进行文件尾部判断,避免读取到文件尾部的标记。

    示例代码:

    FILE* fp;
    fopen_s(&fp, fileName, "r");
    
    // check if file opened successfully
    if (fp == NULL) {
        printf("Failed to open file\n");
        return;
    }
    
    while (!feof(fp)) {
        // read data from file
        // ...
    
        // check if reached end of file
        if (feof(fp)) {
            break;
        }
    
        // process data
        // ...
    }
    
    fclose(fp);
    

    以上是针对问题的一些可能解决方案,具体还需要根据实际代码和问题状况进行调试和优化。