Linux中的学生管理系统(超详细版本(一))


写的较多,除了整体代码之外,用到什么也会记录下来(看完感觉有用的话给俺评论一下有用,有大佬看的话可以给点建议)

一.设计目的:复习C语言,并且在Linux中使用vim编写学生管理系统,学习使用Makefile将多个文件链接起来。

二.各个模块功能以及实现

1.定义结构体以及结构体的初始化

结构体以及记录过了。学生有以下几个基本信息:姓名、年龄、学号、性别。

重点1:内存问题

tips:结构体的成员在内存中的布局是有内存对齐的。内存对齐是为了优化内存访问的效率和硬件对齐要求而进行的一种处理方式。
请看VCR:

typedef struct{
int age;
char name[50];
int id;
char sex[10];
}student;

当这样定义时,我用sizeof()打印出来的内存大小是72字节

typedef struct{
int age;
int id;
char name[50];
char sex[10];
}student;

当这样定义时,我用sizeof()打印出来的内存大小是68个字节
这两个结构体定义内容是相同的,都是定义了
int age;int id;char name[50]; char sex[10];

但是他们所占用的大小就是不一样。想深入去了解一下的同学可以自己去搜一下关于内存对齐方面的知识。
所以我们在定义结构体的时候,切记把相同类型的变量定义在一块,这样做可以减少对内存的占用,也就是说可以减少浪费空间。

重点2:结构体初始化值问题

就用我们这个学生管理系统举例吧,你在写完结构体的初始化之后,哪怕在代码写完之后,结构体里面的所有值也是通过运行程序的时候在对每一个值进行修改的。但是这些值最开始你是不知道的,也就是野值,这些值是有可能会导致程序出现问题的,我大一写这个代码的时候也没有进行初始化,虽然代码运行起来没有出问题吧,但是现在看起来这样并不好
请看VCR:

#include <stdio.h>
#define MAX 20

typedef struct{
	int age;
	int id;
	char name[50];
	char sex[10];
}student;

int main()
{
	student A[MAX]; //定义一个结构体数组
	for(int i=0;i<MAX;i++)
	{
		printf("A[%d].age:%d   A[%d].id:%d\n", i, A[i].age, i, A[i].id); //用.操作符去访问结构体成员
	}
	return 0;
}

记住多用#define宏定义哦
结果:
在这里插入图片描述
从输出结果可以看出,这个结构体数组内存中的每一个值都是随机的,这样的野值会不会出现问题呢,我想可能是会的,并且就是对于新手来说,可能认为定义了一个结构体变量之后,这个结构体变量就自动初始化赋值为0了,我大一的时候就是这样想的,也可能是我当时学的不到位吧。
这个问题如何解决呢?

函数 void *memset(void *s,int c,size_t n);

这个函数后面具体说,先看代码:

#include <stdio.h>
#include <string.h>
#define MAX 20

typedef struct{
	int age;
	int id;
	char name[50];
	char sex[10];
}student;

int main()
{
	student A[MAX]; //定义一个结构体数组
	memset(A,0,sizeof(student)*MAX);
	
	for(int i=0;i<MAX;i++)
	{
		printf("A[%d].age:%d   A[%d].id:%d\n", i, A[i].age, i, A[i].id); //用.操作符去访问结构体成员
	}
	return 0;
}

这个代码和上面的比起来多了一个头文件string和函数 memset(A,0,sizeof(student)*MAX)
结果:
在这里插入图片描述
现在可以看到每一个值都被初始化为0了
只多了这一行代码,让自己的程序运行起来更加安全,所以兄弟们不要嫌麻烦。
现在说函数:

void *memset(void *s,int c,size_t n);

通过刚刚上面的例子以及可以看出来了,函数memset()一共三个参数,第一个是地址,第二个是值,第三个是大小;
void *s------表示所需要初始化的地址,地址是要用&来进行取址操作的,但是我们是操作数组,所以直接数组名称即可,数组名称放在这里面就是代表数组的首地址开始(不了解的可以在去学习一下数组)

int c---------从代码里面就可以看出来了,表示初始化的值,代码中是0,意思就是这些内存中的值变成0呗

