欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C语言实现一个列表式的学生信息管理系统(完善)

程序员文章站 2022-05-05 23:15:58
...

http://blog.csdn.net/morixinguan/article/details/77489633

       上节,我们实现了学生信息管理系统的大多数功能,但还有两个功能没有实现,就是学生信息修改还有学生信息删除了。当然,程序中依然存在诸多的BUG,比如,scanfgetchar函数就是一对冤家,如果用了scanf,再调用getchar,就会出现所谓的输入缓冲区问题,导致程序一闪而过。然而解决这种问题的唯一方法就是使用fflush函数,对输入缓冲区,输出缓冲区,出错缓冲区进行刷新。下面是对多数明显的程序BUG进行修复,以及添加了删除和修改的功能。但可能存在一些未发觉的BUG,需要进行程序的压力测试才能得知,但如图所示的基本功能已经完全可以正常工作了。C语言实现一个列表式的学生信息管理系统(完善)C语言实现一个列表式的学生信息管理系统(完善)

         该项目实现的效果如下:

C语言实现一个列表式的学生信息管理系统(完善)

那么这里面用到了window上的那些知识点才可以做到这样的效果呢?上节博文已经给大家介绍了两个博客。当然大家也可以去搜索这本pdf教程:

叫做C/C++控制台界面编程,可以学习下,写出炫酷的控制台程序。

C语言实现一个列表式的学生信息管理系统(完善)

接下来,我们来看下代码的具体实现:

/*
	Copyright (C) 2007 The Windows console C Open Source Project 
	AUTHOR:  Y.X.YANG
	date:	 2017年8月23日
	version: 2.0
	C runtime environment : Windows DevC++ And all Windows development Software
*/
#include <stdio.h>
#include <Windows.h>
#include <conio.h>
#include <stdlib.h>
#include <unistd.h>
#include <tchar.h>
#define   NR(x)   (sizeof(x)/sizeof(x[0]+0))
#define  TITLE  "学生信息管理系统"
#define  AUTHOR "作者:杨源鑫"
#define  DATE   "日期:2017年8月23日 version2"
#define  SIZE   100
//在终端上打印信息
#define Print_Info_To_console(str,hOut,pos,x,y,color_type) \
	SetConsoleTextAttribute(hOut, color_type); 	\
	pos.X = x;									\
	pos.Y = y ;									\
	SetConsoleCursorPosition(hOut,pos);    		\
	printf("%s",str);							

//清屏
#define ClearScreen() \
	    system("cls");

	
//定义枚举Keyboard的键值数据 
enum 
{
	UP = 72,
	DOWN = 80 ,
	LEFT = 75 ,
	RIGHT = 77 ,
	ENTER = 13 ,
	ESC = 27 ,
};

//存储学生信息的结构体
struct student
{
	char name[20] ; //名字
	int  id ; 	    //学生ID
	float score ;   //分数
};



//定义要显示的菜单 
char *menu[] = 
{
	"*学生信息添加*",
	"*学生信息查找*",
	"*学生信息打印*",
	"*学生信息修改*",
	"*学生信息删除*",
	"*学生信息保存*",
	"*学生信息导入*",
	"*    退出    *",
};


//窗口初始化
void HANDLE_init(HANDLE hOut);
//显示菜单 
void showmenu(HANDLE hOut ,char **menu , int size , int index) ;
//获取用户输入 
int  get_userinput(int *index , int size) ;
//学生信息添加
void stu_add(HANDLE hOut);
//学生信息打印
void stu_show(HANDLE hOut);
//学生信息查找
void stu_search(HANDLE hOut);
//学生信息保存
void stu_save(HANDLE hOut);
//学生信息导入
void stu_load(HANDLE hOut);
//学生信息修改
void stu_modefi(HANDLE hOut);
//学生信息删除
void stu_delete(HANDLE hOut);


//学生的个数
int stucount ; 
//定义一个数组,用于存储学生信息  
struct student array[SIZE] = {0}; 
//定义设置光标结构体变量
CONSOLE_CURSOR_INFO cci; 
//定义默认的坐标位置  	
COORD pos = {0,0};


