大佬们帮忙看看。

状态的状 2018-01-27 09:22:33
/* 登录系统; 可注册密码。可修改密码;*/

#include<stdio.h>
#include<string.h>
#include<windows.h>
#include<stdlib.h>
void dengluxitong();
int main()
{
dengluxitong(10);

return 0;
}


void dengluxitong(int n)
{

while(1)
{

char (*p)[10]=malloc(sizeof(char[10])*n);

FILE *fp=NULL;
int a=0,i=0;
do{
a=0,i=0;
printf("1.登录\n2.注册\n3.修改密码\n");
scanf("%d",&a);
fflush(stdin);

if(a<1||a>3)
{ printf("\n无效的序号!"); Sleep(1000); }

system("cls");

}while(a<1||a>3);


switch(a)
{
case 3: while(1)
{
printf("账号:");
scanf("%s",p[0]);
printf("原密码:");
scanf("%s",p[1]);
printf("新密码:");
scanf("%s",p[2]);

fp=NULL;
fp=fopen("Sl.txt","r+");

if(fp==NULL)
{printf("文件打开失败!"); return ;}

for(i=4;i<n;i++) //读出所有账号密码
fscanf(fp,"%s",p[i]);


for(i=4;i<n;i+=2)
if(strcmp(p[0],p[i])==0) //找出需要修改密码的账号
break;

if(i>=n)
{printf("此账号不存在!"); Sleep(1000); system("cls"); continue;} //因达到循环次数上限导致循环结束的 表明并没有此账号 (如果有此账号 将会break 直接结束循环 )



if(strcmp(p[1],p[i+1])==0) //账号后面就是该账号的密码 ;判断密码如果无误 就对密码进行更换
{strcpy(p[i+1],p[2]); system("cls"); break; } //用新密码将原密码替换掉
else
{printf("原密码错误!"); Sleep(1000); system("cls");}

}


for(i=4;i<n;i++)
fprintf(fp,"%s\n",p[i]); //将修改后的密码重新存入文件

fclose(fp);

break;









case 2: do
{
printf("注册账号:");
scanf("%s",p[0]);
printf("注册密码:");
scanf("%s",p[1]);

fp=NULL;
fp=fopen("Sl.txt","a+");

if(fp==NULL)
{printf("文件打开失败!"); return ;}

for(i=2;i<n;i++) //读出所有账号密码;
fscanf(fp,"%s",p[i]);

for(i=2;i<n;i+=2)
if(strcmp(p[0],p[i])==0)
{printf("账号重复!"); Sleep(1000); system("cls"); break;}


}while(strcmp(p[0],p[i])==0);


fprintf(fp,"%s\n",p[0]); //保存账号
fprintf(fp,"%s\n",p[1]); //保存密码

fclose(fp);
system("cls");

break;















case 1: printf("登录账号:");
scanf("%s",p[0]);
printf("登录密码:");
scanf("%s",p[1]);

fp=fopen("Sl.txt","r");

if(fp==NULL)
{printf("文件打开失败!"); return ;}


for(i=2;i<n;i++)
fscanf(fp,"%s",p[i]); //读取所有账号密码;

for(i=2;i<n;i+=2)
if(strcmp(p[0],p[i])==0) //对比账号是否存在;
break;

if(i>=n)
{printf("此账号不存在!"); Sleep(1000); system("cls"); free(p); continue;}



if(strcmp(p[1],p[i+1])==0 ) //核对输入密码是否与存入密码相符;
{printf("登录成功!"); Sleep(1000); system("cls"); free(p); return ;}
else
{printf("密码错误!"); Sleep(1000); system("cls");}

fclose(fp);






}


free(p);
}


}

注册账号发现文件写入那么多(如图) 就写不进去了。 再写入的时候没有提示,就是账号信息并没有在文件中。 能写入多少似乎和我的数组大小有关。


但是当我使用a 再次打开一次文件后再读写就没问题了

...全文
399 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
自信男孩 2018-01-27
  • 打赏
  • 举报
回复
#include<stdio.h>
#include<string.h>
//#include<windows.h>
#include<stdlib.h>

void  dengluxitong();

int main()
{
    dengluxitong(10);

    return 0;
}

