【C语言】简易登录注册系统(登录、注册、改密、文件操作)

概述:

        本登录注册系统通过使用C语言中的结构体、函数、文件操作以及指针等,设计与实现了一个小型用户登录注册系统的登录、注册、修改密码等基本功能。

        本系统全部功能基本运行良好、用户界面友好、操作简单、使用方便。但系统仍然有不完善之处。例如在隐藏用户输入密码时,如果用户要删除刚输入的密码,则不能将输入‘*’一并删除;修改密码时生成的验证码不应该直接显示,而是通用户留存的手机号将验证码发送至用户绑定的手机上;其实改密部分还可以再添加一个二次输入验证的功能。除此之外,还可以将程序中一些重复使用的代码段再行封装成函数,但考虑接口会变得更复杂,故并未操作。

用户信息采用结构体:

typedef struct The_users {
    char name[11];        
    char pwd[20];       
    char phone[11]; 
} Users;  

程序源码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#include <time.h>

typedef struct The_users { //typedef 可以定义结构体别名
	char name[11]; 		//账号
	char pwd[20]; 		//密码
	char phone[11];		//手机号
} Users;	//该结构体别名

void Options(int);	//菜单导航
void Registers();	//注册模块
void Login();		//登录模块
void Reback();		//密码找回模

int i = 0,flag = 1,menu = 0;
int main() {
	printf("\n\t\t\t++++++++++++++++++++++++\n\t\t\t+  欢迎使用XX登录系统  +\n\t\t\t++++++++++++++++++++++++\n");
//    system ("color 1F");			//程序面板颜色
	while (flag) {
		do {
			printf("\n		******************菜单栏*****************\n");
			printf("\t\t*\t      ①登录                    *\n");
			printf("\t\t*\t      ②没有账号?去注册        *\n");
			printf("\t\t*\t      ③忘记密码?去找回        *\n");
			printf("\t\t*\t      ④退出系统\t\t*\n");
			printf("		*****************************************\n");
			printf("\n");
			printf("\t\t请输入选项:[\t]\b\b\b");
			scanf("%d", &menu);
		} while (menu>5 || menu<1);
		Options(menu);
	}
}

/*
	通过Option函数
	接收代表功能对应的数字
	来调用其他功能函数
*/
void Options(int option) {
	switch (option) {
		case 1:
			Login();
			break;
		case 2:
			Registers();
			break;
		case 3:
			Reback();
			break;
		case 4:
			printf("\n\t\t谢谢使用(^V^)!\n");
			flag=0;		//flag置0,结束主函数循环(也可以不要此句)
			exit(0);
	}
}

