C语言无人超市管理系统进阶版本

题目如下:

设计一个无人超市管理系统,要求至少实现如下功能:

1.用户注册系统
     (1) 新用户注册
     (2) 用户登录
     (3) 退出系统
      新用户注册要求:
           (1) 用户名必须为英文字母或英文字母+数字,其他字符判断为非法用户名,总长度不超过20个字符。
           (2) 手机号码必须为11位数字,其他字符判断为非法。
           (3) 密码不低于6位,总长度不超过20个字符,低于6位或者超过20位判断为非法,注册要求输入2次密码,判断2次输入是否一致。
           (4)新用户注册赠送100元。
           (5) 新用户会员类型默认为普通会员,没有折扣。
           (6) 新用户会员类型默认为账号正常状态。
      用户登录要求:
           (1)输入用户名或者手机号码均可登录。
           (2)密码输入错误超过5次,将账号状态改为锁定。
           (3)登录后显示用户数据,包括用户名,手机号码,余额,会员类型,账号状态。
           (4)可以进入充值功能,充值10000元,自动升级为银卡会员;充值50000元自动升级为金卡会员。充值成功后提示当前的会员状态和享受的折扣。
           退出系统:提示欢迎下次光临等礼貌用语。
           交互界面:整体美观整洁,便于用户操作。

2.管理系统
     (1) 定义管理员结构体数组(支持多个管理员),可设置一个固定的账户与密码供管理员登录管理系统。
     (2) 定义商品信息结构体数组。商品信息包括但不限于:商品编号、商品名字、商品价格、商品库存、商品被购买的次数。
     (3) 管理系统应包括但不限于以下几个模块:商品库中商品信息的增加、删改、修改,商品受欢迎程度统计,营业状况的查看(总营业额、总购买次数等数据),用户的删除。

3.进一步设计用户系统
     (1) 用户系统包括购买模块和用户信息管理模块。
     (2) 购买的流程如下:显示商品列表 -> 输入商品编号 -> 输入购买数量 -> 重复上述操作直至选择完成 -> 显示清单 -> 确认支付 -> 记录数据。
     (3) 确认支付要选择是余额支付还是手机支付或放弃支付,不用编写支付的流程,只需在选择余额支付时判断余额是否足够,若不足时推荐其使用手机支付。
     (4) 支付需考虑用户会员类型。
     (5) 支付完成后进行记录数据,需要保存好本次订单的金额等便于总体数据统计,本次订单中各个商品的购买量,相应地也需要修改库存。
     (6) 用户信息管理模块包括查看余额与充值,修改密码,注销用户。
     (7) 所有数据可文件保存和读取。

思维导图:

在这里插入图片描述

一、所需要的头文件与宏定义


#include <stdio.h>
#include <stdlib.h> //与内存的分配等有关
#include <string.h> //包含大部分字符串处理函数
#include <ctype.h>  //包含字符属于哪一类(数字、字母...)
#include <windows.h> //封装了大部分的windows API函数,在该系统中用于获取系统当前的时间
#include <conio.h> //包含getch()函数,与隐藏密码部分有关

#define UPATH "user.txt" //宏定义文件存储的位置
#define APATH "admin.txt"
#define GPATH "goods.txt"

二、封装常用函数

知识补充

  • // COORD是 Windows API中定义的一种结构 本质是一种结构体
  • GetStdHandle(STD_OUTPUT_HANDLE)是获取当前窗口的句柄
  • SetConsoleCursorPosition(HANDLE,COORD)是将句柄(光标)设置到coord所在的坐标位置上

1. 隐藏光标

void HideCursor()
{
   
	CONSOLE_CURSOR_INFO cursor_info = {
   1, 0};
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}

2. 开启光标

void AppearCursor()
{
   
	CONSOLE_CURSOR_INFO cursor_info = {
   1, 1};
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}

3. 获取系统时间

void Windowstime()
{
   
	SYSTEMTIME sys; 
	printf("\t\t\t\t\t  当前时间为:");
	GetLocalTime( &sys ); //获取系统时间到程序的函数 
	printf( "%4d-%02d-%02d %02d:%02d \n\n",sys.wYear,sys.wMonth,sys.wDay,sys.wHour,sys.wMinute); //按照年/月/日 时/分 格式打印
	return;
}

4. 光标定位

void cursor(int x, int y) 
{
   
	COORD coord; 
	coord.X = x;                                                           
	coord.Y = y;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord); 
}

三、欢迎与退出界面

先看一下效果图:
在这里插入图片描述
在这里插入图片描述
接下来我们看看是怎么实现的

