学生信息管理系统(C语言)

学生信息管理系统(C语言),第1张

学生信息管理系统(C语言)

目录

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
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
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
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 studentsn", 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
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("%dt%st%dn", 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
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("%dt%st%dn", 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("ttnumber     name     scoren");
			printf("tt%*d%*s%*dn",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("tt%*d%*s%*dn",6,student1[i].iNum,9, student1[i].cName,10, student1[i].iScore);

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

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


Sixth.Modify()

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

#include
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("%dt%st%dn", 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()

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

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


 Eighth.Sort()

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

#include
#include
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);
	
	
	
	
	
	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("%dt%st%dn", student[i].iNum, student[i].cName, student[i].iScore);
	}
	return 0;
}

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

需要注意:

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


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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5097229.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-16
下一篇 2022-11-16

发表评论

登录后才能评论

评论列表(0条)

保存