读取和保存函数是实现功能的重要函数,在每次修改前需要调用读取函数拉起链表,修改后需要调用保存函数,存入文件

0.0读取学生信息

void ReadStudent(){
    FILE * fp;
    char k;
    if ((fp = fopen("D:\\demo.txt", "r")) == NULL) {    //以只读方式打开文件
        printf("无学生信息");
        exit(1);
    }
    //从文件读取信息 
    while (!feof(fp)){
            Node* p = (Node*)malloc(sizeof(Node));        //初始化一个结点p
            fscanf(fp,"%s\t%s\t%s\t%d\t%s\t%s\n", p->stu.stuNum, p->stu.stuName, p->stu.stuSex, &p->stu.stuAge, p->stu.stuClass, p->stu.stuScore);
            p->next = Head->next;    //头插p结点
            Head->next = p;
    }
}

0.1保存学生信息

void SaveStudent() { 
    FILE *fp;
    fp=fopen("D:\\demo.txt","w");        //以只写方式打开文件
    if( fp== NULL ){
    printf("打开文件失败\n");
    exit(1);  //退出程序
    }
    Node* p = Head->next;
    while (p != NULL) {                 //依次写入文件
        fprintf(fp, "%s\t%s\t%s\t%d\t%s\t%s\n", p->stu.stuNum, p->stu.stuName, p->stu.stuSex, p->stu.stuAge, p->stu.stuClass, p->stu.stuScore);
        p = p->next;
    }
    fclose(fp);
}

下面实现增加、查找、修改、删除功能

1.录入学生信息

void InputStudent() {
    int x;
    printf("您想要录入的学生人数:");
    scanf("%d", &x);
    int j = 1;

    while (x) {
        Node* p = (Node*)malloc(sizeof(Node));

        printf("录入第%d个学生信息\n", j++);
        printf("请输入学生的学号:");
        scanf("%s", p->stu.stuNum);

        Node* k = Head->next;
        while (k != NULL) {
            while (strcmp(p->stu.stuNum,k->stu.stuNum)==0) {
                printf("该学号已存在,请重新输入!\n");
                printf("请输入学生的学号:");
                scanf("%s", p->stu.stuNum);
            }
            k = k->next;
        }


        printf("请输入学生的姓名:");
        scanf("%s", p->stu.stuName);

        printf("请输入学生的性别:");
        scanf("%s", p->stu.stuSex);

        printf("请输入学生的年龄:");
        scanf("%d", &p->stu.stuAge);

        printf("请输入学生的班级:");
        scanf("%s", p->stu.stuClass);

        printf("请输入学生的成绩:");
        scanf("%s", p->stu.stuScore);

        p->next = Head->next;
        Head->next = p;
        x--;
    }

}

2.查找学生信息

void SearchStudent(){
    int n;
    char s[20];
    printf("请选择查找方式\n");
    printf("1.根据学号查找\n");
    printf("2.根据姓名查找\n");

    scanf("%d",&n);

    switch (n){
    case 1:{
        ReadStudent();//从文件将链表读入,Head为头结点
        int flag=0;
        Node* p=Head->next;
        printf("请输入想查找的学号:");
        scanf("%s",s);
        while(p!=NULL){
            if(strcmp(p->stu.stuNum,s)==0){                    //字符串匹配
                printf("学号\t姓名\t性别\t年龄\t班级\t成绩\n");
                printf("%s\t%s\t%s\t%d\t%s\t%s\n", p->stu.stuNum, p->stu.stuName, p->stu.stuSex, p->stu.stuAge, p->stu.stuClass, p->stu.stuScore);
                flag=1;
                break;
            }
            p=p->next;
        }
        if(flag==0){
            printf("没有符合条件的学生\n");
        }
    }
        break;

    case 2:    {
        ReadStudent();
        int flag=0;
        Node* p=Head->next;
        printf("请输入想查找的姓名:");
        scanf("%s",s);
        while(p){
            if(strcmp(p->stu.stuName,s)==0){
                printf("学号\t姓名\t性别\t年龄\t班级\t成绩\n");
                printf("%s\t%s\t%s\t%d\t%s\t%s\n", p->stu.stuNum, p->stu.stuName, p->stu.stuSex, p->stu.stuAge, p->stu.stuClass, p->stu.stuScore);
                flag=1;
                break;
            }
            p=p->next;
        }
        if(flag==0){
            printf("没有符合条件的学生");
        }
    }
        break;
    }
}

3.修改学生信息