欢迎界面:

void welcome(){
   
	system("color F4");	//设置为红字白底
	HideCursor();		//为了美观 隐藏光标 
	cursor(0,21);		//将光标定位在(0,21)处
	Windowstime();		//显示系统时间 
	int i,j;
	char star = '*';
	for(i = 0; i <= 100; i++){
   		
		cursor(44,8);
		printf("欢迎使用无人超市管理系统");
		cursor(53,12);
		printf("启动中...");
		cursor(28,16);
		printf("<");
		for(j = 0; j < 50; j++){
   	//打印进度条 
			if(j < i/2)
			printf("*");
			else printf("o");
		}
		printf(">");
		printf("%d%%",i);
		Sleep(20);	//每 20ms 进一格 
	}
	return;
} 

退出界面:

void PrintExit(){
   		//同启动界面 
	system("cls"); 		
	system("color 8F");	
	HideCursor();
	cursor(0,21); 
	Windowstime();
	int i,j;
	for(i = 0; i <= 100; i++){
   
		cursor(44,8);
		printf("感谢使用无人超市管理系统"); 
		cursor(49,12);
		printf("数据保存中..."); 
		cursor(28,16);
		printf("<");
		for(j = 0; j < 50; j++){
   
			if(j < i/2)
			printf("*");
			else printf("o");
		}
		printf(">");
		printf("%d%%",i);
		Sleep(5);
	}
	cursor(0,26);
	return;
}

知识补充:

  • system(“cls”); “clear screem” 是清空屏幕的意思

  • system(“color XY”); 是设置页面的颜色

    X 是背景颜色 Y是前景颜色 颜色与数字的对应关系如下:

    0 = 黑色 8 = 灰色
    1 = 蓝色 9 = 淡蓝色
    2 = 绿色 A = 淡绿色
    3 = 湖蓝色 B = 淡浅绿色
    4 = 红色 C = 淡红色
    5 = 紫色 D = 淡紫色
    6 = 黄色 E = 淡黄色
    7 = 白色 F = 亮白色

  • Sleep() 执行挂起/“停止”一段时间 单位是 毫秒

  • sleep() 单位是秒

四、用户还是管理员

在启动系统之后,面前之人是用户?还是管理员?我们需要询问
在这里插入图片描述

代码实现如下:

int UserOrAdmin(){
   
	system("color 70");
	system("cls");
	cursor(20,9);
	printf("■■■■■■■■");
	cursor(20,10);
	printf("■用户请按:<1>■");
	cursor(20,11);
	printf("■■■■■■■■");
	cursor(80,9);
	printf("■■■■■■■■■");
	cursor(80,10);
	printf("■管理员请按:<2>■");
	cursor(80,11);
	printf("■■■■■■■■■");
	cursor(52,20);
	printf("请选择: ");
	int option;
	scanf("%d",&option);
	while(option != 1 && option != 2){
   
		cursor(44,20);
		printf("您的输入有误,请重新输入:  \b");
		scanf("%d",&option);
	} 
	return option; //在主函数中会有专门的变量来接受此数进而判断进入用户模块还是管理员模块
} 

五、定义所需的结构体

//记录商品购买记录 
typedef struct Record{
   
		char ID[20];			//商品名称 
		int number;				//购买数量 
		struct Record *next;	//指针域 
	} Record;

//用户信息 
typedef struct User{
   
	
	float balance;          //余额(保留两位小数) 
	int memberType;         //会员类型,0表示普通会员,1表示银卡会员,2表示金卡会员
	float discount[3];      //普通会员没折扣,银卡会员9折,金卡会员8折
	int userState;          //账号状态,0表示正常,1表示锁定
	int count_error;        //计数密码输错次数  满 5 自动锁定 
	char name[22];          //用户名
    char mobileNumber[12];  //手机号码
	char password[21];      //密码
	float recharge;         //总充值金额 
	int count_record;       //购买商品总数 
	struct User *next;		//指针域 
	Record *headp;			//商品记录头指针 
	Record *curp;			//商品记录当前所在位置指针 
	
	} User;

//商品信息 
typedef struct Goods
{
   
	
	char type[20];		//种类(水果、蔬菜、肉类、饮料等等)
	char name[20];		//商品名称 
	char  ID[20]; 	    //编号 (四位数)
	float price;		//价格 
	char locality[20];	//产地
	int salt;			//销量
	char day[20];		//保质期
	int amount;			// 库存数量 
	struct Goods *next; //指针域
	
}Goods;