size_t------也可以看出来,我先用一个sizeof(student)去读取出student这一个结构体的长度,然后乘20(也就是MAX)来求出结构体数组A[MAX]所占的内存空间
sizeof()应该都学过怎么用吧,就是读取括号里面的字节大小,这个东西灵活用起来也很厉害

2.main主函数

看VCR:

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

#include "struct.h"  //结构体初始化
#include "menu.h"    //打印首页面
#include "add_student.h" //增加学生
#include "look_student.h" //查看所有学生
#include "find_student.h" //查找学生
#include "change_student.h"//修改学生信息
#include "delete_student.h"//删除学生信息

int size=0;	 //当前学生数量
// 使用嵌套结构体会更好一点,这个弄完后面跟进

int main()
{
	int flag=1,choose=0;flag2=1;
	student ST[STUDENT_MAX]; //定义一个最大为20人的结构体数组
	memset(ST,0,sizeof(student)*STUDENT_MAX); //将结构体数组所有的值清零
	
	while(flag) //循环标志位
	{
		Meun_Display(); //打印首页面
		while(flag2)   //循环标志位
		{
			printf("输入编号:");
			if(scanf("%d", &choose)==1) flag2=0; //标志位置0
			else{
				printf("输入错误,请重新输入!");
				int c;
           		while ((c = getchar()) != '\n' && c != EOF); //清除缓存区
			}
		}
		switch(choose)
		{
			case(1):Add_student(ST);break;   	//添加学生
			case(2):Look_student(ST);break;  	//查看所有学生
			case(3):Find_student(ST);break;  	//查找学生
			case(4):Change_student(ST);break;   //修改学生信息
			case(5):Delete_student(ST);break;   //删除学生信息
			case(6):flag=0;break;              	//标志位置0,退出循环
			default:printf("输入有误,请重新输入!");break;
		}
		return 0;
	}
}

头文件多先不用管,我是因为学习Makefile所以才写在多个文件下的,如果只是单纯的用的话可以把他们放在同一个文件里面就行。
开始解说:

重点1:头文件#include <stdio.h> 和 #include "menu.h"的区别

看代码中可以看出大概有两种头文件类型:

  • 一种是 #include <stdio.h>
  • 一种是 #include “menu.h”
    区别:
    1.< > 尖括号:这种方式用于包含系统头文件。编译器会在系统默认的头文件路径中搜索该文件。一般来说,系统头文件位于操作系统或编译器的标准库中
    2." " 双引号:这种方式用于包含用户自定义的头文件。编译器会先在当前源文件所在目录下搜索该文件,如果找不到,再在系统默认的头文件路径中搜索。用户可以将自定义的头文件放在与源文件相同的目录下,或者在编译时通过指定额外的头文件路径来使编译器能够找到它。
    总结:< >就是在操作系统的标准库里面寻找 ------“xxx"就是在源文件所在文件夹下面找或者指定的地方寻找----------自己定义的头文件一般都使用"xxx”

重点2:scanf的问题

while(flag2)   //循环标志位
		{
			printf("输入编号:");
			if(scanf("%d", &choose)==1) flag2=0; //标志位置0
			else{
				printf("输入错误,请重新输入!");
				int c;
           		while ((c = getchar()) != '\n' && c != EOF); //清除缓存区
			}
		}

这一部分为啥要这样写呢,如果是这样写

	Meun_Display(); //打印首页面
	printf("输入编号:");
	scanf("%d", &choose) 
	switch(choose)
	{
	}
没写的地方和上面一样,自己理解一下

会出现一个问题哈,因为现在scanf()这个函数写入的是int类型的变量,如果输入一个a,b,c,d这种字符型或者不是整型的变量,程序会卡死,会一直循环操作不了。按什么都没用!!!
看VCR:
在这里插入图片描述在这里插入图片描述
这里我输入一个s,然后程序就会卡死,一直循环执行打印首页面。我试过只要是没有进行清除缓存区操作不管是 while for() do{}while(); goto; 只要是循环就会卡死。
函数:

函数:int scanf(const char * restrict format,…);

看一下键盘输入的过程:
在这里插入图片描述

scanf有缓存区,当输入非法字符(要求的类型与输入的类型不符合),scanf会直接跳过,该输入及不会被接受也不会被清除,被存放在scanf的缓存区,当下次调用scanf函数时,会直接从缓存区读取非法字符,造成死循环。

