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

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语言实现一个列表式的学生信息管理系统(完善)




    


上一篇:国家信息中心宁家骏:中国经济稳中向好 互联网+、信息化需求紧迫


下一篇:开源社区Open-O技术峰会圆满落幕,Release1.0步入正轨