//管理员信息 
typedef struct Admin
{
   
	
	char ID[22];		//账号
	char password[21];	//密码
	Admin *next;		//指针域 
	
}Admin;
 
//定义管理员、用户、商品链表头指针与现指针 
//此系统是用单链表来存取数据
Admin* Ahead = NULL; Admin* Ap = Ahead;  
User * Uhead = NULL; User * Up = Uhead;
Goods* Ghead = NULL; Goods* Gp = Ghead;

六、用户

先看看效果图吧

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1. 用户模块主函数

//用户界面 
void user(){
   
	int option = 0,i;
	while(option != 3){
   
		system("cls");
		system("color F0");
		HideCursor(); 
		cursor(26,6);
	    printf("______________________________________________________________");
	    cursor(46,9);
		printf("[请输入数字选择以下功能]");
		cursor(48,11);
		printf("(1) 用户注册");
		cursor(48,13);
		printf("(2) 用户登录");
		cursor(48,15);
		printf("(3) 退出系统");
		cursor(26,17);
	    printf("______________________________________________________________");
	    for(i = 7; i <= 17; i++){
   
	    	cursor(26,i); printf("|");
	    	cursor(88,i); printf("|");
		}
		cursor(50,20);
		printf("请选择: ");
		scanf("%d",&option);fflush(stdin);
		while(option != 1 && option != 2 && option != 3){
   
			cursor(44,20);
			printf("您的输入有误,请重新输入:  \b");
			scanf("%d",&option);fflush(stdin);
		}
		if(option == 1) userregist();
		else if(option == 2) userlogin();
		else PrintExit();
	}
}

2. 用户注册

//打印注册界面 
void PrintInterface(){
   
	
	int i; 
	system("cls");
	cursor(28,1);
	printf("____________________________________________________________________");
    cursor(54,3);
	printf("[注册要求]");
	printf("\n\n\t\t\t\t(1) 用户名必须为英文字母或英文字母+数字,总长度不超过20个字符\n\n");
	printf("\t\t\t\t(2) 手机号码必须为11位数字\n\n"); 
	printf("\t\t\t\t(3) 密码不低于6位,总长度不超过20个字符\n\n"); 
	cursor(28,10);
    printf("____________________________________________________________________");
    for(i = 2; i <= 10 ; i++){
   
    	cursor(28,i); printf("|");
    	cursor(95,i); printf("|");
	}
	cursor(0,13);
	printf("\t\t\t\t   │============================================│\n");
	printf("\t\t\t\t   │ 请输入用户名:            			│\n");
	printf("\t\t\t\t   │============================================│\n");
	printf("\t\t\t\t   │ 请输入手机号码:            		│\n");
	printf("\t\t\t\t   │============================================│\n");	
	printf("\t\t\t\t   │ 请输入密码:             			│\n");
	printf("\t\t\t\t   │============================================│\n");
	printf("\t\t\t\t   │ 请再次输入密码:  	           		│\n");
	printf("\t\t\t\t   │============================================│\n");
}