int main()
{
    int i;
    int ret ;
    int index = 0 ;
    HANDLE hOut;
	hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	HANDLE_init(hOut);
    while(1)
    {
    	showmenu(hOut , menu , NR(menu) , index);
		ret = get_userinput(&index , NR(menu));
		if(ret == ESC)
			break ;
		if(ret == ENTER)
		{
			switch(index)
			{
				case 0:  stu_add(hOut) ; break ;  	//学生信息添加
				case 1:  stu_search(hOut);break ;   //学生信息查找
				case 2:  stu_show(hOut); break ;  	//学生信息打印
				case 3:  stu_modefi(hOut); break ;  //学生信息修改
				case 4:  stu_delete(hOut); break ;  //学生信息删除
				case 5:  stu_save(hOut); break ; 	//学生信息保存
				case 6:  stu_load(hOut); break ;    //学生信息导入
				case 7:  ClearScreen();return 0 ;   //退出学生信息管理系统
			}
		}
	}
	//关闭窗口句柄
	CloseHandle(hOut);
    return 0;
}

//窗口初始化
void HANDLE_init(HANDLE hOut)
{
	SetConsoleTitleA(TITLE);
	//获取当前的句柄---设置为标准输出句柄 
    //获取光标信息
    GetConsoleCursorInfo(hOut, &cci); 
	//设置光标大小   
    cci.dwSize = 1; 
	//设置光标不可见 FALSE   
    cci.bVisible =  0; 
    //设置(应用)光标信息
    SetConsoleCursorInfo(hOut, &cci); 
}

//菜单初始化
void showmenu(HANDLE hOut ,char **menu , int size , int index)
{
	int i ; 
	ClearScreen();	
	Print_Info_To_console(TITLE,hOut,pos,30,0,FOREGROUND_GREEN | 0x8);
	Print_Info_To_console(AUTHOR,hOut,pos,32,1,FOREGROUND_GREEN | 0x8);
	Print_Info_To_console(DATE,hOut,pos,25,2,FOREGROUND_GREEN | 0x8);
	Print_Info_To_console("请按↑↓←→按键选择,并用Enter按键确认",hOut,pos,20,20,FOREGROUND_GREEN | 0x8);
	for(i = 0 ; i < size ; i++)
	{
		//如果i==index表示在当前选项的位置,默认初始化显示是第一项,显示为红色,
		//当按下上下按键选择的时候,光标会移动,也就看到了列表选择的现象 
		if(i == index){
			Print_Info_To_console(menu[i],hOut,pos,30,i+5,FOREGROUND_RED | 0x8);
		}
		else{
			Print_Info_To_console(menu[i],hOut,pos,30,i+5,FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | 0x8);			
		}
	}
	//刷新标准输出缓冲区 
	fflush(stdout);
}

//获取用户输入的接口 
int  get_userinput(int *index , int size)
{
	int ch ;
	fflush(stdin);
	ch = getch();
	switch(ch)
	{
		//上 
		//如果选择上,那么光标向上移动 
		case UP : if(*index > 0)  *index -= 1 ;  break; 
		//下 
		//如果选择下,那么光标向下移动 
		case DOWN :if(*index < size -1)  *index += 1 ;  break;
		//左 
		case LEFT: 
		case 97:return 0 ;
		//右 
		case RIGHT:return 0 ;
		//回车 
		case ENTER: return ENTER ;
		//ESC
		case ESC: return ESC ;
	}
	return 0 ;
}

//学生信息添加
void stu_add(HANDLE hOut)
{
	ClearScreen();	
	if(stucount >= SIZE){
		Print_Info_To_console("学生信息已经满了\n",hOut,pos,30,0,FOREGROUND_RED | 0x8);
	}
	Print_Info_To_console("学生信息添加\n",hOut,pos,30,0,FOREGROUND_GREEN | 0x8);
	printf("学生姓名:");
	scanf("%s" , array[stucount].name);
	printf("\n学生ID:");
	scanf("%d" , &(array[stucount].id));
	printf("\n学生成绩:");
	scanf("%f" , &(array[stucount].score));
	stucount++ ; 
	 //清掉输入缓冲区中的\n
	getchar();  
	fflush(NULL);
}

