改完有新问题了,输入错误密码也会显示欢迎登陆,而且文件里还是很多“烫”
#include
#include
#include
void login();
void register_();
typedef struct
{
char username[30];
char password[10];
int score;
int days;
}Users;
typedef struct
{
char English[20];
char property[10];
char Chinese[50];
}Word;
int main()
{
int n;
while(1)
{
printf("欢迎使用背单词系统\n\n"); //首页界面
printf("1:登录\n");
printf("2:注册\n");
printf("0:退出\n");
printf("请选择您想进行的操作并输入编号:"); //功能选择
scanf("%d",&n);
switch(n) //判断
{
case 1:
login(); break;
case 2:
register_();break;
case 0:exit(1);break;
default:
printf("您输入的操作编号有误,请重新输入!\n");
}
}
}
void login() //登录
{
Users a,b; //定义结构体The_users别名
FILE *fp;
printf("欢迎使用背单词系统\n");
printf("请输入用户名:");
scanf("%s",a.username);
printf("请输入密码:");
scanf("%s",a.password);
fp = fopen("Users.txt","r");
while(1)
{
while(fread(&b,sizeof(Users),1,fp)==1); //读取一个用户
{
if(strcmp(a.username,b.username)==0)//||(!feof(fp))
break;
else
{
if(!feof(fp))
{
fread(&b,sizeof(Users),1,fp);
}
else
{
fclose(fp);
printf("您尚未注册,请注册后登陆!\n");
}
}
}
fclose(fp);
if(strcmp(a.password,b.password)==0)
{
printf("欢迎登录!\n");
}
else
{
printf("用户名或密码错误\n");
}
}
}
void register_()
{
Users a,b;
FILE *fp;
printf("欢迎注册!\n");
printf("请设置用户名(小于30字符):\n");
scanf("%s",a.username);
a.username[strlen(a.username)]='\0';
fp=fopen("Users.txt","r");
while (fread(&b, sizeof(Users), 1, fp) == 1)
{
if (strcmp(a.username, b.username) == 0) //如果此账号已存在,退出注册界面
{
printf("此用户名已存在!\n");
fclose(fp);
return;
}
}
fclose(fp);
fp=fopen("Users.txt","a"); // 以追加方式打开文件
fwrite(&a,sizeof(Users),1,fp);
printf("请设置密码(小于10字符):");
scanf("%s",a.password);
a.password[strlen(a.password)]='\0';
printf("账号注册成功!\n");
fclose(fp);
return;
}
烫说明字符串没有截断,我想每一个程序员都应该知道“烫烫烫”是什么梗吧
这里的排序本质上是结构体排序,通过结构体(联系人信息)的一个成员(姓名)的大小关系来进行排序。
这里用选择排序完成,其中姓名大小要用 strcmp 函数判断:
//函数声明 - 给通讯录排序
void Sort(Contact* pc);
void Sort(Contact* pc)
{
for(int i=0; i<pc->sz-1; i++)
for (int j = i + 1; j < pc->sz; j++)
{
PeoInfo tmp = { 0 };
if (strcmp(pc->PeoInfo[i].name, pc->PeoInfo[j].name) > 0)
{
tmp = pc->PeoInfo[i];
pc->PeoInfo[i] = pc->PeoInfo[j];
pc->PeoInfo[j] = tmp;
}
}
printf("排序成功\n");
}
整体修改如下,供参考:
#include<stdio.h>
#include<string.h>
#include<windows.h>
void login();
void register_();
typedef struct
{
char username[30];
char password[10];
int score;
int days;
}Users;
typedef struct
{
char English[20];
char property[10];
char Chinese[50];
}Word;
int main()
{
int n;
while(1)
{
printf("\n欢迎使用背单词系统\n"); //首页界面
printf("1:登录\n");
printf("2:注册\n");
printf("0:退出\n");
printf("请选择您想进行的操作并输入编号:"); //功能选择
scanf("%d",&n);
switch(n) //判断
{
case 1:
login(); break;
case 2:
register_();break;
case 0:exit(1);break;
default:
printf("您输入的操作编号有误,请重新输入!\n");
}
}
}
void login() //登录
{
Users a,b; //定义结构体The_users别名
FILE *fp;
int i = 0;
fp = fopen("Users.txt","r");
if (fp == NULL) //修改
printf("尚未注册用户,请注册后登陆!\n");
else{
printf("\n欢迎登录背单词系统\n"); //修改
printf("请输入用户名:");
scanf("%s",a.username);
do { //修改
fread(&b,sizeof(Users),1,fp);
if (strcmp(a.username,b.username) == 0) break;
} while (!feof(fp)); //修改
if (feof(fp))
printf("该用户名不存在!\n"); //修改
else{
do { //修改
printf("输入密码:");
scanf("%s",a.password);
if(strcmp(a.password,b.password)==0){
printf("\n登录背单词系统成功!\n");
break;
}
else{
i++;
if (i != 3)
printf("密码错误,还有%d次机会,请重新", 3 - i);
else {
printf("输入密码错误,3次机会已用完,退出登录!\n");
break;
}
}
} while (strcmp(a.password,b.password)!=0);//修改
}
fclose(fp);
}
}
void register_()
{
Users a,b;
FILE *fp;
printf("欢迎注册用户!\n");
fp = fopen("Users.txt","r");
if (fp == NULL){ //修改
printf("请设置用户名(小于30字符):\n");
scanf("%s",a.username);
printf("请设置密码(小于10字符):");
scanf("%s",a.password);
}
else{ //修改
while (1){
printf("请设置用户名(小于30字符):\n");
scanf("%s",a.username);
do {
fread(&b, sizeof(Users), 1, fp);
if (strcmp(a.username, b.username) == 0)//如果此账号已存在
{ printf("此用户名已存在,"); break;}
}while (!feof(fp));
if (feof(fp))
break;
else
rewind(fp);
}
printf("请设置密码(小于10字符):");
scanf("%s",a.password);
fclose(fp);
}
fp = fopen("Users.txt","a+"); //修改
fwrite(&a,sizeof(Users),1,fp);
fclose(fp);
printf("账号注册成功!\n");
return;
}
在login()函数中,需要加入一个判断语句,判断用户名是否存在于文件中,如果不存在就提示用户尚未注册,并返回上一级菜单。此外,还需要修改读取一个用户信息的方式,不再使用while循环读取,而是用if语句判断是否成功读取到一个用户。修改后的代码如下:
void login()
{
Users a,b; //定义结构体The_users别名
FILE *fp;
printf("欢迎使用背单词系统\n");
printf("请输入用户名:");
scanf("%s",a.username);
printf("请输入密码:");
scanf("%s",a.password);
fp = fopen("Users.txt","r");
int user_exist = 0; //标记用户是否存在
while(fread(&b,sizeof(Users),1,fp)==1) //读取一个用户
{
if(strcmp(a.username,b.username)==0) //找到了对应的用户名
{
user_exist = 1; //将标记设为1
if(strcmp(a.password,b.password)==0) //密码正确
{
printf("欢迎登录!\n");
fclose(fp);
return;
}
else //密码错误
{
printf("用户名或密码错误\n");
fclose(fp);
return;
}
}
}
//文件结束,但用户不存在
if(!user_exist)
{
fclose(fp);
printf("您尚未注册,请注册后登陆!\n");
}
}
在register_()函数中,为了防止字符串越界,需要在读取用户名和密码后立即将末尾加上'\0',并且要在每次写入文件前先关闭文件。另外,为了防止以追加方式打开文件时写入错误的数据,应当先读取文件判断是否存在重名用户,只有不存在重名用户时才进行写入操作。修改后的代码如下:
void register_()
{
Users a,b;
FILE *fp;
printf("欢迎注册!\n");
printf("请设置用户名(小于30字符):\n");
scanf("%s",a.username);
a.username[strlen(a.username)]='\0';
fp=fopen("Users.txt","r");
while (fread(&b, sizeof(Users), 1, fp) == 1)
{
if (strcmp(a.username, b.username) == 0) //如果此账号已存在,退出注册界面
{
printf("此用户名已存在!\n");
fclose(fp);
return;
}
}
fclose(fp);
fp=fopen("Users.txt","a"); // 以追加方式打开文件
printf("请设置密码(小于10字符):");
scanf("%s",a.password);
a.password[strlen(a.password)]='\0';
fwrite(&a,sizeof(Users),1,fp);
printf("账号注册成功!\n");
fclose(fp);
return;
}