C语言课程设计模板

首先看一张自制的设计框架:
在这里插入图片描述

我个人觉得在设计c语言信息管理系统中,基本都是以上的框架
例如:
1、学生信息管理系统
2、酒店客房管理系统
3、火车售票管理系统
4、职工信息管理系统
5、图书信息管理系统
这类系统,无非就是把数据从磁盘中拿出来,再对数据秀一番操作后,又写入到磁盘中,整体这样去看待就简单多了
类似以上的系统,都可以套用下面的模板进行自行修改使用

其中主要难点:
1、结构体数组、结构体链表
2、标准文件I/O操作
3、程序设计的熟练

接下来上代码:

//编译环境:Dev c++编译器 (不同的编译器可能有细微的差别,可自行改动调试) 
//编译语言:C
//数据结构:结构体、单链表
//可以套用大多数的信息管理系统

//框架与设计介绍:

//1、登录模块
//2、功能子模块
//3、主菜单调用 

//其中可扩展部分在框内自行添加,无需改动的会标注 

#include<stdio.h>
struct Information
{
	char name[20];	//姓名
	char number[20];//编号
	int age;		//年龄
	//**自行添加**
	struct Information *next;//连接下一个节点
};
const unsigned char allchar[63] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";//随机产生字符串使用 
char Str[10];//随机产生字符串使用 


/////////////////////////////////////////  1、登陆模块  ////////////////////////////////////////// 
void Verification()		//随机产生字符串
{
	int i=6;
	srand((unsigned int)time(NULL));
	while(i--)
	{
		Str[5-i]=allchar[rand()%62];
	}
	Str[5]='\0';
}
  

void Validation(char account[],char password[])	//函数用于验证账号密码的正确性
{
	char s_account[20],s_password[20],s_verification[10];
	while(1){	
	printf("请输入账户:");
	scanf("%s",&s_account);
	printf("请输入密码:"); 
	scanf("%s",&s_password);
	Verification();							//调用函数产生验证码 
	printf("请输入验证码(%s):",Str);
	scanf("%s",&s_verification);
	if((strcmp(s_account,account)==NULL)&&(strcmp(s_password,password)==NULL))	//如果账户和密码正确
	{
		if((strcmp(Str,s_verification)==NULL))
		{
			printf("登陆成功!\n");
			break;
		}
		printf("验证码错误!\n");
		Sleep(2000);
		system("cls"); 
		continue; 
	}
	printf("账户或密码验证失败!\n");
	Sleep(2000);
	system("cls"); 
	}
}
void Landing()		//函数用于从磁盘中读取账户和密码数据,并且传递给 Validation函数进行验证 
{
	//打开Landing.txt文件,读取账户和密码信息
	char account[20];	//账号
	char password[20];	//密码
	char Verification[10];	//验证码
	 
	FILE *fp;
	if((fp=fopen("Landing.txt","r"))==NULL)
	{
		printf("Landing.txt文件打开失败!\n");
		exit(0);
	}
	fscanf(fp,"账号: %s 密码: %s\n",&account,&password);
	fclose(fp);
	Validation(account,password);	//把磁盘中的账户和密码传入验证函数
}


////////////////////////////////////  2、功能子模块   //////////////////////////////////////// 

//**自行添加别的函数模块**

struct Information * Initialize(struct Information *head)	//调用函数进行初始化(从磁盘文件中读取信息)
{
	FILE *fp;
	struct Information *p,*q;		//head指向链表头,q和q来进行尾插法 
	p=q=NULL;
	if((fp=fopen("data.txt","r"))==NULL)//判断文件是否正确打开 
	{
		printf("file open fail !\n");
		exit(0);
	}
	if(fgetc(fp)==EOF)		//判断文件是否为空 
	{
		printf("磁盘文件为空!\n");
		return(head);
	}
	rewind(fp);			//由于上面fgetc使文件位置指针移动,让其还原 
	head=q=p=(struct Information *)malloc(sizeof(struct Information));	//分配空间 
	