//学生信息打印
void stu_show(HANDLE hOut)
{
	int i ; 
	ClearScreen();	
	fflush(stdin);
	fflush(stdout);
	Print_Info_To_console("学生信息打印\n",hOut,pos,30,0,FOREGROUND_GREEN | 0x8);
	for(i = 0 ; i < stucount ; i++)
	{
		SetConsoleTextAttribute(hOut, FOREGROUND_RED| 0x8); 
		pos.X = 1;
		pos.Y = i+4 ;
		SetConsoleCursorPosition(hOut,pos); 
		printf("ID:%2d ",array[i].id);
		printf("姓名:%s ",array[i].name);
		printf("分数:%4.1f ",array[i].score);
	}
	fflush(stdout);
	Print_Info_To_console("Please press any key to continue ... \n",hOut,pos,0,20,FOREGROUND_GREEN | 0x8);
	getchar(); 
}
//查找ID
static void search_id(HANDLE hOut,int id)
{
	ClearScreen();	
	Print_Info_To_console("查找到学生的信息\n",hOut,pos,30,0,FOREGROUND_GREEN | 0x8);
	fflush(stdout);
	int i ,j ,flag = 0; 
	for(i = 0 , j = 0 ; i < stucount ; i++)
	{
		if(array[i].id == id)
		{
			flag = 1 ;
			SetConsoleTextAttribute(hOut, FOREGROUND_RED| 0x8); 
			pos.X = 1;
			pos.Y = j+4 ;
			SetConsoleCursorPosition(hOut,pos); 
			printf("ID:%2d ",array[i].id);
			printf("姓名:%s ",array[i].name);
			printf("分数:%f ",array[i].score);
			j++ ; 
		}
	}
	if(flag == 0)
	{
		Print_Info_To_console("找不到该学生的ID,请按任意按键返回主菜单!\n",hOut,pos,0,20,FOREGROUND_RED | 0x8);
		getchar();
	}
	if(flag == 1)
	{
		fflush(stdout);
		Print_Info_To_console("Please press any key to continue ... \n",hOut,pos,0,20,FOREGROUND_GREEN | 0x8);
		getchar(); 
	}
}
//查找姓名
static void search_name(HANDLE hOut,const char *name)
{
	ClearScreen();	
	Print_Info_To_console("查找到学生的信息\n",hOut,pos,30,0,FOREGROUND_GREEN | 0x8);
	fflush(stdout);
	int i , j , flag = 0; 
	for(i = 0 , j = 0; i < stucount ; i++)
	{
		if(strcmp(array[i].name , name) == 0)
		{
			flag = 1 ;
			SetConsoleTextAttribute(hOut, FOREGROUND_RED| 0x8); 
			pos.X = 1;
			pos.Y = j+4 ;
			SetConsoleCursorPosition(hOut,pos); 
			printf("ID:%2d ",array[i].id);
			printf("姓名:%s ",array[i].name);
			printf("分数:%f ",array[i].score);
			j++ ; 
		}
	}
	if(flag == 0)
	{
		Print_Info_To_console("找不到该学生的姓名,请按任意按键返回主菜单!\n",hOut,pos,0,20,FOREGROUND_RED | 0x8);
		getchar();
	}
	if(flag == 1)
	{
		fflush(stdout);
		Print_Info_To_console("Please press any key to continue ... \n",hOut,pos,0,20,FOREGROUND_GREEN | 0x8);
		getchar();
	}
}