void  dengluxitong(int n)
{

    while(1)
    {

        char (*p)[10] = malloc(sizeof(char[10]) * n);
        FILE *fp=NULL;
        int a = 0, i = 0;

        do {
            a=0,i=0;
            printf("1.登录\n2.注册\n3.修改密码\n");
            scanf("%d", &a);
            fflush(stdin);

            if(a < 1 || a > 3)
            {
                printf("\n无效的序号!");
                Sleep(1000);
            }

            system("cls");

        }while(a < 1 || a > 3);


        switch(a)
        {
            case 3:
                fp=fopen("Sl.txt","r+");
                if(!fp) {
                    printf("文件打开失败!");
                    return ;
                }

                for(i=4;i<n;i++)                 //读出所有账号密码
                    fscanf(fp,"%s",p[i]);
                while(1)
                {
                    printf("账号:");
                    scanf("%s",p[0]);
                    printf("原密码:");
                    scanf("%s", p[1]);
                    printf("新密码:");
                    scanf("%s",p[2]);

                    for(i=4;i<n;i+=2)
                        if(strcmp(p[0],p[i])==0)        //找出需要修改密码的账号
                            break;
                    if(i >= n) {
                        printf("此账号不存在!");
                        Sleep(1000);
                        system("cls");
                        continue;
                    }

                    if(strcmp(p[1],p[i+1])==0)             //账号后面就是该账号的密码 ;判断密码如果无误 就对密码进行更换
                    {
                        strcpy(p[i+1],p[2]);
                        system("cls");
                        break;
                    }
                    else
                    {
                        printf("原密码错误!");
                        Sleep(1000);
                        system("cls");}

                }

                rewind(fp);    /* 覆盖原有的账户和密码需要将文件指针重置到开始位置*/
                for(i=4;i<n;i++)
                    fprintf(fp,"%s\n",p[i]);   //将修改后的密码重新存入文件
                fclose(fp);
                break;

            case 2:
                fp = fopen("Sl.txt","a+");
                if(!fp)
                {
                    printf("文件打开失败!");
                    return ;
                }
                for(i=2;i<n;i++)                     //读出所有账号密码;
                    fscanf(fp,"%s",p[i]);
                do
                {
                    printf("注册账号:");
                    scanf("%s",p[0]);
                    printf("注册密码:");
                    scanf("%s",p[1]);
                    for(i=2;i<n;i+=2)
                        if(strcmp(p[0],p[i])==0)
                        {printf("账号重复!"); Sleep(1000); system("cls"); break;}


                }while(strcmp(p[0],p[i])==0);


                fprintf(fp,"%s\n",p[0]);  //保存账号
                fprintf(fp,"%s\n",p[1]); //保存密码

                fclose(fp);
                system("cls");

                break;

            case 1:
                printf("登录账号:");
                scanf("%s",p[0]);
                printf("登录密码:");
                scanf("%s",p[1]);

                fp=fopen("Sl.txt","r");

                if(fp==NULL)
                {printf("文件打开失败!");  return ;}


                for(i=2;i<n;i++)
                    fscanf(fp,"%s",p[i]);  //读取所有账号密码;

                for(i=2;i<n;i+=2)
                    if(strcmp(p[0],p[i])==0)       //对比账号是否存在;
                        break;

                if(i>=n)
                {printf("此账号不存在!");  Sleep(1000);  system("cls"); free(p); continue;}



                if(strcmp(p[1],p[i+1])==0 )     //核对输入密码是否与存入密码相符;
                {printf("登录成功!");  Sleep(1000);   system("cls");  free(p);   return ;}
                else
                {printf("密码错误!");  Sleep(1000);   system("cls");}

                fclose(fp);
        }


        free(p);
    }


}
问题有很多,最大的问题就是代码风格,太不注意代码的风格,如果代码很乱,对于读代码的人是一种煎熬。 出现的问题主要是因为将文件打开放在的while循环中,根据逻辑个人感觉没必要放在循环中。另外,在覆盖原有的账户信息时,没有将文件指针重新设定到文件开头; 文件指针的操作,建议拿出时间好好研究一下; 有问题可以继续提出来。 不过还是改了改你的代码,不过,其实还可以做的更好,那就是那switch case下的每个case都写成一个函数像这样:

switch (a) {
    case3: 
        modefy_account_info();
        break;
    case 2:
        register_account_info();
        break;
    case1:
        check_account_info();
        break;
}
这三个功能用三个函数实现,函数参数我没有写,建议楼主根据实际需要添加;
状态的状 2018-01-27
  • 打赏
  • 举报
回复

/* 登录系统;  可注册密码。可修改密码;*/