void ModifyStudent(){
    printf("请输入你想修改学生的姓名\n");
    char s[20];
    char num[20];
    char name[20];
    char sex[20];
    int age;
    char classs[20];
    char score[20];
    Head->next=NULL;//重要,如果要保存链表,每次读取链表前都要将头指针指向空,不然数据会重复
    ReadStudent();//读入链表
    int flag=0;
    Node* p=Head->next;
    scanf("%s",s);
    while(p!=NULL){
        if(strcmp(p->stu.stuName,s)==0){
            flag=1;
            break;
        }
        p=p->next;
    }
    if(flag==0){
        printf("没有找到该学生");
    }else{

        printf("请输入想修改的内容:\n");
        printf("1.学生学号\n");
        printf("2.学生姓名\n");
        printf("3.学生性别\n");
        printf("4.学生年龄\n");
        printf("5.学生班级\n");
        printf("6.学生成绩\n");

        int n;
        scanf("%d",&n);
        switch(n){
            case 1: 
                printf("将学号修改为:");
                scanf("%s",num);
                strrpl(p->stu.stuNum,num);  //strrpl为字符串替换函数,见末尾
                break;

            case 2:
                printf("将姓名修改为:");
                scanf("%s",name);
                strrpl(p->stu.stuName,name);
                break;

            case 3:
                printf("将性别修改为:");
                scanf("%s",sex);
                strrpl(p->stu.stuSex,sex);
                break;

            case 4:
                printf("将年龄修改为:");
                scanf("%d",&age);    
                p->stu.stuAge=age;
                break;

            case 5:
                printf("将班级修改为:");
                scanf("%s",classs);
                strrpl(p->stu.stuClass,classs);
                break;

            case 6:
                printf("将成绩修改为:");
                scanf("%s",score);
                strrpl(p->stu.stuScore,score);
                break;
            }
        }    
}

修改的时候需要用到字符替换函数

//字符替换 s1替换为s2
void strrpl(char q1[20],char q2[20]){
    int i=0,j=0;
    while(q1[i]!='\0'){
        q1[i++]='\0';
    }
    i=0;
    while(q2[j]!='\0'){
        q1[i++]=q2[j++];
    }

}

4.删除学生信息

void DeleStudent(){ 
    Head->next=NULL;//重要,如果要保存链表,每次读取链表前都要将头指针指向空,不然数据会重复
    ReadStudent();
    char name[20];
    Node*p=Head->next;
    Node*q=Head;
    printf("要删除学生姓名\n");
    scanf("%s",name);
    while(p!=NULL){
        if(strcmp(p->stu.stuName,name)==0){
            q->next=p->next;
            free(p);
        }
        q=q->next;
        p=p->next;
    }
}

最后实现统计和查看功能

5.统计学生人数

void NumStudent(){
    FILE* fp;
    char w;
    int num=0;
    if ((fp = fopen("D:\\demo.txt", "r")) == NULL) {
        printf("无学生信息");
    }else{
        fp = fopen("D:\\demo.txt", "r");
        while ((w=fgetc(fp))!=EOF){
            if(w=='\n'){        //根据换行数统计学生人数
                num++;
            }
        }
        printf("共有学生%d人\n",num);
    }

}

6.查看录入学生信息

void PrintStudent() {
    Head->next=NULL;
    ReadStudent();
    Node* p=Head->next;
    while (p){
        printf("%s\t%s\t%s\t%d\t%s\t%s\n", p->stu.stuNum, p->stu.stuName, p->stu.stuSex, p->stu.stuAge, p->stu.stuClass, p->stu.stuScore);
        p=p->next;
    }
}

全部代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
 #include<windows.h>

typedef struct _Student {     //学生结点数据域结构体
    char  stuNum[20];        //学号
    char stuName[20];   //姓名
    char stuSex[20];       //性别
    int  stuAge;        //年龄
    char stuClass[20];  //班级
    char stuScore[20];        //分数
}Student;

typedef struct _Node {            //学生结点
    Student stu;        //学生
    struct _Node* next;//指针域
}Node;

void Welcome();//欢迎界面
void ReadStudent();//读取学生信息
void SaveStudent();//保存学生信息
void InputStudent();//录入学生信息
void NumStudent();//统计学生人数
void SearchStudent();//查找学生信息
void ModifyStudent();//修改学生信息
void DeleStudent();//删除学生信息
void PrintStudent();//查看录入信息
void Help();//使用帮助
void strrpl(char s1[20],char s2[20]);//字符替换 



Node* Head;//全局头结点

