以链表为基本数据结构的学生信息库大作业

 我记得当时一个晚上多一点敲了500多行,后来debug了两天。。。

以后写东西还是踏实一点,写一个功能就测试一下,不要一股脑往下写,不然一堆bug真的会de到吐魂。。。

 写这篇博客主要是记录一下de最久的一部分,就是链表数据向文件中的存入和读取

1. 我这里是将整个结点存入数据 => 每次存取都要用循环一个一个存取

2. 我这里是整条链表存进去(覆盖),而非追加结点进去 => wb+(覆盖)

要注意的是:一开始我的写法是ab+ 和 rewind重定位到文件头部进行文件重写;但是,经过漫长时间的测试以及和老师的交流发现 => 如果是ab+那rewind就不起作用,必须用wb+。

更离谱的是用Dev跑和用Clion一个是追加,一个是覆盖。

// 这里文件读入的时候读入文件的链表是没有头节点的
void Write(FILE* f, List head) {
    List p = head;
    while(p) {
        fwrite(p, SIZE, 1, f);
        p = p->next;
    }
    printf("		Success Write!\n\n");
}

// 在从文件中读出链表数据(没有头节点)的时候自动添加上头节点
List Read(FILE* f) {
    List dummy = (List)malloc(sizeof(Node));
    dummy->next = NULL;
    List head = dummy;
    int n = getCount(f);
    for(int i = 0; i < n; i++) {
        List p = (List)malloc(sizeof(Node));
        fread(p, SIZE, 1, f);
        head->next = p;
        head = p;
    }
    printf("		Success Read!\n\n");
    return dummy;
}

最后大作业开源,仅提供思路用 

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

typedef struct Subject {
    char name[18];
    double scores[100];
    int count;
    double sum;
    double aver;
} Subject;

typedef struct Node{
    char name[18];
    char uuid[18];
    Subject subject[5];
    int FailedSubjectCount;
    double aver;
    struct Node* next;
} Node, Student, *List;

long SIZE;

#define FILENAME "test.txt"

int cmpD_bySubject(const void* a, const void* b);
List InitialList();
int getCount(FILE* f);
void Write(FILE* f, List head);
List Read(FILE* f);
List DSortList(List head);
List ASortList(List head);
char Menu();
void Add(FILE* f);
bool FindStudent(FILE* f);
void ListALL(FILE* f);
void Del(FILE* f);
void Update(FILE* f);
void FindFailed(FILE* f);
void FindTop(FILE* f);
void FindAverage(FILE* f);


int main() {
    FILE *fp;
    if((fp = fopen(FILENAME, "ab+")) == NULL) {
        printf("\n       can't open this file!\n\n\n\n");
        exit(0);
    }
    char choice;
    SIZE = sizeof(Node);
    while(( choice = Menu()) != '0') {
        switch (choice) {
            case '1':
                fp = fopen(FILENAME, "ab+");
                Add(fp);
                break;
            case '2':
                fp = fopen(FILENAME, "ab+");
                printf("\n	   --------------------------Search record---------------------------\n\n");
                printf("		        1.Single student   2.Average Score\n\n");
                printf("		        3.Fail Exam 	   4.Top 5 student\n\n");
                printf("		        0.Exit\n\n");
                printf("	   ------------------------------------------------------------------\n\n");
                printf("	   Please give your choice: ");
                char Choice;
                scanf("%c", &Choice);
                getchar();
                if(Choice == '3') FindFailed(fp);
                else if(Choice == '4') FindTop(fp);
                else if(Choice == '2') FindAverage(fp);
                else if(Choice == '1') FindStudent(fp);
                else if(Choice == '0') {
                	printf("\n\n");
                	break;
				}
                else printf("Error Input!\n\n");
                break;
            case '3':
                fp = fopen(FILENAME, "ab+");
                Del(fp);
                break;
            case '4':
                fp = fopen(FILENAME, "rb+");
                Update(fp);
                break;
            case '5':
                fp = fopen(FILENAME, "ab+");
                ListALL(fp);
                break;
            case '6':
            	system("cls");
                break;
            default:
                printf("\n\n\n\n		   			Error, please input again!\n\n\n\n");
                break;
        }
    }
    if(fclose(fp)) {
        printf("can't close the file!\n");
        exit(0);
    }
    return 0;
}