#include<stdio.h>
#include<string.h> 
#include<windows.h> 
#include<stdlib.h>
#define NNN 15

 void  dengluxitong(int n);   //登录选择 
 void  xiugai(char (*p)[10],int n); //修改密码 
 void  zhuche(char (*p)[10],int n); //注册账号 
 void  denglu(char (*p)[10],int n); //登录账号
  
int main()
{
    dengluxitong(NNN);
	
	
	return 0;
 } 
 
 
 
 
 //登录选择 
 void  dengluxitong(int n) 
 {
 	
   while(1)	
   {	
 	
 	 char (*p)[10]=malloc(sizeof(char[10])*n);

 	 int a=0,i=0;
   
     for(;i<n;i++)
     strcpy(p[i],"x0x");  //先给申请的内存空间指定一个值 ;
   
 
     do{	
 	   printf("1.登录\n2.注册\n3.修改密码\n");
	    scanf("%d",&a);
	    fflush(stdin);
	    
	    if(a<1||a>3)
	    { printf("\n无效的序号!");  Sleep(1000);  } 
	    
	    system("cls");
	 
	 
	 
       }while(a<1||a>3);
 	
 	
 	            switch(a)
 	            {
 	             case 3:     xiugai(p,n);     //修改密码 
 	            	          break;   

 	            	
	              case 2:     zhuche(p,n);    //注册账号  
							  break;
							    
 
				  case 1:     denglu(p,n);   //登录账号 
				              return;     	           	
			    }

	       free(p);
   }
 	
 	
 }
 
 
 
 
 //修改密码
 void xiugai(char (*p)[10],int n)
 { 
            	       	      
     char a[3][10];	 //用于临时存放输入的账号密码 
	 int i=0;
	 FILE *fp=NULL;     	      
            	      
            	        while(1)
                           {
						     printf("账号:");
 	                        scanf("%s",a[0]);  
 	                        printf("原密码:");
							 scanf("%s",a[1]);
							 printf("新密码:");
							 scanf("%s",a[2]);
 	            	        
							 fp=NULL;
							 fp=fopen("Sl.eep","rb+");
							 
							 if(fp==NULL)
							 {printf("文件打开失败!可能并无任何账号;"); return ;}
							 
							 for(i=0;i<n;i++)                 
							  fread(p[i],sizeof(p[i]),1,fp);   //读出所有账号密码

 	            	         for(i=0;i<n;i+=2)
 	            	          if(strcmp(a[0],p[i])==0)        //找出需要修改密码的账号 
 	            	               break;
 	            	          
 	            	          if(i>=n)                    
 	            	           {printf("此账号不存在!");  Sleep(1000);  system("cls"); continue;}  //因达到循环次数上限导致循环结束的 表明并没有此账号 (如果有此账号 将会break 直接结束循环  ) 

 	            	          
 	            	          
 	            	          if(strcmp(a[1],p[i+1])==0)             //账号后面就是该账号的密码 ;判断密码如果无误 就对密码进行更换 
							  	{strcpy(p[i+1],a[2]);  system("cls");   break;  }   //用新密码将原密码替换掉 
							  else
							  {printf("原密码错误!"); Sleep(1000); system("cls");}
		
		                   }
		                   
		                   
		                   
		                     rewind(fp);  //文件指针回到文件头
							 i=0;
							  
							 while(strcmp(p[i],"x0x")!=0)
							 {					           
							   fwrite(p[i],sizeof(p[i]),1,fp);   //将修改后的密码重新存入文件							   
							   i++;
							   
							   if(i>=n)
							    break;
 	            	         }
 	            	        
 	            	    		fclose(fp);  
 	
 	
 	
 	
 	return ; 	
 }
 
 
 
 
 
 //注册账号 
 void  zhuche(char (*p)[10],int n) 
 {
 	 char a[2][10]; //用于临时存放输入的账号密码 
 	 int i=0;
 	 FILE *fp=NULL;

				        do{
							    printf("注册账号:");
				                scanf("%s",a[0]);
								printf("注册密码:");
								scanf("%s",a[1]);
								
							    fp=NULL;
							    fp=fopen("Sl.eep","ab+");
							    
							    if(fp==NULL)
							     {printf("文件打开失败!"); return ;} 
							    
							    for(i=0;i<n;i++)                     
							      fread(p[i],sizeof(p[i]),1,fp);    //读出所有账号密码;    
							     
								for(i=0;i<n;i+=2)
								  if(strcmp(a[0],p[i])==0)
								   {printf("账号重复!"); Sleep(1000); system("cls"); break;} 

							
						   }while(strcmp(a[0],p[i])==0);
						   
	
							    fwrite(a[0],sizeof(a[0]),1,fp);  //保存账号 
							    fwrite(a[1],sizeof(a[1]),1,fp);  //保存密码
								 
							    fclose(fp); 
							    system("cls");
 	
 	
 	return;
 	
 	
 }

 
 
 