	//**fscanf按照结构体自行修改,不懂格式看链接:https://blog.csdn.net/qq_42856154/article/details/93225821 掌握文件I/O操作**
	fscanf(fp,"姓名:%s 编号:%s 年龄:%d\n",p->name,p->number,&p->age);		//已经判断文件有数据,读取第一个数据,作为头节点 
	
	while(!feof(fp))	//feof(fp):当返回值为1时,文件到达尾部当返回值为0时,文件未到达尾部  
	{
		p=(struct Information *)malloc(sizeof(struct Information));
		
		//**fscanf按照结构体自行修改
		fscanf(fp,"姓名: %s 编号:%s 年龄: %d\n",p->name,p->number,&p->age);	//格式读取信息,一次一行 
		q->next=p;
		q=p;
	}
	p->next=NULL;		//尾节点next域赋值为NULL 
	p=q=NULL;			//指针指向为NULL 
	fclose(fp);			
	return(head);		//返回链表的头指针 
}




struct Information * Increase(struct Information *head)		//增加节点(在链表尾增加) 
{
	struct Information *p,*q;
	q=head;
	
	p=(struct Information *)malloc(sizeof(struct Information));
	
	//**按照自己定义的结构体自行修改 
	printf("请输入姓名:");
	scanf("%s",p->name);
	printf("请输入编号:");
	scanf("%s",p->number);
	printf("请输入年龄:");
	scanf("%d",&p->age);
	
	p->next=NULL;
	if(head==NULL)		//当头节点不存在时,把创建的节点直接当作头节点 
	{
		head=p;
	}
	else
	{
		while(q->next!=NULL)
			q=q->next;
		q->next=p;
	}
	q=p=NULL;
	printf("增加成功!\n");
	return head;
}

struct Information * Delete(struct Information *head)		//删除节点 (按编号删除)
{
	int i=0;
	char num[20];
	struct Information *p,*q;
	p=q=head;
	printf("请输入要删除的编号:");
	scanf("%s",num);
	while(q!=NULL)
	{
		if(i>1)p=p->next;
		i++;
		if((strcmp(num,q->number)==NULL))
		{
			printf("已经找到是第 %d 个节点\n",i);
			goto delete;
		}
		q=q->next;
	}
	printf("该编号信息不存在!\n");
	return head;
	
delete:
	if(i==1)			//删除头节点 
	{
		head=q->next;
		printf("头节点删除成功!\n");
		return head;
	}
	if(q->next==NULL)	//删除尾节点 
	{
		p->next=NULL;
		p=q=NULL;
		return head;
	}
	p->next=q->next;	//删除中间节点  
	free(q);
	q=NULL;
	printf("删除成功!\n"); 
	return head;
}

int Find(struct Information *head)		//查找节点信息 (按编号查找)
{
	int i=0;
	char num[20];
	printf("请输入要查找的编号:");
	scanf("%s",num);
	while(head!=NULL)
	{
		i++;
		if((strcmp(num,head->number)==NULL))
		{
			printf("已经找到在: %d 个节点\n",i);
			
			//**printf按照结构体自行修改
			printf("姓名: %s 编号:%s 年龄: %d\n",head->name,head->number,head->age);
			return 0;
		}
		head=head->next;
	}
	printf("该编号信息不存在!\n");
	return 0;
}

int Change(struct Information *head)		//修改节点信息 (按编号修改)
{
	//该函数可以做成(按照名称、学好、编号查找,本例为编号查找),可以自行修改 
	char num[20];
	printf("请输入要修改的编号:");
	scanf("%s",num);
	while(head!=NULL)
	{
		if((strcmp(num,head->number)==NULL))
		{
			printf("姓名: %s 编号:%s 年龄: %d\n",head->name,head->number,head->age);
			printf("请输入除编号外的其它信息\n\n");
			printf("请输入姓名:");
			scanf("%s",head->name);
			printf("请输入年龄:");
			scanf("%d",&head->age);
			printf("姓名: %s 编号:%s 年龄: %d\n",head->name,head->number,head->age);
			printf("\n修改成功!\n");
			return 0;
		}
		head=head->next;
	}
	printf("该编号信息不存在!\n");
	return 0;
}