解决办法:很明确,清除缓存区,让下一次输入正常输入即可。

1.函数fflush(stdin);
int a;

fflush(stdin); //缓存区清除函数
scanf("%d", &a);
这样可以解决,在每次输入前将缓存区清除一下就好

但是Linux种gcc没有该函数,就是这个函数用不可了,所以我没用这个‘,想具体了解的去查这个函数。

2.函数getchar()

int getchar():从控制台(键盘)读一个字符

**getchar()**读取字符,不管是空格还是什么,读取到’\n’停止
所以我们用这个函数将缓存区中的所有字符读取出来,相当于清空缓存区了;
注意:当getchar()在读取结束或出现错误时会返回EOF

int c;
while ((c = getchar()) != '\n' && c != EOF) { } // 清空输入缓冲区

肯定不能读取一个字符就停下来,所以使用while来进行一直读取,从代码中可以到,读取到’\n’并且等于EOF(即读取结束)的时候结束循环,就可以做到清空缓存区了。

在主函数main()中看不到结构体的初始化以及符号常量的定义,我把这些放在别的头文件中了

  • 41
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python是一种高级、通用、解释型的编程语言,由Guido van Rossum于1989年发起,1991年正式发布。Python以简洁而清晰的语法著称,强调代码的可读性和易于维护。以下是Python的一些主要特点和优势: 易学易用: Python的语法设计简单直观,更接近自然语言,使初学者更容易上手。这种易学易用的特性促使了Python在教育领域和初学者的广泛应用。 高级语言: Python是一种高级编程语言,提供了自动内存管理(垃圾回收)等功能,减轻了程序员的负担,同时具有动态类型和面向对象的特性。 跨平台性: Python具有很好的跨平台性,可以在多个操作系统上运行,包括Windows、Linux、macOS等,使得开发的代码可以轻松迁移。 丰富的标准库: Python内置了大量的模块和库,涵盖了文件操作、网络编程、数据库访问等各个方面。这些标准库使得开发者能够快速构建功能丰富的应用程序。 开源: Python是开源的,任何人都可以免费使用并查看源代码。这种开放性促进了Python社区的发展,使得有大量的第三方库和框架可供使用。 强大的社区支持: Python拥有庞大而活跃的开发社区,这使得开发者可以轻松获取帮助、分享经验,并参与到Python的发展。 适用于多个领域: Python在各种领域都有广泛的应用,包括Web开发、数据科学、人工智能、自动化测试、网络编程等。特别是在数据科学和人工智能领域,Python成为了主流的编程语言之一。 支持面向对象编程: Python支持面向对象编程,允许开发者使用类和对象的概念,提高了代码的重用性和可维护性。
学生管理系统是一个用于管理学生信息及学生成绩的软件系统。使用Linux C/S架构进行开发,可以实现客户端和服务器的交互,方便管理人员对学生信息的录入、查看、修改和删除等操作。 首先,在服务器端搭建一个数据库,用于存储学生信息和成绩相关的数据。可以使用MySQL或SQLite等数据库管理系统进行数据库的创建和管理,建立学生信息表和成绩表等数据表,同时配置用户权限和访问控制机制,确保数据安全。 其次,在客户端开发学生管理系统的界面,可以使用C语言和GTK+或者Qt等图形界面库进行开发。客户端应具备用户名和密码的登录功能,以保证只有授权人员可以进行操作。登录成功后,可以显示学生列表,并提供添加、修改、删除、查询等功能。 在客户端的界面上,可以设置各种按钮和输入框,方便用户进行操作和输入。例如,可以实现添加学生的功能,通过输入学生的基本信息如姓名、性别、学号等,将这些信息发送到服务器端,并将其存储到数据库。 此外,还可以实现成绩管理的功能,在学生的详细信息界面,可以录入各科目的成绩。在服务器端,可以计算学生的总分、平均分等统计数据,并将成绩存储到数据库。 除此之外,还可以实现查询学生信息的功能,包括按照姓名、学号等条件进行检索,并将查询结果显示在客户端界面上。 在开发过程,还需考虑数据的备份和恢复、用户的权限管理、数据的导入导出等功能。 总之,使用Linux C/S架构进行学生管理系统的开发,可以实现对学生信息和成绩的全面管理,提高学校管理效率,方便管理人员进行相关操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值