//登录账号 
 void denglu(char (*p)[10],int n)
 {
 	 char a[2][10]; //用于临时存放输入的账号密码 
 	 int i=0;
 	 FILE *fp=NULL;
 	                       
 	                        while(1)
 	                        {
						
 		                       printf("登录账号:");
				                scanf("%s",a[0]);
								printf("登录密码:");
								scanf("%s",a[1]);    		 
								
								fp=NULL; 
								fp=fopen("Sl.eep","rb");
								
								if(fp==NULL)
								  {printf("文件打开失败!您可能还未注册账号!");  return ;} 
								
								
								for(i=0;i<n;i++)
								fread(p[i],sizeof(p[i]),1,fp);  //读取所有账号密码; 
								
								for(i=0;i<n;i+=2)
                                 if(strcmp(a[0],p[i])==0)       //对比账号是否存在; 
				                   break;
				                   
				                if(i>=n)
								  {printf("此账号不存在!");  Sleep(1000);  system("cls"); free(p); continue;}


								if(strcmp(a[1],p[i+1])==0 )     //核对输入密码是否与存入密码相符;  
								  {printf("登录成功!");  Sleep(1000);   system("cls");  free(p);   return ;}
								else
								  {printf("密码错误!");  Sleep(1000);   system("cls");}  
								
								fclose(fp); 
 	
 	                        }
 	
 	
 }
 
不过由于新人对发帖也不是特别了解。之前的代码都是直接复制黏贴的,所以格式都是乱的,这次进行了格式转换。我回去看了一下 之前确实乱七八糟的 ;特别感谢之前大佬能帮忙看那么乱的代码; 谢谢
状态的状 2018-01-27
  • 打赏
  • 举报
回复
[code=c]经过多次测试; 我发现 由于“+” 兼顾了读和写, 编译器或者C标准可能考虑到这方面的问题。如果使用 r+ 或a+ 打开文件,首先进行了“读”, 那可读范围就限制了可写范围; 我认为这样很好,如果无法读取那么多,那写入也毫无意义;



我经过了以下测试 ;图中读取了 10次 a[i] 进行储存 表明可读取范围为10个字符串(字符串不超过10个字节)
程序运行后 可以看到确实只写入了10次"aaa" 可读范围限制了可写范围;


同理; 图中读取了1次a[0] ; 程序运行后可以看到 确实只写入了1次"aaa"


楼上的大佬建议我不要将文件打开放入循环,经过测试;
由于文件打开在循环中 每次循环进行了重置打开(重置打开 操作系统或者编译器可能会将上次打开的文件先关闭,再进行打开)
如果文件打开不在循环内 文件将一直保持最初的打开状态 直到循环结束;

图中可以看到 如果文件打开状态 确实可以写入很多数据;但是也只是一次性写入大量数据;文件总要关闭 重新打开的;


如果写入的文件内 原先的内容已经超出了可读范围,依旧无法写入;附图:
再次运行 文件大小并未变化; 写入限制依旧存在 ;


当然如果使用“+” 形式打开 并未读写的情况下 不存在可读范围 当然也不会存在写入限制
附图: 不读取,写入无限制;


当然 我也发现了解决办法; 写入时重新以新的方式重置打开;写入将不会受限制; 附图
再次运行 文件字节数变大。 当然我不太确定这种做法是否规范。 (这种解决办法 目前来说并不需要,还是我开头说的 我认为可读范围限制可写 这样很好,如果无法读取那么多,那写入再多也毫无意义;)




以上都是自己经过测试的片面理解。 如果有不对的地方,还是希望大佬们帮忙指出。




paschen 2018-01-27
  • 打赏
  • 举报
回复
单步跟踪程序运行,观察变量变化情况,分析原因,必要时检查函数返回值看是否执行成员,如果失败了检查失败原因。此外一个小问题是dengluxitong函数的声明和定义的不一致

33,311

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