int Print_list(struct Information *head)	//打印链表数据 
{
	if(head==NULL)
	{
		printf("链表为空!\n");
		return 0;
	}
	while(head!=NULL)		//当头指针不为NULL,表示头节点有数据 
	{
		
		//**printf按照结构体自行修改
		printf("姓名: %s 编号:%s 年龄: %d\n",head->name,head->number,head->age);
		head=head->next;
	}
	return 0;
}


void Save(struct Information *head)
{
	FILE *fp;
	if((fp=fopen("data.txt","w"))==NULL)//判断文件是否正确打开 
	{
		printf("file open fail !\n");
		exit(0);
	}
	while(head!=NULL)
	{
		
		//**fprintf按照结构体自行修改
		fprintf(fp,"姓名: %s 编号:%s 年龄: %d\n",head->name,head->number,head->age);
		head=head->next;
	}
	printf("保存磁盘成功!\n");
	fclose(fp);
}


///////////////////////////////////     3、主菜单调用     ///////////////////////////////////////////
void Menu()
{
	Sleep(2000);
	system("cls");
	
	//**按照函数功能自行修改菜单目录
	 
	printf("\t\t\t*****功能主菜单*****\n\n\n");
	printf("\t\t*** 增加节点 ***\t\t--1\n");
	printf("\t\t*** 删除节点 ***\t\t--2\n");
	printf("\t\t*** 修改节点 ***\t\t--3\n");
	printf("\t\t*** 查询节点 ***\t\t--4\n");
	printf("\t\t*** 打印链表 ***\t\t--5\n");
	printf("\t\t*** 保存磁盘 ***\t\t--6\n");
	printf("\t\t*** 退出系统 ***\t\t--7\n");
} 


int main()
{
	//main函数内可能变化较大,所以根据自己的喜好进行排布代码 
	
	int flag = 1;
	int n;
	struct Information *Head = NULL;	//头指针(头指针为空,只是用来指向头节点)
	Landing();			//1、登陆模块调用,使用默认的账户和密码进行验证(**登陆**) 
	Head = Initialize(Head);	//2、调用函数进行初始化(**从磁盘文件中读取信息恢复链表**)
	
	while(flag)
	{
		Menu();
		printf("请选择:");
		scanf("%d",&n);
		switch(n)
		{
			case 1:Head = Increase(Head);break;
			case 2:Head = Delete(Head);break;
			case 3:Change(Head);break;
			case 4:Find(Head);break;
			case 5:Print_list(Head);break;
			case 6:Save(Head);break;
			case 7:flag = 0;break;
			default:printf("输入错误!\n");	
		}
	} 
	return 0;
}

代码总体不长,但基本功能很完善,但严格来测试会存在数据BUG,但作为学习是可以的

做了一些这类程序,最大的感受就是:(先栽树,再去修剪枝干和美化叶子)

OK
代码大致介绍:
1、语言:C语言
2、数据结构:结构体链表作为整个代码的核心
3、文件操作:文本文件的格式化写入和读出操作
4、登陆模块:账户密码验证+随机验证码
5、功能子模块:

  • 增加节点
  • 删除节点
  • 修改节点
  • 查询节点
  • 初始化从磁盘中读取数据初始化链表
  • 向磁盘中保存整个链表(不追加,直接覆盖文件)
  • 打印整条链表

(项目目录下里面有两个txt格式的文件,data.txt 和 Landing.txt)
data.txt:保存链表数据
Landing.txt:保存登陆账号和密码数据
在项目目录下建立这两个txt文件,data.txt中可以不存数据,但要存的话一定是这种格式,Landing.txt一定要保存图片中的内容

在这里插入图片描述

建议:
1、登陆模块分用户账号和管理员账号,对子函数功能操作时进行权限设置,可以增强整个程序
2、子模块可以添加一些数据统计类的模块
3、main函数中的设计中,应该不断改进调用的顺序,使代码看起来紧凑条理清晰,这一块的调用控制,决定着最后的运行效果和使用体验

就说这些,如果要拿去使用,建议具体跑一跑,再配合(注释)自行添加修改
最后附上一句鸡汤:绝知此事必躬行

有什么问题,欢迎评论区里留言

猜你喜欢

转载自blog.csdn.net/qq_42856154/article/details/93376716