//学生信息查找
void stu_search(HANDLE hOut)
{
	char ch ; 
	int id ; 
	char name[30] ; 
repeat:
	ClearScreen();	
	Print_Info_To_console("学生信息查找\n",hOut,pos,30,0,FOREGROUND_GREEN | 0x8);
	Print_Info_To_console("请选择按什么方式查找学生信息 :\n",hOut,pos,20,0,FOREGROUND_GREEN | 0x8);
	Print_Info_To_console("			1.ID \n",hOut,pos,10,1,FOREGROUND_GREEN | 0x8);
	Print_Info_To_console("			2.NAME \n",hOut,pos,10,2,FOREGROUND_GREEN | 0x8);
	fflush(stdout);
	//获取要输入的信息
	ch = getch();  
	if(ch == '1')
	{
		ClearScreen();	
		Print_Info_To_console("请输入学生ID: ",hOut,pos,0,1,FOREGROUND_GREEN | 0x8);
		fflush(stdout);
		scanf("%d" , &id);
		getchar();
		if(id < 0)
		{
			getchar();
			Print_Info_To_console("请入ID有误,请按任意键重新选择输入\n",hOut,pos,0,20,FOREGROUND_RED | 0x8);
			getchar();  
			goto repeat;
		}
		search_id(hOut,id);
	}
	if(ch == '2')
	{
		printf("请输入学生NAME: ");
		fflush(stdout);
		scanf("%s" , name);
		getchar();
		search_name(hOut,name);
	}
	if(ch != '1' && ch != '2')
	{
		goto repeat;
	}
}