void userregist(){
   
	User *user = NULL;
	user = (User*)malloc(sizeof(User));
	int len_name,len_num,len_pswd,i,j;
	char flag_alnum = 0, flag_num = 0;
	char test[21];
	
	PrintInterface();	//打印注册页面
	cursor(51,14);		//将光标定位到用户名位置
	AppearCursor();
	
	fflush(stdin);gets(user->name);		//输入用户名 
	len_name = strlen(user->name);		//获取输入的用户名长度 
	for(i = 0;i < len_name;i++){
   
		if(!isalnum(user->name[i])){
   	//判断是否仅由字母与数字组成 
			flag_alnum = 1;
			break;
		}
	}
	while(len_name > 20 || flag_alnum){
   	//输入限制 
		PrintInterface(); 
		cursor(90,14); printf("用户名输入错误!请重新输入");
		cursor(51,14); fflush(stdin);gets(user->name);
		len_name = strlen(user->name);
		flag_alnum = 0;
		for(i = 0;i < len_name;i++){
   
			if(!isalnum(user->name[i])){
   
				flag_alnum = 1;
				break;
			}
		}
	}
	
	fflush(stdin);cursor(53,16);                    //输入手机号码
	gets(user->mobileNumber);      
	len_num = strlen(user->mobileNumber);
	for(i = 0;i < len_num;i++){
   						//判断是否仅由数字组成 
		if(!isdigit(user->mobileNumber[i])){
   
			flag_num = 1;
			break;
		}
	}
	while(len_num != 11 || flag_num){
   				//输入限制 
		PrintInterface();cursor(51,14);printf("%s",user->name);
		cursor(90,16); printf("手机号码输入错误!请重新输入");
		cursor(53,16); fflush(stdin);gets(user->mobileNumber);
		len_num = strlen(user->mobileNumber);
		flag_num = 0;
		for(i = 0;i < len_num;i++){
   
			if(!isdigit(user->mobileNumber[i])){
   
				flag_num = 1;
				break;
			}
		}
	}
	
re:	fflush(stdin);cursor(49,18);i = 0;		//初次输入密码
	
	while((user->password[i] = getch()) != 13){
   
		if(user->password[i] == 8){
   
			if(i > 0){
   
				printf("\b \b"); user->password[i] = '\0'; i--;
			}
		}else{
   
			printf("*"); i++;
		}
		if(i == 24){
   
			char temp;
			while((temp = getch()) != 13 && temp != 8);
			if(temp == 13) break;
			else{
   
				printf("\b \b"); user->password[i] = '\0'; i--;
			}
		}
	}
	user->password[i] = '\0'; fflush(stdin);
	len_pswd = strlen(user->password);
	if(len_pswd < 6 || len_pswd > 20){
   
		PrintInterface();
		cursor(51,14);printf("%s",user->name);
		cursor(53,16);printf("%s",user->mobileNumber);
		cursor(90,18); printf("密码长度错误!请重新输入");
		goto re;
	}
	
	fflush(stdin);cursor(53,20);i = 0;		//再次输入密码
	while((test[i] = getch()) != 13){
   
		if(test[i] == 8){
   
			if(i > 0){
   
				printf("\b \b"); test[i] = '\0'; i--;
			}
		}else{
   
			printf("*"); i++;
		}
		if(i == 24){
   
			char temp;
			while((temp = getch()) != 13 && temp != 8);
			if(temp == 13) break;
			else{
   
				printf("\b \b"); test[i] = '\0'; i--;
			}
		}
	}
	test[i] = '\0'; fflush(stdin);
	if(len_pswd != strlen(test)){
   
		PrintInterface();
		cursor(51,14);printf("%s",user->name);
		cursor(53,16);printf("%s",user->mobileNumber);
		cursor(90,20); printf("两次密码不匹配!请重新输入");
		goto re;
	}
	if(strcmp(test,user->password) == 0){
   	//两次密码匹配 注册成功 用户信息初始化 
		user->memberType = 0;
		user->balance = 100;
		user->userState = 0;
		user->recharge = 0;
		user->discount[0] = 1;
		user->discount[1] = 0.9;
		user->discount[2] = 0.8;
		user->count_error = 0;
		user->count_record = 0;
		user->next = NULL;
		user->headp = NULL;
		user->curp = NULL;
		count_user++;
		if(Uhead == NULL){
   		//尾插法插入用户链表 
			Up = user; Uhead = Up;
		}else{
   
			Up->next = user; Up = user;
		}
		cursor(40,23);printf("注册成功!正在返回用户界面...");
		HideCursor();
		for(i = 0; i <= 100; i++){
   		//打印进度条 
			cursor(28,25); printf("<");
			for(j = 0; j < 50; j++){
   
				if(j < i/2) printf("*");
				else printf("o");
			}
		printf(">");
		printf("%d%%",i);
		Sleep(5);
		}
	}else{
   
		PrintInterface();
		cursor(51,14); printf("%s",user->name);
		cursor(53,16); printf("%s",user->mobileNumber);
		cursor(90,20); printf("两次密码不匹配!请重新输入");
		goto re;
	}
}

3. 用户登录


//用户登录
void userlogin(){
   
	int i;
	User *p = NULL;
	char temp_n[25],temp_p[25];
re:	p = Uhead;
	system("cls"); cursor(57,11); AppearCursor(); 
	printf("[用户登录]"); cursor(0,13);
	printf("\t\t\t\t   │====================================================│\n");
	printf("\t\t\t\t   │ 请输入用户名/手机号码:            		│\n");
	printf("\t\t\t\t   │====================================================│\n");	
	printf("\t\t\t\t   │ 请输入密码:             				│\n");
	printf("\t\t\t\t   │====================================================│\n");
	
	//输入账号 
	cursor(60,14); gets(temp_n); fflush(stdin);
	
	//输入密码 
	cursor(49,16); fflush(stdin); i = 0;
	while((temp_p[i] = getch()) != 13){
   
		if(temp_p[i] == 8){
   
			if(i > 0){
   
				printf("\b \b"); temp_p[i] = '\0'; i--;
			
  • 27
    点赞
  • 87
    收藏
    觉得还不错? 一键收藏
  • 28
    评论
评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值