int main() {
    system("color 3a");//改变控制台颜色
    Head = (Node*)malloc(sizeof(Node));
    Head->next = NULL;//初始化一个头结点

    Welcome();    //欢迎界面

    int n;
    while (1) {
        printf("请选择想使用的功能\n");
        scanf("%d", &n);//输入一个数字
        switch (n) {
        case 1: InputStudent();     //1.录入学生信息
                SaveStudent(); 
            break;        
        case 2: NumStudent();        //2.统计学生信息    
            break;
        case 3: SearchStudent();    //3.查找学生信息
            break;
        case 4: ModifyStudent();    //4.修改学生信息
                SaveStudent(); 
            break;
        case 5: DeleStudent();        //5.删除学生信息
                SaveStudent(); 
            break;
        case 6: PrintStudent();        //6.查看录入信息
            break;
        case 7: Help();                //7.使用帮助
            break;
        case 0: exit(0);
        }


    }
    return 0;
}


//欢迎界面
void Welcome() {
    printf("===============================================\n");
    printf("===========欢迎使用学生管理系统 v1.0===========\n");
    printf("=                                             =\n");
    printf("=               1.录入学生信息                 =\n");
    printf("=               2.统计学生人数                 =\n");
    printf("=               3.查找学生信息                 =\n");
    printf("=               4.修改学生信息                 =\n");
    printf("=               5.删除学生信息                 =\n");
    printf("=               6.查看录入信息                   =\n");
    printf("=               7.查看使用帮助                   =\n");
    printf("=               0.退出系统                     =\n");
    printf("=                                             =\n");
    printf("===============================================\n");
}

//读取学生信息
void ReadStudent(){
    FILE * fp;
    char k;
    if ((fp = fopen("D:\\demo.txt", "r")) == NULL) {    //以只读方式打开文件
        printf("无学生信息");
        exit(1);
    }
    //从文件读取信息 
    while (!feof(fp)){
            Node* p = (Node*)malloc(sizeof(Node));        //初始化一个结点p
            fscanf(fp,"%s\t%s\t%s\t%d\t%s\t%s\n", p->stu.stuNum, p->stu.stuName, p->stu.stuSex, &p->stu.stuAge, p->stu.stuClass, p->stu.stuScore);
            p->next = Head->next;    //头插p结点
            Head->next = p;
    }
}

//保存学生信息
void SaveStudent() { 
    FILE *fp;
    fp=fopen("D:\\demo.txt","w");        //以只写方式打开文件
    if( fp== NULL ){
    printf("打开文件失败\n");
    exit(1);  //退出程序
    }
    Node* p = Head->next;
    while (p != NULL) {                 //依次写入文件
        fprintf(fp, "%s\t%s\t%s\t%d\t%s\t%s\n", p->stu.stuNum, p->stu.stuName, p->stu.stuSex, p->stu.stuAge, p->stu.stuClass, p->stu.stuScore);
        p = p->next;
    }
    fclose(fp);
}

//1.录入学生信息
void InputStudent() {
    int x;
    printf("您想要录入的学生人数:");
    scanf("%d", &x);
    int j = 1;

    while (x) {
        Node* p = (Node*)malloc(sizeof(Node));

        printf("录入第%d个学生信息\n", j++);
        printf("请输入学生的学号:");
        scanf("%s", p->stu.stuNum);

        Node* k = Head->next;
        while (k != NULL) {
            while (strcmp(p->stu.stuNum,k->stu.stuNum)==0) {
                printf("该学号已存在,请重新输入!\n");
                printf("请输入学生的学号:");
                scanf("%s", p->stu.stuNum);
            }
            k = k->next;
        }


        printf("请输入学生的姓名:");
        scanf("%s", p->stu.stuName);

        printf("请输入学生的性别:");
        scanf("%s", p->stu.stuSex);

        printf("请输入学生的年龄:");
        scanf("%d", &p->stu.stuAge);

        printf("请输入学生的班级:");
        scanf("%s", p->stu.stuClass);

        printf("请输入学生的成绩:");
        scanf("%s", p->stu.stuScore);

        p->next = Head->next;
        Head->next = p;
        x--;
    }

}

//2.统计学生人数
void NumStudent(){
    FILE* fp;
    char w;
    int num=0;
    if ((fp = fopen("D:\\demo.txt", "r")) == NULL) {
        printf("无学生信息");
    }else{
        fp = fopen("D:\\demo.txt", "r");
        while ((w=fgetc(fp))!=EOF){
            if(w=='\n'){        //根据换行数统计学生人数
                num++;
            }
        }
        printf("共有学生%d人\n",num);
    }

}