//学生信息保存
void stu_save(HANDLE hOut)
{
	FILE *filp = NULL ; 
	char ch ; 
	char Path[30] ; 
repeat1:
	ClearScreen();	
	Print_Info_To_console("学生信息保存\n",hOut,pos,30,0,FOREGROUND_GREEN | 0x8);
	Print_Info_To_console("请选择按什么方式保存学生信息 :\n",hOut,pos,20,0,FOREGROUND_GREEN | 0x8);
	Print_Info_To_console("			1.追加 \n",hOut,pos,10,1,FOREGROUND_GREEN | 0x8);
	Print_Info_To_console("			2.覆盖 \n",hOut,pos,10,2,FOREGROUND_GREEN | 0x8);
	fflush(stdout);
	ch = getch();  
	ClearScreen();	
	Print_Info_To_console("请输入保存文件名:\n",hOut,pos,0,1,FOREGROUND_GREEN | 0x8);
	scanf("%s" , Path);
	getchar();
	if(ch == '1')
	{
		filp = fopen(Path , "a+");
		if(NULL == filp)
		{
			Print_Info_To_console("文件打开失败 \n",hOut,pos,0,20,FOREGROUND_RED | 0x8);
			Print_Info_To_console("请按任意键重新选择输入 \n",hOut,pos,0,21,FOREGROUND_RED | 0x8);
			getchar(); 
			goto  repeat1;
		}
	}
	if(ch == '2')
	{
		filp = fopen(Path , "w+");
		if(NULL == filp)
		{
			Print_Info_To_console("文件打开失败 \n",hOut,pos,0,20,FOREGROUND_RED | 0x8);
			SetConsoleTextAttribute(hOut, FOREGROUND_RED | 0x8); 
			Print_Info_To_console("请按任意键重新选择输入 \n",hOut,pos,0,21,FOREGROUND_RED | 0x8);
			getchar(); 
			goto  repeat1;
		}
	}
	if(ch != '1' && ch != '2')
	{
		goto repeat1;
	}

	int i ; 
	for(i = 0 ; i < stucount ; i++)
	{
		fwrite(&(array[i]) , sizeof(struct student) , 1 , filp);
	}
	fclose(filp);
	Print_Info_To_console("学生信息保存完毕\n",hOut,pos,0,20,FOREGROUND_GREEN | 0x8);
	sleep(1) ; 
}
//学生信息装载
void stu_load(HANDLE hOut)
{
	int i ; 
	FILE *filp = NULL ; 
	char Path[30] ; 
	ClearScreen();	
	Print_Info_To_console("学生信息加载\n",hOut,pos,30,0,FOREGROUND_GREEN | 0x8);
	Print_Info_To_console("请输入导入文件名 :\n",hOut,pos,0,1,FOREGROUND_GREEN | 0x8);
	scanf("%s" , Path);
	filp = fopen(Path , "r");
	if(NULL == filp)
	{
		Print_Info_To_console("文件打开失败 \n",hOut,pos,0,20,FOREGROUND_RED | 0x8);
		SetConsoleTextAttribute(hOut, FOREGROUND_RED | 0x8); 
		Print_Info_To_console("请按任意键退出 \n",hOut,pos,0,21,FOREGROUND_RED | 0x8);
		fflush(stdin);
		fflush(stdout); 
		getchar();
		return ;
	}
	char buffer[1024] ; 
	char *p = NULL ; 
	int ret ; 
	while(1)
	{
		ret = fread(&(array[stucount]) , sizeof(struct student) , 1 , filp);
		if(ret != 1)
			break;
		stucount++ ; 
	}
	fclose(filp);
	ClearScreen();	
	Print_Info_To_console("学生信息导入完毕\n",hOut,pos,0,20,FOREGROUND_GREEN | 0x8);
	sleep(1);
}
//学生信息修改
void stu_modefi(HANDLE hOut)
{
	int id ; 
	int flag = 0 ;
	int location ;
	char ch ;
	replay:
	ClearScreen();	
	Print_Info_To_console(" 学生信息修改\n",hOut,pos,30,0,FOREGROUND_GREEN | 0x8);
	Print_Info_To_console("请输入学生ID: ",hOut,pos,0,1,FOREGROUND_GREEN | 0x8);
	fflush(stdout);
	scanf("%d" , &id);
	int i ; 
	for(i = 0 ; i < stucount ; i++)
	{
		//如果ID匹配,也就是查找到这个学生的信息了
		if(array[i].id == id)
		{
			flag = 1 ;
			//保存当前数组的位置
			location = i ;
			break ;
		}
	}
	//判断是否匹配成功的标志
	if(flag == 1){
		flag = 0 ;
		//打印该学生的信息
		ClearScreen();	
		Print_Info_To_console("找到该学生的信息如下:\n",hOut,pos,15,0,FOREGROUND_GREEN | 0x8);
		SetConsoleTextAttribute(hOut, FOREGROUND_GREEN| 0x8); 
		pos.X = 0;
		pos.Y = 1 ;
		SetConsoleCursorPosition(hOut,pos); 
		printf("ID:%2d ",array[i].id);
		SetConsoleTextAttribute(hOut, FOREGROUND_GREEN| 0x8); 
		pos.X = 0;
		pos.Y = 2 ;
		SetConsoleCursorPosition(hOut,pos); 
		printf("姓名:%s ",array[i].name);
		SetConsoleTextAttribute(hOut, FOREGROUND_GREEN| 0x8); 
		pos.X = 0;
		pos.Y = 3 ;
		SetConsoleCursorPosition(hOut,pos); 
		printf("分数:%f ",array[i].score);
	}
	else
	{
		Print_Info_To_console("请入ID有误,请按任意键重新选择输入\n",hOut,pos,0,1,FOREGROUND_RED | 0x8);
		fflush(stdin);
		getchar();
		goto replay ;
	}
	//询问是否需要修改
	Print_Info_To_console("请问是否需要修改该学生的信息?按1确定,按2退回到主菜单\n",hOut,pos,0,4,FOREGROUND_GREEN | 0x8);
	//刷新输出缓冲区
	fflush(stdout);
	//刷新输入缓冲区
	fflush(stdin);
	ch = getch();
	ClearScreen();	
	if(ch == '1')
	{
		//是否需要修改学生的ID?
		Print_Info_To_console("是否需要修改学生的ID?按1确定,按2不需要\n",hOut,pos,0,1,FOREGROUND_GREEN | 0x8);
		fflush(stdout);
		fflush(stdin);
		ch = getch();
		if(ch == '1')
		{
			ClearScreen();	
			Print_Info_To_console("修改学生ID为:",hOut,pos,0,1,FOREGROUND_GREEN | 0x8);
			scanf("%d" , &(array[location].id));
			Print_Info_To_console("修改学生ID成功,请按任意键返回主菜单\n",hOut,pos,0,2,FOREGROUND_GREEN | 0x8);
			sleep(2);
			fflush(stdin);
			getchar();
			return ;
		}
		if(ch == '2')
		{
			//是否需要修改学生的姓名
			ClearScreen();	
			Print_Info_To_console("是否需要修改学生的姓名?按1确定,按2不需要\n",hOut,pos,0,1,FOREGROUND_GREEN | 0x8);
			fflush(stdout);
			fflush(stdin);
			ch = getch();
			if(ch == '1')
			{
				ClearScreen();	
				Print_Info_To_console("修改学生姓名为:",hOut,pos,0,1,FOREGROUND_GREEN | 0x8);
				scanf("%s" , array[location].name);
				Print_Info_To_console("修改学生姓名成功,请按任意键返回主菜单\n",hOut,pos,0,2,FOREGROUND_GREEN | 0x8);
				sleep(1);
				fflush(stdin);
				getchar();
				return ;
			}
			if(ch == '2')
			{
				//是否需要修改学生的成绩
				ClearScreen();	
				Print_Info_To_console("是否需要修改学生的成绩?按1确定,按2不需要\n",hOut,pos,0,1,FOREGROUND_GREEN | 0x8);
				fflush(stdout);
				fflush(stdin);
				ch = getch();
				if(ch == '1')
				{
					ClearScreen();	
					Print_Info_To_console("修改学生成绩为:",hOut,pos,0,1,FOREGROUND_GREEN | 0x8);
					scanf("%f" , &(array[location].score));
					Print_Info_To_console("修改学生成绩成功,请按任意键返回主菜单\n",hOut,pos,0,2,FOREGROUND_GREEN | 0x8);
					sleep(1);
					fflush(stdin);
					getchar();
					return ;
				}
				if(ch == '2')
				{
					return ;
				}
			}
		}
	}
	if(ch == '2')
	{
		Print_Info_To_console("请按任意键返回主菜单\n",hOut,pos,0,2,FOREGROUND_GREEN | 0x8);
		fflush(stdin);
		getchar();
		return ;
	}
}
//学生信息删除
void stu_delete(HANDLE hOut)
{
	char ch ; 
	int id ; 
	char name[30] ; 
repeat3:
	ClearScreen();	
	Print_Info_To_console(" 学生信息删除\n",hOut,pos,30,0,FOREGROUND_GREEN | 0x8);
	Print_Info_To_console(" 请选择按什么方式删除学生信息 :\n",hOut,pos,20,0,FOREGROUND_GREEN | 0x8);
	Print_Info_To_console("			1.ID",hOut,pos,10,1,FOREGROUND_GREEN | 0x8);
	Print_Info_To_console("			2.NAME\n",hOut,pos,10,2,FOREGROUND_GREEN | 0x8);
	fflush(stdout);
	ch = getch(); 
	ClearScreen();	
	int i , j ; 
	if(ch == '1')
	{
		Print_Info_To_console("请输入ID:\n",hOut,pos,0,1,FOREGROUND_GREEN | 0x8);
		scanf("%d" , &id);
		getchar();
		for(i = 0 ; i < stucount ; i++)
		{
			if(array[i].id == id)
			{
				SetConsoleTextAttribute(hOut, FOREGROUND_RED| 0x8); 
				printf("删除 : ID:%d  NAME:%s  score:%f\n" , array[i].id , array[i].name , array[i].score);
				for(j = i ; j < stucount -1 ; j++)
					array[j] = array[j+1] ;
				stucount-- ;
				break ;
			}
		}
	}
	if(ch == '2')
	{
		Print_Info_To_console("请输入NAME:\n",hOut,pos,0,1,FOREGROUND_GREEN | 0x8);
		scanf("%s" , name);
		getchar();
		for(i = 0 ; i < stucount ; i++)
		{
			if(strcmp(array[i].name , name) == 0)
			{
				SetConsoleTextAttribute(hOut, FOREGROUND_RED| 0x8); 
				printf("删除 : ID:%d  NAME:%s  score:%f\n" , array[i].id , array[i].name , array[i].score);
				for(j = i ; j < stucount -1 ; j++)
					array[j] = array[j+1] ;
				stucount-- ;
				break ;
			}
		}
	}
	if(ch != '1' && ch != '2')
	{
		goto repeat3;
	}
	sleep(1);
}
重点看下最新的两个接口的更新演示过程:

学生信息修改演示:

C语言实现一个列表式的学生信息管理系统(完善)

学生信息删除演示:

C语言实现一个列表式的学生信息管理系统(完善)