int cmpD_bySubject(const void* a, const void* b) {
    return ((Subject*)b)->aver - ((Subject*)a)->aver;
}

List InitialList() {
    List dummy = (List)malloc(sizeof(Node));
    dummy->next = NULL;
    dummy->FailedSubjectCount = -1;
    dummy->aver = -1;
    return dummy;
}

int getCount(FILE* f) {
    long begin, end;
    fseek(f, 0L, SEEK_SET);
    begin = ftell(f);
    fseek(f, SIZE, SEEK_END);
    end = ftell(f);
//    在这里将文件的重定位到文件头部 不影响后续操作
    rewind(f);
    return (int)((end - begin) / SIZE - 1);
}

// 这里文件读入的时候读入文件的链表是没有头节点的
void Write(FILE* f, List head) {
    List p = head;
    while(p) {
        fwrite(p, SIZE, 1, f);
        p = p->next;
    }
    printf("		Success Write!\n\n");
}

// 在从文件中读出链表数据(没有头节点)的时候自动添加上头节点
List Read(FILE* f) {
    List dummy = (List)malloc(sizeof(Node));
    dummy->next = NULL;
    List head = dummy;
    int n = getCount(f);
    for(int i = 0; i < n; i++) {
        List p = (List)malloc(sizeof(Node));
        fread(p, SIZE, 1, f);
        head->next = p;
        head = p;
    }
    printf("		Success Read!\n\n");
    return dummy;
}

// 对链表进行插入排序(降序)
List DSortList(List head) {
    if(!head || !head->next) return head;
    List last = head->next;
    head->next = NULL;
    List dummy = (List)malloc(sizeof(Node));
    dummy->aver = INT_MAX;
    dummy->next = head;
    List p = last;
    while(p) {
        last = p->next;
        p->next = NULL;
        List temp = dummy;
        while(temp) {
            if(temp->next == NULL || (temp->aver >= p->aver && temp->next->aver <= p->aver) ) {
                p->next = temp->next;
                temp->next = p;
                break;
            }
            temp = temp->next;
        }
        p = last;
    }
    return dummy->next;
}

// 对链表进行插入排序(升序)
List ASortList(List head) {
    if(!head || !head->next) return head;
    List last = head->next;
    head->next = NULL;
    List dummy = (List)malloc(sizeof(Node));
    dummy->aver = INT_MIN;
    dummy->next = head;
    List p = last;
    while(p) {
        last = p->next;
        p->next = NULL;
        List temp = dummy;
        while(temp) {
            if(temp->next == NULL || (temp->aver <= p->aver && temp->next->aver >= p->aver) ) {
                p->next = temp->next;
                temp->next = p;
                break;
            }
            temp = temp->next;
        }
        p = last;
    }
    return dummy->next;
}

char Menu() {
    char choice;
    printf("	   --------------------------Management for Students' Information---------------------------\n\n");
    printf("		   1.Append record 			2.Search record\n\n");
    printf("		   3.Delete record			4.Modify record\n\n");
    printf("		   5.List All Students      		6.Clean the Window\n\n");
    printf("		   0.Exit\n\n");
    printf("	   -----------------------------------------------------------------------------------------\n\n");
    printf("	   Please give your choice: ");
    scanf("%c", &choice);
    getchar();
    return choice;
}