//3.查找学生信息
void SearchStudent(){
    int n;
    char s[20];
    printf("请选择查找方式\n");
    printf("1.根据学号查找\n");
    printf("2.根据姓名查找\n");

    scanf("%d",&n);

    switch (n){
    case 1:{
        ReadStudent();//从文件将链表读入,Head为头结点
        int flag=0;
        Node* p=Head->next;
        printf("请输入想查找的学号:");
        scanf("%s",s);
        while(p!=NULL){
            if(strcmp(p->stu.stuNum,s)==0){                    //字符串匹配
                printf("学号\t姓名\t性别\t年龄\t班级\t成绩\n");
                printf("%s\t%s\t%s\t%d\t%s\t%s\n", p->stu.stuNum, p->stu.stuName, p->stu.stuSex, p->stu.stuAge, p->stu.stuClass, p->stu.stuScore);
                flag=1;
                break;
            }
            p=p->next;
        }
        if(flag==0){
            printf("没有符合条件的学生\n");
        }
    }
        break;

    case 2:    {
        ReadStudent();
        int flag=0;
        Node* p=Head->next;
        printf("请输入想查找的姓名:");
        scanf("%s",s);
        while(p){
            if(strcmp(p->stu.stuName,s)==0){
                printf("学号\t姓名\t性别\t年龄\t班级\t成绩\n");
                printf("%s\t%s\t%s\t%d\t%s\t%s\n", p->stu.stuNum, p->stu.stuName, p->stu.stuSex, p->stu.stuAge, p->stu.stuClass, p->stu.stuScore);
                flag=1;
                break;
            }
            p=p->next;
        }
        if(flag==0){
            printf("没有符合条件的学生");
        }
    }
        break;
    }
}

//4.修改学生信息
void ModifyStudent(){
    printf("请输入你想修改学生的姓名\n");
    char s[20];
    char num[20];
    char name[20];
    char sex[20];
    int age;
    char classs[20];
    char score[20];
    Head->next=NULL;//重要,如果要保存链表,每次读取链表前都要将头指针指向空,不然数据会重复
    ReadStudent();//读入链表
    int flag=0;
    Node* p=Head->next;
    scanf("%s",s);
    while(p!=NULL){
        if(strcmp(p->stu.stuName,s)==0){
            flag=1;
            break;
        }
        p=p->next;
    }
    if(flag==0){
        printf("没有找到该学生");
    }else{

        printf("请输入想修改的内容:\n");
        printf("1.学生学号\n");
        printf("2.学生姓名\n");
        printf("3.学生性别\n");
        printf("4.学生年龄\n");
        printf("5.学生班级\n");
        printf("6.学生成绩\n");

        int n;
        scanf("%d",&n);
        switch(n){
            case 1: 
                printf("将学号修改为:");
                scanf("%s",num);
                strrpl(p->stu.stuNum,num);  //strrpl为字符串替换函数,见末尾
                break;

            case 2:
                printf("将姓名修改为:");
                scanf("%s",name);
                strrpl(p->stu.stuName,name);
                break;

            case 3:
                printf("将性别修改为:");
                scanf("%s",sex);
                strrpl(p->stu.stuSex,sex);
                break;

            case 4:
                printf("将年龄修改为:");
                scanf("%d",&age);    
                p->stu.stuAge=age;
                break;

            case 5:
                printf("将班级修改为:");
                scanf("%s",classs);
                strrpl(p->stu.stuClass,classs);
                break;

            case 6:
                printf("将成绩修改为:");
                scanf("%s",score);
                strrpl(p->stu.stuScore,score);
                break;
            }
        }    
}

//5.删除学生信息
void DeleStudent(){
    Head->next=NULL;//重要,如果要保存链表,每次读取链表前都要将头指针指向空,不然数据会重复
    ReadStudent();
    char name[20];
    Node*p=Head->next;
    Node*q=Head;
    printf("要删除学生姓名\n");
    scanf("%s",name);
    while(p!=NULL){
        if(strcmp(p->stu.stuName,name)==0){
            q->next=p->next;
            free(p);
        }
        q=q->next;
        p=p->next;
    }
}

//6.查看录入信息
void PrintStudent() {
    Head->next=NULL;
    ReadStudent();
    Node* p=Head->next;
    while (p){
        printf("%s\t%s\t%s\t%d\t%s\t%s\n", p->stu.stuNum, p->stu.stuName, p->stu.stuSex, p->stu.stuAge, p->stu.stuClass, p->stu.stuScore);
        p=p->next;
    }
}

//7.使用帮助
void Help(){
    printf("1.程序将自动在D盘根目录下新建一个demo.txt文件用来储存学生信息\n");
    printf("2.根据提示在键盘上选择对应的数字完成交互\n");

}


//字符替换 s1替换为s2
void strrpl(char q1[20],char q2[20]){
    int i=0,j=0;
    while(q1[i]!='\0'){
        q1[i++]='\0';
    }
    i=0;
    while(q2[j]!='\0'){
        q1[i++]=q2[j++];
    }

}