/*
	注册账号模块
*/
void Registers() {
	system("cls");
	Users a,b;		//定义两个临时用结构体变量
	FILE *fp;
	char temp_pwd[20];
	int count = 0;
	printf("\n\t\t欢迎来到注册界面!\n");
	Sleep(500);
	fp = fopen("Users.txt","r");
	fread(&b, sizeof(Users), 1, fp); 	//读入一个用户信息,用于在下面查找注册的账号名是否存在
	printf("\n\t\t请设置账号:[ \t\t ]\b\b\b\b\b\b\b\b\b\b\b\b\b");
	scanf("%s",&a.name);
	while (1) {
		if (strcmp(a.name, b.name)) { 	//如果注册账号不存在
			if (!feof(fp)) {  						//如果未到文件尾
				fread(&b, sizeof(Users), 1, fp);	//继续读入下一个用户信息
			} 
			else {
				break;		//检查完毕,跳出
			}
		} 
		else {	//如果此账号已存在,退出
			printf("\t\t此用户名已存在!请重新注册!\n");
			Sleep(1000);
			fclose(fp);
			return;
		}
	}
	printf("\t\t请输入您的手机号:[ \t\t ]\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
	scanf("%s",&a.phone);
	int time = 2;
	do {
		printf("\t\t请设置密码:[ \t\t ]\b\b\b\b\b\b\b\b\b\b\b\b\b");
		i = 0;
		/*
		以下代码段用于将输入的明文替换为'*'
		起到保护作用,但仍存一点bug
		*/
		do {
			a.pwd[i]=getch();
			if(a.pwd[i]=='\r')
				break;
			if(a.pwd[i]=='\b') {	//如果退格(删除键)
				if(i==0) {			//依旧可以让输入的内容
					printf("\a");	//正确保存到密码中
					continue;
				}
				i=i-1;
				printf("\b");
			} 
			else {
				i=i+1;
				printf("*");		//但已经打印出的'*'是不能消除的,此程序bug
			}
		} while(a.pwd[i]!='\n' && i<20);	//当接收到回车符或者密码长度已够时完成密码接收
		a.pwd[i]='\0';
		printf("\n");
		printf("\t\t请确认密码:[ \t\t ]\b\b\b\b\b\b\b\b\b\b\b\b\b");
		/*
			再接收一次密码
			用于验证,防止用户设置密码出错
		*/
		i= 0;
		do {
			temp_pwd[i]=getch();
			if(temp_pwd[i]=='\r')
				break;
			if(temp_pwd[i]=='\b') {
				if(i==0) {
					printf("\a");
					continue;
				}
				i=i-1;
				printf("\b");
			} 
			else {
				i=i+1;
				printf("*");
			}
		} while(temp_pwd[i]!='\n' && i<20);
		temp_pwd[i]='\0';
		printf("\n");
		if(!strcmp(a.pwd,temp_pwd)) {	//如果两次输入的密码相同就可以注册了
			fp = fopen("Users.txt","a");	// a-向文件尾部追加写入
			fwrite(&a, sizeof(Users), 1, fp);
			printf("\t\t账号注册成功!\n");
			fclose(fp);
			return;
		} 
		else {
			if (time!=0) {
				printf("\n\t\t两次输入的密码不相同!\t请重新输入(剩余%d次机会)\n",time);
				time--;
				continue;	//如果本次密码匹配不相同跳出,进入下一次输入
			} 
			else {
				printf("\n\t\t多次输入错误,即将退出!");
				Sleep(1500);
				return ;
			}
		}
	} while(time >= 0);
}

/*
	登录模块
*/
void Login() {
	system("cls");
	Users a,b;	//定义结构体The_users别名
	FILE *fp;
	printf("\t\t\n欢迎来到登录界面!\n\n");
	printf("\t\t请输入账号:[ \t\t ]\b\b\b\b\b\b\b\b\b\b\b\b\b");
	scanf("%s",&a.name);
	printf("\t\t请输入密码:[ \t\t ]\b\b\b\b\b\b\b\b\b\b\b\b\b");
	i= 0;
	/*
		采用相同的方法掩盖明文密码
	*/
	do {
		a.pwd[i]=getch();
		if(a.pwd[i]=='\r')
			break;
		if(a.pwd[i]=='\b') {
			if(i==0) {
				printf("\a");
				continue;
			}
			i=i-1;
			printf("\b");
		} 
		else {
			i=i+1;
			printf("*");
		}
	} while(a.pwd[i]!='\n' && i<20);
	a.pwd[i]='\0';
	printf("\n");
	fp = fopen("Users.txt","r");
	while (1) {
		fread(&b, sizeof(Users), 1, fp); //读入一个结构体字符块 写入b
		if ((strcmp(a.name, b.name)==0)||(!feof(fp))) {      	//如果有此账号
			break;								//此账号已经注册 可以登录
		} 
		else {
			if (!feof(fp)) { //如果文件没有读完
				fread(&b, sizeof(Users), 1, fp);
			} 
			else {	//如果在变量用户表之后没有找到该账号,提示错误信息
				printf("\t\t账号或密码错误!\n");
				fclose(fp);
				Sleep(1000);
				system("cls");
				return ;
			}
		}
	}
	fclose(fp);
	if (strcmp(a.pwd, b.pwd)==0) {          /*如果密码匹配*/
		printf("\t\t登录成功!欢迎使用!\n");
		return;
	} 
	else {
		printf("\t\t账号或密码错误!……");
		Sleep(1000);
		system("cls");
		return;
	}
}

/*
	找回密码模块
*/
void Reback() {
	system("cls");
	Users a,b;	//两个用于零时写入的结构体变量
	FILE *fp;
	printf("\t\t欢迎来到找回密码界面!\n\n");
	int num = 0;	//用于记录改密用户在文件中的位置
	fp = fopen("Users.txt","r");
	fread(&b, sizeof(Users), 1, fp); //读入一个用户信息并写入b
	printf("\t\t请输入账号:[ \t\t ]\b\b\b\b\b\b\b\b\b\b\b\b\b");
	scanf("%s",&a.name);
	while (1) {
		if (strcmp(a.name, b.name)==0) {    //如果有此用户名
			break;						//就跳出完成查找
		} 
		else {
			if (!feof(fp)) { 			//如果文件没有读完切没有找到该用户
				fread(&b, sizeof(Users), 1, fp);	//继续查找用户
				num++;
			} 
			else {		//如果没有找到
				printf("\t\t此用户不存在!!!\n");
				fclose(fp);
				for(i=0; i<2; i++) {
					printf("\t\t%d秒后退出 ……",2-i);
					printf("\r");
					Sleep(1000);
				}
				system("cls");
				return;
			}
		}
	}
	//如果程序走到这 就可以开始修改密码了
	int ver_code = 0,user_ver_code = 0;
	//生成随机的验证码
	srand((unsigned)time(NULL));
	for (i = 0; i < 7; i++){
		ver_code += rand() % 1000;	
	}
	char phone_tail[5] ;	// 获取该用户的手机尾号
	strncpy(phone_tail,a.phone+7,4) ;
	printf("\t\t已向尾号为%s的手机号码发送验证码 %d ,请注意查收!\n\t\t请输入验证码:[\t\t]\b\b\b\b\b\b\b\b\b\b", phone_tail,ver_code);
	scanf("%d", &user_ver_code);
	int sign = 0;
	//给用户提供三次验证输入的机会
	for(i=0; i<3; i++) {
		if (ver_code != user_ver_code) {
			printf("\t\t验证码错误!请重新输入:[\t](剩%d次机会)\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b",2-i);
			scanf("%d", &user_ver_code);
			continue;
		} 
		else if (i<=3) {	//如果验证次数内正确输入验证码
			sign =1;		//就可以退出循环
			break;			//向下一步改密
		} 
		else {
			for(i=0; i<2; i++) {
				printf("\t\t多次输入错误!!%d秒后退出 ……",2-i);
				printf("\r");
				Sleep(1000);
			}
		}
	}
	if(sign == 1) {		//如果验证手机正确开始改密
		FILE*fp;
		int N = 0;	//用于记录当前用户总数
		if((fp=fopen("Users.txt","r"))==NULL) {		// 判断文件是否能打开
			printf ("\t\tCannot open file\n");
			exit(0);
		} 
		else {
			while (feof(fp)==0) {
				fread(&b, sizeof(Users), 1, fp);	//依次读取用户并记录用户总数
				N++;
			}
		}
		N = N-1;	//实际用是完成上面循环的 N-1
		fclose(fp);
		Users user[N];		//定义结构体数组
		if((fp=fopen("Users.txt","r"))==NULL) {		// 判断文件是否能打开
			printf ("\t\tCannot open file\n");
			exit(-1);
		} 
		else {
			i=0;
			do {
				fread(&user[i],sizeof(Users),1,fp);	//将用户表中的数据都读入以便修改指定用户的密码
			} while(feof(fp)==0);		//直到读到文件尾结束
		}
		printf("\t\t设置您的新密码:[   \t\t]\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
		i= 0;
		/*
			让输入的密码不可见
		*/
		do {
			user[num].pwd[i]=getch();
			if(user[num].pwd[i]=='\r')
				break;
			if(user[num].pwd[i]=='\b') {
				if(i==0) {
					printf("\a");
					continue;
				}
				i=i-1;
				printf("\b");
			} 
			else {
				i=i+1;
				printf("*");
			}
		} while(user[num].pwd[i]!='\n' && i<20);
		user[num].pwd[i]= '\0';
		printf("\n");
		if ((fp=fopen("Users.txt","w"))==NULL) { 	 /*判断文件是否能打开*/
			printf ("\t\tCannot open file\n");
			exit(0);
		}
		for (i=0; i<N; i++) 	/*将内存中的用户信息输出到磁盘文件中去*/
			if (fwrite(&user[i],sizeof(Users),1,fp)!=1)
				printf("File write error\n");
		fclose(fp);
		printf("\t\t密码修改成功!\n");
		return ;
	} 
	else {
		for(i=0; i<3; i++) {
			printf("\t\t多次输入错误!!%d秒后退出 ……",3-i);
			printf("\r");
			Sleep(1000);
		}
	}
}

运行测试:

注意:运行前需要在程序目录新建一个.txt的用户信息表

  1.注册用户:

(1)正常注册(账号未被注册)

(2)异常注册(账号已被注册)

 2.用户登录:

(1)用户未注册

 (2)用户已注册

        ①密码正确

         ②密码错误

 3.用户修改密码:

(1)无当前用户:

 (2)用户存在

        ①正确输入验证码:

         ③错误输入验证码        

  (3) 修改后登录 

  • 54
    点赞
  • 489
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 15
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.魚肉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值