void Add(FILE* f) {
    int n;
    int NodeCount = getCount(f);
    List tail = NULL;
    List head = NULL;
//    判断文件中有没有结点 => 拿头节点
//    这里的链表都是自带头节点的
    if(!NodeCount) {
        tail = InitialList();
        head = tail;
    }else {
        tail = Read(f);
        head = tail;
        while(tail->next) tail = tail->next;
    }
    printf("	   please input the number of student you want to append.\n	   ");
    scanf("%d", &n);
    getchar();
    while(n--) {
        List stu = (List)malloc(sizeof(Node));
        stu->FailedSubjectCount = 0;
        stu->aver = 0;
        stu->next = NULL;
        printf("	   Input the student's name:\n	   ");
        scanf("%s", stu->name);
        getchar();
        printf("	   Input the student's uuid:\n	   ");
        scanf("%s", stu->uuid);
        getchar();
//        此题限定四门课程
        strcpy(stu->subject[0].name, "Calculus");
        strcpy(stu->subject[1].name, "Linear Algebra");
        strcpy(stu->subject[2].name, "Physics");
        strcpy(stu->subject[3].name, "Programme C");
        double average = 0;
        for (int i = 0; i < 4; i++) {
            double score = 0;
            int k = 0;
            stu->subject[i].sum = 0, stu->subject[i].aver = 0;
            printf("	   Input the scores of %s (-1 stands for stop):\n	   ", stu->subject[i].name);
            while (~scanf("%lf", &score) && score != -1) {
                getchar();
                if(score < 60) (stu->FailedSubjectCount)++;
                stu->subject[i].scores[k++] = score;
                stu->subject[i].sum += score;
            }
            // 最后一个score == -1的输入不会进入while内部 => getchar()要写在外面
            getchar();
            stu->subject[i].count = k;
            stu->subject[i].aver = stu->subject[i].sum / (k * 1.0);
            average += stu->subject[i].aver;
        }
        stu->aver = average / 4.0;
        printf("	   Press any key to write the information.\n\n\n\n");
        getch();
        tail->next = stu;
        tail = stu;
    }
//    整条读入 => 每次新增都是覆盖原有文件数据
    f = fopen(FILENAME, "wb+");
    Write(f, head->next);
    printf("		Add Over!\n\n");
    printf("		Press any key to continue.\n\n");
    getch();
    fclose(f);
}

bool FindStudent(FILE* f) {
    int count = getCount(f);
//    考虑到代码的健壮性 当文件中没有数据的时候提示用户
    if (!count) {
        printf("		Empty File!\n\n\n\n");
        printf("		Press any key to continue.\n\n");
        getch();
        fclose(f);
        return false;
    }
    List head = Read(f)->next;
    printf("		Input the student's UUID or NAME to search it's information.\n			");
    char infor[18];
    scanf("%s", infor);
    getchar();
    List p = head;
    while (p) {
        // 需要注意的是strcmp对于相同字符串返回0
        if ((!strcmp(p->uuid, infor)) || (!strcmp(p->name, infor))) {
            printf("\n	        Name       	  Uuid          \n\n");
            printf("            %8s        %8s\n\n", p->name, p->uuid);
            for (int i = 0; i < 4; i++) {
                printf("		%s: ", p->subject[i].name);
                for (int j = 0; j < p->subject[i].count; j++) {
                    printf("%.2lf  ", p->subject[i].scores[j]);
                }
                printf("\n    		Average: %.2lf\n\n", p->subject[i].aver);
            }
            break;
        }
        p = p->next;
    }
    printf("		That's the student's information in this File.\n\n\n\n");
    if(p == NULL) {
        printf("		Can't find this student!\n\n");
        printf("		Press any key to continue.\n\n");
        getch();
        fclose(f);
        return false;
    }
    printf("		Press any key to continue.\n\n");
    getch();
    fclose(f);
    return true;
}

void ListALL(FILE* f) {
    int count = getCount(f);
    printf("\n\n		The number of the students = %d\n\n", count);
//    考虑到代码的健壮性 当文件中没有数据的时候提示用户
    if (!count) {
        printf("		Empty File!\n\n\n\n");
        printf("		Press any key to continue.\n\n");
        fclose(f);
        return;
    }
    List p = Read(f)->next;
    printf("\n	        Name       	  Uuid          \n\n");
    while (p) {
        printf("            %8s        %8s\n\n", p->name, p->uuid);
        for (int i = 0; i < 4; i++) {
            printf("		%s: ", p->subject[i].name);
            for (int j = 0; j < p->subject[i].count; j++) {
                printf("%.2lf  ", p->subject[i].scores[j]);
            }
            printf("\n    		Average: %.2lf\n\n", p->subject[i].aver);
        }
        p = p->next;
        printf("\n\n");
    }
    printf("		That's all students in this File.\n\n\n\n");
}

