目录

First.main()

Second.Enter()

Third.Count()

Forth.Delete()

Fifth.Lookup()

Sixth.Modify()

Seventh.Append()

Eighth.Sort()


本人为大一学生,学C语言时间尚不长,所以本文的解释并不是十分的优美,代码略显臃肿;其次,本人使用的编译器为Visual Studio 2017,有些函数可能与您使用的会有出入(比如scanf与scanf_s,fopen与fopen_s),故请您对于本文仅作参考,希望本文对您有所帮助。


First.main()

首先,本管理系统分为8个函数部分,第一个main()函数部分如下:

#include<stdio.h>
struct Student
{int iNum;char cName[10];int iScore;
}student[10], student1[10];
void functions()
{printf("\t-------------------------------------------------------------------------------------------------\n");printf("\t|             Functions      Menu                     |\n");printf("\t|                 1.Enter (录入)                     |\n");printf("\t|                 2.Delete(删除)                  |\n");printf("\t|                 3.Lookup(查询)                  |\n");printf("\t|                 4.Modify(更改)                  |\n");printf("\t|                 5.Append(添加)                     |\n");printf("\t|                 6.Sort(按成绩排序)                 |\n");printf("\t|                 7.Count(人数)                       |\n");printf("\t-------------------------------------------------------------------------------------------------\n");
}
int main_n;
int main()
{char filename[20];printf("please input the filename:\n");scanf_s("%s", filename, 20);while (1){functions();if (scanf_s("%d", &main_n) == 1){if (main_n <1||main_n>7)return 0;switch (main_n){case 1:Enter(filename);break;case 2:Delete(filename);break;case 3:Lookup(filename);break;case 4:Modify(filename);break;case 5:Append(filename);break;case 6:Sort(filename);break;case 7:Count(filename);break;}}else return 0;}return 0;
}

注:第二行的D:\\c.txt为我已经在D盘中建立的文本文件,在显示出菜单界面后,你只需按下相应功能前的数字即可

如果你输入的不是数字,又会发生什么呢?结果如下:

原因戳这里,或是这里

这是因为数据不对口,返回值不为1,有兴趣的小伙伴可以试一下%c、%lf等,看看输入不对称的值时scanf_s(scanf)的返回值是多少


Second.Enter()

接下来,编写第二个函数Enter(),可以看出其参量为一个字符指针filename,之后的几个函数也是以字符指针为参量:

#include<stdio.h>
extern struct Student
{int iNum;char cName[10];int iScore;
}student[10], student1[10];
void Enter(char *name)
{int enter_n;FILE *fp;printf("How many students do you want to enter:\n");scanf_s("%d", &enter_n);printf("Ok!\n");errno_t err = fopen_s(&fp, name, "w+");if (err != 0){printf("error.");}for (int i = 0; i < enter_n; i++){scanf_s("%d", &student[i].iNum);scanf_s("%s", student[i].cName, 10);scanf_s("%d", &student[i].iScore);}for (int i = 0; i < enter_n; i++){fwrite(&student[i], sizeof(struct Student), 1, fp);}fclose(fp);//一次fopen对应一次fclose,中间只有一次fopen或一次fclose.err = fopen_s(&fp, name, "r+");if (err != 0){printf("error.");}for (int i = 0; i < enter_n; i++){fread(&student1[i], sizeof(struct Student), 1, fp);}fclose(fp);}

注:这里要特别注意的一个前提就是fopen_s和fclose的配对使用,中间只能有一次对文本文件的读取或写入的操作,刚开始编写这个函数时栽了好几个跟头,读者注意这一点

控制台输出如下:


Third.Count()

为了便于读者理解另外几个函数,我们先来介绍Count()函数,其代码如下:

#include<stdio.h>
extern struct Student
{int iNum;char cName[10];int iScore;
}student[10],student1[10];
int Count(char *filename)
{FILE *fp;int count_n = 0;errno_t err = fopen_s(&fp, filename, "r+");if (err != 0){printf("error!");return 0;}while(!feof(fp)){if(fread(&student[count_n], sizeof(struct Student), 1, fp)==1)count_n++;}fclose(fp);printf("There are %d students\n", count_n);return count_n;
}

这个函数的功能主要是确定文件中学生的人数,先定义一个变量count_n,它的值初始化为0,以便每从文件中读取相应的字节数时它的值相应加1,获得正确的总人数。

这个函数的关键部分是:

while(!feof(fp))
{if(fread(&student[count_n], sizeof(struct Student), 1, fp)==1)count_n++;
}

通过feof函数我们才得以实现这个功能,相关知识戳这里。

而为什么我编写这个函数时它的返回值时count_n呢?我明明可以return 0的啊。

这是因为我的本意是想将这个返回的值用作另外几个函数的参量,另外几个函数也会用到Count()函数的关键代码,这样就可以减少一些代码的重复量,但我并没有这样做是因为我想削弱这几个函数间的关联,让它们各司其职,增强它们的可移植性


Forth.Delete()

那么接下来就让我们继续了解第四个函数Delete(),先上代码:

#include<stdio.h>
extern struct Student
{int iNum;char cName[10];int iScore;
}student[10], student1[10];int Delete(char *filename)
{FILE *fp;int delete_n=0,delete_num=0;//delete_n用来保存要删除的数组元素下标,delete_num用来计算总的人数errno_t err = fopen_s(&fp, filename, "r+");if (err != 0){printf("error.");}while (!feof(fp)){if (fread(&student1[delete_num], sizeof(struct Student), 1, fp) == 1)delete_num++;}fclose(fp);for (int i = 0; i < delete_num; i++){printf("%d\t%s\t%d\n", student1[i].iNum, student1[i].cName, student1[i].iScore);}printf("please input the number of the student you want to delete:\n");scanf_s("%d", &delete_n);if (delete_n < 0 || delete_n == 0||delete_n>delete_num){printf("Sorry,I can't help!Cause you input the wrong number!\n");return 0;}for(int i=delete_n;i< delete_num;i++){student1[i-1] = student1[i];}//删除的不是对应学号的学生err = fopen_s(&fp, filename, "w+");if (err != 0){printf("error.");}for (int i = 0; i < delete_num-1; i++){fwrite(&student1[i], sizeof(struct Student), 1, fp);}fclose(fp);return 0;
}

注:代码中已经说过,删除的不是对应学号的学生,这里再强调一遍!

执行后控制台中会一行行列出学生的信息,注意,你如果要删除某个同学的信息,直接输入它所在的行数即可

例如,如果我要删除上图中luog同学的信息,我只需输入2,可如果我输入了他的学号,控制台输出为


Fifth.Lookup()

第五个函数则是Lookup(),用来查询某个学生的信息,上代码:

#include<stdio.h>
extern struct Student
{int iNum;char cName[10];int iScore;
}student[10], student1[10];
int Lookup(char *filename)
{FILE *fp;int lookup_n=0,lookup_num=0;//lookup_n用来计算有多少个学生,lookup_num用来储存要查询的学生学号errno_t err = fopen_s(&fp, filename, "r+");if (err != 0){printf("error!");}while (!feof(fp)){if(fread(&student1[lookup_n],sizeof(struct Student),1,fp)==1)lookup_n++;}fclose(fp);for (int i = 0; i < lookup_n; i++){printf("%d\t%s\t%d\n", student1[i].iNum, student1[i].cName, student1[i].iScore);}printf("please input the homologous number of the student:\n");scanf_s("%d", &lookup_num);for (int i = 0; i < lookup_n; i++){if (student1[i].iNum== lookup_num){printf("\t\tnumber     name     score\n");printf("\t\t%*d%*s%*d\n",6,student1[i].iNum,9, student1[i].cName,10, student1[i].iScore);return 0;}}if (lookup_num<0 || lookup_num>lookup_n)printf("Sorry,but I don't have the information of the student.\n");return 0;
}

这个函数的大部分代码功能前文已经提到,小伙伴们主要的疑问可能是

printf("\t\t%*d%*s%*d\n",6,student1[i].iNum,9, student1[i].cName,10, student1[i].iScore);

为什么会有%*d和%*s中的*呢?这个是为了让输出的代码对齐,如图

并且要注意,这里输入的是学号,不是行数,与Delete()函数刚好相反


Sixth.Modify()

接下来介绍Modify()函数,通过这个函数,我们只要输入对应的学生学号,即可修改对应学生的信息:

#include<stdio.h>
extern struct Student
{int iNum;char cName[10];int iScore;
}student[10], student1[10];
int Modify(char *filename)
{FILE *fp;int modify_n=0, modify_num=0;int iTemp=0;//modify_n用来计算学生个数,modify_num用来保存要更改信息的学生的号码,iTemp用来保存对应学生的下标errno_t err = fopen_s(&fp, filename, "r+");if (err != 0){printf("error!");}while (!feof(fp)){if (fread(&student1[modify_n], sizeof(struct Student), 1, fp) == 1)modify_n++;}fclose(fp);for (int i = 0; i < modify_n; i++){printf("%d\t%s\t%d\n", student1[i].iNum, student1[i].cName, student1[i].iScore);}printf("please input the homologous number of the student:\n");scanf_s("%d", &modify_num);for (int i = 0; i < modify_n; i++){if (student1[i].iNum == modify_num)iTemp = i;}if (iTemp == 0){printf("Not have this student!\n");return 0;}printf("student%d.Num:", iTemp+1);scanf_s("%d", &student1[iTemp].iNum);printf("student%d.Name:", iTemp+1);scanf_s("%s", student1[iTemp].cName,sizeof(student1[iTemp].cName));printf("student%d.Score:", iTemp+1);scanf_s("%d", &student1[iTemp].iScore);putchar('\n');err = fopen_s(&fp, filename, "w+");if (err != 0){printf("error!");return 0;}for (int i = 0; i < modify_n; i++){fwrite(&student1[i], sizeof(struct Student), 1, fp);}fclose(fp);return 0;
}

控制台输出为:

在功能菜单下输入4后,控制台自动打印出已储存的学生信息,这时你只要对照学生信息输入对应的学号即可 。利用这个函数,你不仅可以行使修改功能,也可以全部修改达到替换目的。

细心的读者可以发现,本函数的一个变量modify_n、上一个函数的lookup_n、上上个函数的delete_num,以及接下来要讲解的Append()函数的append_n和Sort()函数的sort_n,与我上文说的那样,都与count_n行使着一样的功能,那就是计算人数。


Seventh.Append()

#include<stdio.h>
extern struct Student
{int iNum;char cName[10];int iScore;
}student[10], student1[10];
int Append(char *filename)
{FILE *fp;int append_n=0;//append_n用来保存学生总人数errno_t err = fopen_s(&fp, filename, "r+");if(err!=0){printf("error!");return 0;}while (!feof(fp)){fread(&student[append_n], sizeof(struct Student), 1, fp);append_n++;}fclose(fp);append_n--;printf("There are %d students.\n", append_n);printf("So student%d.num:", append_n + 1);scanf_s("%d", &student[append_n].iNum);printf("And student%d.name:", append_n + 1);scanf_s("%s", student[append_n].cName,sizeof(student[append_n].cName));printf("Then student%d.score:", append_n + 1);scanf_s("%d", &student[append_n].iScore);err = fopen_s(&fp, filename, "w+");if (err != 0){printf("error!");return 0;}for (int i = 0; i < append_n + 1; i++){fwrite(&student[i], sizeof(struct Student), 1, fp);}fclose(fp);return 0;
}

函数Append()有着与Enter()函数类似的功能,不同的是,Append()函数一次只能输入一个学生的信息,控制台输出如下:

在显示菜单后按5,会显示出“There are X students"的字样,接着会需要你输入新添加的学生的信息,它会自动连接上结构体数组的末尾,即连接上一位同学lu,样式如图:


Eighth.Sort()

接下来介绍最后一个函数Sort(),先上代码:

#include<stdio.h>
#include<stdlib.h>
extern struct Student
{int iNum;char cName[10];int iScore;
}student[10],student1[10];int Sort(char *filename)
{FILE *fp;int sort_n = 0;//sort_n用来计算学生个数struct Student t;errno_t err = fopen_s(&fp, filename, "r+");if (err != 0){printf("error!");return 0;}while (!feof(fp)){if (fread(&student[sort_n], sizeof(struct Student), 1, fp)==1)sort_n++;}fclose(fp);/*for (int i = 0; i < sort_n - 1; i++){for (int j = i; j < sort_n - 1; j++){if (student[i].iScore < student[j + 1].iScore)//若将iScore改成iNum,则按照学号排序{t = student[i];student[i] = student[j + 1];student[j + 1] = t;}}}     //交换排序*//*for (int i = 0; i < sort_n-1; i++){t = student[i];int iTemp = i;//iTemp用来保存对应学生的下标for (int j = i + 1; j < sort_n; j++){if (t.iScore < student[j].iScore){t = student[j];iTemp = j;}}student[iTemp] = student[i];student[i] = t;}        //选择排序*//*for (int i = 0; i < 10; i++){int iTemp=i;//保存特定学生的下标t = student[i]; while ((iTemp-1 >= 0) && (t.iScore > student[iTemp - 1].iScore)){student[iTemp] = student[iTemp - 1];iTemp--;}student[iTemp] = t;}       //插入排序*//*for (int i = 0; i < sort_n ; i++){for (int j = sort_n-1; j > i; j--){if (student[j].iScore > student[j - 1].iScore){t = student[j];student[j] = student[j-1];student[j - 1] = t;}}}       //冒泡排序*/err = fopen_s(&fp, filename, "w+");if (err != 0){printf("error!");return 0;}for (int i = 0; i < sort_n; i++){fwrite(&student[i], sizeof(struct Student), 1, fp);}fclose(fp);printf("I have order the array!\n");for (int i = 0; i < sort_n; i++){printf("%d\t%s\t%d\n", student[i].iNum, student[i].cName, student[i].iScore);}return 0;
}

用/**/括起来的那四段代码,你可以随意选一段去掉/**/后进行使用,这些排序均是按照学生的成绩进行排列的,如果要按照学号排列,只需将iScore改成iNum.

需要注意:

图右下角显示“不能将'struct Student'类型的值分配到'struct Student'类型的实体”,但实际上可以强

制进行使用。

好了,本篇内容到此结束,愿对君有益。


我的下一篇博客:一题多解×1

我的上一篇博客:无

学生信息管理系统(C语言)相关推荐

  1. 学生信息管理系统c语言课设,学生信息管理系统C语言课设.doc

    学生信息管理系统C语言课设 目录 一.需求分析2 二.概要设计2 三.详细设计4 四.调试分析9 五.用户手册9 六.测试数据9 七.附录10 一.需求分析学生学籍管理系统用数据文件存放学生的学籍,可 ...

  2. 用c语言录入3组学生数据编程,学生信息管理系统C语言编程

    学生信息管理系统C语言编程 [问题描述] 学生信息的管理是每个学校必须具有的管理功能,主要是对学生的基本情况及学习成绩等方面的管理.该系统模拟一个简单的学生管理系统,要求对文件中所存储的学生数据进行各 ...

  3. 学生信息管理系统(C语言版本+源码)

    学生信息管理系统(C语言版本) 有需要的可以自行下载 链接:https://download.csdn.net/download/qq_52889967/14955434 源码在后面 java+数据库 ...

  4. c语言学生信息管理ppt,学生信息管理系统(C语言、含代码解释).ppt

    学生信息管理系统(C语言.含代码解释) 第3章 脂类代谢 脂类的分布与生理功能 脂类的消化与吸收 血脂 甘油三酯的中间代谢 类脂代谢 脂类代谢紊乱 3.1 脂类的分布和生理功能 3.1.1 脂类的分布 ...

  5. 显示学生信息的C语言,学生信息管理系统C语言.doc

    学生信息管理系统C语言 学生信息管理系统 摘要 由于学校规模进一步扩大,学生人数逐年上升,学生信息的管理也变得越来越复杂,切实有效的把学生信息管理系统引入学校教务管理中,对于促进学校管理制度和提高学校 ...

  6. 学生信息管理系统(C++语言版)

    学生信息管理系统(C语言版) #include "stdio.h" #include "bios.h" #include "conio.h" ...

  7. 快递信息管理系统源代码c++_学生信息管理系统C语言版

    C语言学生信息管理系统包括以下功能: 1.学生信息的整体注册 2.学生信息的修改 3.学生成绩信息的录入 4.学生信息的添加 5.恢复误删的学生信息 6.学生信息的删除 7.密码修改保存函数 8.学生 ...

  8. c语言程序设计课程设计学生信息管理系统,C语言程序设计课程设计报告----学生信息管理系统.doc...

    河南理工大学计算机学院 <C语言程序设计>课程设计报告 题目: 学生信息管理系统 专业: 计算机科学与技术 班级: 计算机XX班 学号: 311009033232 姓名: ***** 日期 ...

  9. 学生信息管理系统c 语言程序设计报告,C语言程序设计报告(学生信息管理系统)[1].txt...

    C语言程序设计报告(学生信息管理系统)[1].txt C CCCC * * * * * * * * * * * * * * * * .3 3 .4 1. .4 2. 4 3. 4 4. .5 飺 .5 ...

  10. 学生信息管理系统C语言

    用C写的简单的学生成绩管理系统(含源码)(适用于短学期作业) 1.需求分析 我们团队本次选择的问题是学生信息管理系统设计 问题描述:学生的基本个人信息管理,其中个人信息应包含:姓名.性别.年龄.出生年 ...

最新文章

  1. 用c语言实现去bmp图片的背景,菲律宾博牛网-官方网站
  2. SAP 年结(转载)
  3. Qt-qwidget项目入门实例
  4. go python java_一文助你搞懂参数传递原理解析(java、go、python、c++)
  5. STM32 FSMC学习笔记
  6. (android 实战总结)android第三方组件实现总结
  7. 一维卷积神经网络、卷积神经网络的基础知识
  8. 阿里云linux绑定域名
  9. Linux内存管理:ARM64体系结构与编程之cache(1)
  10. 使用CImage类将RGB图像转化为灰度图像
  11. windows下删除文件:提示无法删除文件,无法读源文件或磁盘
  12. Oracle range分区values less than代表的是小于
  13. python 聚宽 对股票名称或代码进行查询
  14. 感知机算法(一)---原理
  15. 一个有趣的网站:子说
  16. php artisan command,artisan command 小技巧
  17. Permit.js – 用于构建多状态原型的 jQuery 插件
  18. Shelve Silently 静默搁置 Android Studio Git 功能
  19. K-Means算法及其变种,优缺点分析笔记
  20. Unity assetstore资源商店 地址

热门文章

  1. 图形验证码知识点整理 Object.prototype.toString.call()等
  2. 【开源.NET】 分享一个前后端分离的轻量级内容管理框架
  3. C++引用之引用的使用
  4. c# 导出Excel
  5. python 实现C atoi函数
  6. java_home的变量是_JAVA坏境变量中的JAVA_HOME path classpath 的设置与作用
  7. 贴片铝电容识别及型号_铝电容和钽电容的区别,你们知道吗?
  8. Jupyter Notebook Virtualenv 添加 卸载环境
  9. 全国计算机网络考试和答案,全国计算机三级《网络技术》复习题及答案2017
  10. TCP数据的传输过程