void Del(FILE* f) {
    int count = getCount(f);
//    考虑到代码的健壮性 当文件中没有数据的时候提示用户
    if(!count) {
        printf("		Empty File!\n\n\n\n");
        printf("		Press any key to continue.\n\n");
        getch();
        fclose(f);
        return;
    }
    List dummy = Read(f);
    printf("		Input the student's UUID or NAME to Delete it's information.\n	   ");
    char infor[18];
    scanf("%s", infor);
    getchar();
    List p = dummy;
    while (p->next) {
        List stu = p->next;
        // 需要注意的是strcmp对于相同字符串返回0
        if (!strcmp(stu->uuid, infor) || !strcmp(stu->name, infor)) {
            printf("		Have found the student, are you sure to delete it?(Y/N)\n	   ");
            char judge;
            scanf("%c", &judge);
            getchar();
//            用户选择继续修改后执行
            if(judge == 'Y' || judge == 'y') {
                p->next = p->next->next;
                printf("        Success Delete!\n\n");
                f = fopen(FILENAME, "wb+");
                Write(f, dummy->next);
            }
            break;
        }
        p = p->next;
    }
    if(p == NULL) {
        printf("		Can't find this student!\n\n\n\n");
    }
    printf("		Press any key to continue.\n\n");
    getch();
    fclose(f);
}

void Update(FILE* f) {
    int count = getCount(f);
//    考虑到代码的健壮性 当文件中没有数据的时候提示用户
    if (!count) {
        printf("		Empty File!\n\n\n\n");
        printf("		Press any key to continue.\n\n");
        getch();
        fclose(f);
        return;
    }
    List dummy = Read(f);
    printf("		Input the student's UUID or NAME to Modify it's information.\n	   ");
    char infor[18];
    scanf("%s", infor);
    getchar();
    List p = dummy->next;
    while (p) {
        // 需要注意的是strcmp对于相同字符串返回0
        if (!strcmp(p->uuid, infor) || !strcmp(p->name, infor)) {
            printf("\n	        Name       	  Uuid          \n\n");
            printf("            %8s        %8s\n\n", p->name, p->uuid);
            for (int i = 0; i < 4; i++) {
                printf("		%s: ", p->subject[i].name);
                for (int j = 0; j < p->subject[i].count; j++) {
                    printf("%.2lf  ", p->subject[i].scores[j]);
                }
                printf("\n");
            }
            printf("		Have found the student, are you sure to modify it?(Y/N)\n	   ");
            char judge;
            scanf("%c", &judge);
            getchar();
//            用户选择继续修改后执行
            if (judge == 'Y' || judge == 'y') {
                printf("\n  		Input the student's name:\n	   ");
                scanf("%s", p->name);
                getchar();
                printf("\n  		Input the student's uuid:\n	   ");
                scanf("%s", p->uuid);
                getchar();
                printf("\n  		Input each score of this student(-1 stands for stop):\n");
                for (int i = 0; i < 4; i++) {
                    double score = 0, sum = 0;
                    int k = 0;
                    p->subject[i].sum = 0, p->subject[i].aver = 0;
                    p->FailedSubjectCount = 0, p->aver = 0;
                    printf("		Input the scores of %s (-1 stands for stop):\n	   ", p->subject[i].name);
                    while (~scanf("%lf", &score) && score != -1) {
		                getchar();
		                if(score < 60) (p->FailedSubjectCount)++;
		                p->subject[i].scores[k++] = score;
		                p->subject[i].sum += score;
		            }
                    getchar();
                    p->subject[i].count = k;
                    p->subject[i].aver = sum / (k * 1.0);
                }
                printf("        Success Modification!\n\n");
                f = fopen(FILENAME, "wb+");
                Write(f, dummy->next);
            }
            break;
        }
        p = p->next;
    }
    if(p == NULL) {
        printf("	   Can't find this student!\n\n\n\n");
    }
    printf("	   Press any key to continue.\n\n");
    getch();
    fclose(f);
}

void FindFailed(FILE* f) {
    int count = getCount(f);
//    考虑到代码的健壮性 当文件中没有数据的时候提示用户
    if (!count) {
        printf("	   Empty File!\n\n\n\n");
        printf("	   Press any key to continue.\n\n");
        getch();
        fclose(f);
        return;
    }
    List dummy = Read(f);
    List p = dummy->next;
    int FailedPersonCount = 0, FailedSubjectCount = 0;
    while(p) {
        if(p->FailedSubjectCount > 0) {
            FailedPersonCount++;
            FailedSubjectCount += p->FailedSubjectCount;
        }
        p = p->next;
    }
    printf("        The number of Failed Person: %d\n", FailedPersonCount);
    printf("        The number of Failed Subject: %d\n\n", FailedSubjectCount);
    printf("		Press any key to continue.\n\n");
    getch();
    fclose(f);
}

void FindTop(FILE* f) {
    int count = getCount(f);
//    考虑到代码的健壮性 当文件中没有数据的时候提示用户
    if (!count) {
        printf("	   Empty File!\n\n\n\n");
        printf("	   Press any key to continue.\n\n");
        getch();
        fclose(f);
        return;
    }
    List dummy = Read(f);
    printf("    See Top5 or Last5(T/L)\n\n");
    char choice;
    scanf("%c", &choice);
    getchar();
//    考虑到学生数量不足5个时,
    if(count > 5) count = 5;
    if(choice == 'T' || choice == 't') {
        List Top = DSortList(dummy->next);
        List p = Top;
        for (int i = 1; i <= count; i++) {
            printf("        Top%d: %s\n", i, p->name);
            p = p->next;
        }
    }else if(choice == 'L' || choice == 'l') {
        List Last = ASortList(dummy->next);
        List p = Last;
        for (int i = 1; i <= count; i++) {
            printf("        Last%d: %s\n", i, p->name);
            p = p->next;
        }
    }
    printf("\n");
    printf("	   Press any key to continue.\n\n");
    getch();
    fclose(f);
}

void FindAverage(FILE* f) {
    int count = getCount(f);
//    考虑到代码的健壮性 当文件中没有数据的时候提示用户
    if (!count) {
        printf("		Empty File!\n\n\n\n");
        printf("		Press any key to continue.\n\n");
        getch();
        fclose(f);
        return;
    }
    List dummy = Read(f);
    List p = dummy->next;
//    对课程类进行初始化 
    Subject subject[5];
    for(int i = 0; i < 4; i++) {
    	subject[i].sum = 0;
    	subject[i].aver = 0;
    	subject[i].count = 0;
	}
    strcpy(subject[0].name, "Calculus");
    strcpy(subject[1].name, "Linear Algebra");
    strcpy(subject[2].name, "Physics");
    strcpy(subject[3].name, "Programme C");
//    导入所有学生的信息进行计算每门课程的平均分
    while(p) {
        for(int i = 0; i < 4; i++) {
            subject[i].sum += p->subject[i].aver;
            subject[i].count++;
        }
        p = p->next;
    }
    printf("		Name		Average\n\n");
    for(int i =0; i < 4; i++) {
    	subject[i].aver = subject[i].sum / (subject[i].count * 1.0);
    	printf("        	%s:   	%.2lf\n", subject[i].name, subject[i].aver);
	}
    printf("\n");
    long size = sizeof(Subject);
    qsort(subject, 4, size, cmpD_bySubject);
    printf("		The highest in average is %s\n", subject[0].name);
    printf("		The lowerest in average is %s\n", subject[3].name);
    printf("	        Press any key to continue.\n\n");
    getch();
    fclose(f);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值