目录
一、思维导图
二、作业
2.1 实现登录功能
2.2 实现注册功能
三、练习
3.1 用fprintf与fscanf函数实现文件拷贝
3.2 用fgetc与fputc函数实现文件拷贝
四、课堂知识回顾
4.1 使用fopen函数打开文件,使用fclose函数关闭文件
4.2 使用fprintf函数将"hello world 12"和一个整型数组输入到fprintf.txt中
4.3 使用fprintf函数将fprintf.txt文件中的数据读取并打印到到终端中
4.4 使用fputc、fgetc函数将数据赋值到fputc.txt文件,并从中读取并输出到终端中
自定义一个usr.txt,先手动输入其账户密码。
格式:账户 密码
例:
zhangsan 12345
lisi abcde
wangwu abc123
需求如下:
1. 从终端获取账户密码,与文件中的账户密码比较;
2. 若终端输入的账户不存在,则输出账户不存在;
3. 若终端输入的账户存在,但是密码不正确,则输出密码错误;
4. 若账户密码均正确,则输出登录成功。
方法一:
#include
#include
#include
#include
int main(int argc, const char *argv[])
{
char get_usrname[20]="";
char get_usrpass[20]="";
printf("请输入账号:");
scanf("%s",get_usrname);
printf("请输入密码:");
scanf("%s",get_usrpass);
FILE* fp=fopen("./usr.txt","r");
if(NULL == fopen)
{
perror("fopen");
return -1;
}
char file_name[20];
char file_pass[20];
int flag=0;
while(1)
{
if(fscanf(fp,"%s %s",file_name,file_pass)==EOF)//从终端读取账号密码
{
flag=1;
break;
}
if(strcmp(file_name,get_usrname)==0 && strcmp(file_pass,get_usrpass)!=0)
{
printf("密码错误!\n");
break;
}
if(strcmp(file_name,get_usrname)==0 && strcmp(file_pass,get_usrpass)==0)
{
printf("登录成功!\n");
break;
}
}
if(flag==1)
{
printf("该用户不存在!\n");
}
fclose(fp);
return 0;
}
方法二:
#include
#include
#include
int main(int argc, const char *argv[])
{
char get_name[20] = "", get_passwd[20] = "";
char file_name[20] = "", file_passwd[20] = "";
//从终端获取账户密码
printf("请输入账户和密码>>> ");
scanf("%s %s", get_name, get_passwd);
//以读的方式打开文件
FILE* fp = fopen("./usr.txt", "r");
if(NULL == fp)
{
perror("fopen");
return -1;
}
//循环读取文件的一行:账户 密码
while(1)
{
//将字符串清空
bzero(file_name, sizeof(file_name));
bzero(file_passwd, sizeof(file_passwd));
if(fscanf(fp, "%s %s", file_name, file_passwd) == EOF)
{
printf("%s 用户不存在\n", get_name);
break;
}
// printf("%s %s\n", file_name, file_passwd);
//与终端获取到的账户密码比较
if(strcmp(file_name, get_name) != 0) //若账户名不相同,则去获取下一个账户密码
continue;
if(strcmp(file_passwd, get_passwd) != 0)
{
printf("%s 密码错误\n", get_name);
}
else
{
printf("%s 用户登录成功\n", get_name);
}
break; //若账户相同,则不需要继续往后比较其他用户了
}
//关闭文件
fclose(fp);
return 0;
}
注册的账户密码存储在上一题的文件中。
需求:不能重复注册。
#include
#include
#include
#include
int log_on();
int regist();
int main(int argc, const char *argv[])
{
/*
一、实现登录功能。自定义一个usr.txt,手动输入账户密码,格式如下:账户 密码
例如: zhangsan 12345
lisi abcde
wangwu abc123
需求如下:
1.从终端获取账户密码,与文件中的账户密码比较
2.若终端输入的账户不存在,则输出账户不存在
3.若终端输入的账户存在,但是密码不正确,则输出密码错误
4.若账户密码均正确,则输出登录成功
二、附加题
实现注册功能,注册的账户密码存储在上一题的文件中。需求:不能重复注册。
*/
int choose;
printf("请选择是注册用户(1)还是登录用户(2):");
scanf("%d",&choose);
if(choose!=1&&choose!=2)
{
printf("选择失败!\n");
return 0;
}
//注册
else if(choose==1)
{
regist();
}
//登录
else
{
log_on();
}
return 0;
}
int log_on()
{
char get_usrname[20]="";
char get_usrpass[20]="";
printf("请输入账号:");
scanf("%s",get_usrname);
printf("请输入密码:");
scanf("%s",get_usrpass);
FILE* fp=fopen("./usr.txt","r");
if(NULL == fopen)
{
perror("fopen");
return -1;
}
char file_name[20];
char file_pass[20];
int flag=0;
while(1)
{
if(fscanf(fp,"%s %s",file_name,file_pass)==EOF)//从终端读取账号密码
{
flag=1;
break;
}
if(strcmp(file_name,get_usrname)==0 && strcmp(file_pass,get_usrpass)!=0)
{
printf("密码错误!\n");
int b=0;
printf("请问是否要再次登录(0/1):");
scanf("%d",&b);
if(b==1)
{
log_on();
}
break;
}
if(strcmp(file_name,get_usrname)==0 && strcmp(file_pass,get_usrpass)==0)
{
printf("登录成功!\n");
break;
}
}
if(flag==1)
{
printf("该用户不存在!\n");
int b=0;
printf("请选择是否要注册(0/1):");
scanf("%d",&b);
if(b==1)
{
regist();
}
}
fclose(fp);
return 0;
}
int regist()
{
char get_usrname[20];
char get_usrpass[20];
printf("请输入注册账户:");
scanf("%s",get_usrname);
printf("请输入注册密码:");
scanf("%s",get_usrpass);
FILE* fp=fopen("./usr.txt","r");
char file_name[20];
char file_pass[20];
int flag=0;
while(1)
{
if(fscanf(fp,"%s %s",file_name,file_pass)==EOF)
{
flag=1;
break;
}
if(strcmp(get_usrname,file_name)==0)
{
printf("用户已存在!\n");
int b=0;
printf("请问是否直接选择登录(0/1):");
scanf("%d",&b);
if(b==1)
{
log_on();
}
break;
}
}
if(flag==1)
{
fclose(fp);
fp=fopen("./usr.txt","a+");
fprintf(fp,"%s %s",get_usrname,get_usrpass);
fputc(10,fp);
printf("注册成功!\n");
}
fclose(fp);
}
例:将1.txt的内容拷贝到2.txt中
#include
#include
#include
int main(int argc, const char *argv[])
{
//以读的方式打开文件
FILE* fp_r=fopen("./1.txt","a+"); //可以是r a a+
if(NULL == fp_r)
{
printf("__%d__\n",__LINE__);
perror("fopen");
return -1;
}
printf("以读的方式打开成功\n");
//以写的方式打开目标文件
FILE* fp_w=fopen("./2.txt","w");
if(NULL == fp_w)
{
printf("__%d__\n",__LINE__);
perror("fopen");
return 0;
}
printf("以写的方式打开成功\n");
//写文件
char c = 0 ;
int rec = 0;
while(fscanf(fp_r,"%c", &c)!=EOF)
{
fprintf(fp_w,"%c", c);
}
printf("拷贝成功\n");
//此时文件偏移量在文件的结尾,如果想要从copy.c文件中读取数据
//则需要将文件描述符重新偏移打破文件开头位置
//所以需要关闭文件重新打开,将偏移量重新改回到开头位置
fclose(fp_w);
fp_w=fopen("./2.txt","r");
while(fscanf(fp_w,"%c",&c)!=EOF)
{
printf("%c", c);
}
fclose(fp_w);
return 0;
}
例:将1.txt的内容拷贝到2.txt中
要求:
1. 用fgetc计算一个文件有多少个字节
2. 用fgetc计算一个文件有几行
注意:
1. 运算符优先级: =号优先级最低
2. 可以用\n计算行数
#include
#include
#include
#include
int main(int argc, const char *argv[])
{
//打开可读文件
FILE* fp_r=fopen("./02_fprintf.c","r");
if(NULL == fp_r)
{
printf("__%d__",__LINE__);
perror("fopen");
return -1;
}
//打开可写文件
FILE* fp_w=fopen("./2.txt","w");
if(NULL == fp_r)
{
printf("__%d__",__LINE__);
perror("fopen");
return -1;
}
char c=0;
int count=0,row=0;//count计算字节数 row计算行数
//开始拷贝
while((c=(fgetc(fp_r)))!=EOF)
{
count++;
if(c=='\n')
{
row++;
}
fputc(c,fp_w);
}
printf("拷贝成功\n");
printf("2.txt总共有%d个字节\n",count);
printf("2.txt共有%d行\n",row);
//关闭两个文件
fclose(fp_r);
fclose(fp_w);
return 0;
}
1. 标准IO函数根据ANSI标准,对文件IO的二次封装,printf、scanf、getchat、putchar
2. 最终标准IO函数依然会去调用文件IO函数
scanf:
if(OS == Linux)
{
去调用Linux的文件IO
read();
}
else if(OS == windows)
{
去调用windows的文件IO
fread();
}
struct _IO_FILE {
char* _IO_buf_base; 缓冲区的起始地址
char* _IO_buf_end; 缓冲区的结尾地址
int _fileno; 文件描述符,在文件IO的时候再讲解。
}
缓冲区大小:尾地址-首地址。
#include
#include
int main(int argc, const char *argv[])
{
FILE* fp= fopen("./1.txt","w");
if(NULL == fp)
{
perror("fopen");
return -1;
}
printf("fopen函数运行成功\n");
if(fclose(fp)<0)
{
perror("fclose");
return -1;
}
printf("fclose函数运行成功\n");
return 0;
}
知识点:
errno:本质上是一个整型数,不同的错误会更新不同的errno;
定义在errno.h这个头文件中
所有情况可在以下两个文件查看(共133种):
① /usr/include/asm-generic errno.h
② /usr/include/asm-generic errno-base.h
其中:
errno=2的意思是没有这个文件
errno=13的意思是权限不够
#include
#include
#include
int main(int argc, const char *argv[])
{
//打开文件
FILE* fp=fopen("fprintf.txt","w");
if(NULL == fp)
{
perror("fopen");
return -1;
}
printf("fopen success\n");
//将hello world 12输出到fprintf.txt文件中
//printf("hello world %d\n", 12);
fprintf(fp,"hello world %d\n", 12);
//将一个整型数组输入到fprintf.txt文件中
int arr[]={1,2,3};
for(int i=0;i
#include
#include
#include
int main(int argc, const char *argv[])
{
//打开文件fprintf.txt
FILE* fp=fopen("./fprintf.txt","r");
if(NULL==fprintf)
{
perror("fopen");
return -1;
}
printf("以读的方式打开成功\n");
char str1[10]="";
char str2[10]="";
int a=0,b=0,c=0;
fscanf(fp,"%s%s%d",str1,str2,&a);
printf("%s %s %d\n",str1,str2,a);
/*使用循环读取文件中的数据并打印在终端中
int arr[3];
for(int i=0;i<3;i++)
{
fscanf(fp,"%d",&arr[i]);
printf("%d\t",arr[i]);
}
*/
fscanf(fp,"%d%d%d",&a,&b,&c);
printf("a=%d\nb=%d\nc=%d\n",a,b,c);
//关闭文件fprintf.txt
if(fclose(fp)<0)
{
perror("fclose");
return -1;
}
printf("fclose success\n");
return 0;
}
#include
#include
#include
#include
int main(int argc, const char *argv[])
{
//使用写权限打开文件
FILE* fp = fopen("fputc.txt","w");
if(NULL == fp)
{
perror("fopen");
return -1;
}
printf("fopen success\n");
//将单字符输入到fputc.txt中
fputc('a',fp);
fputc('b',fp);
fputc('c',fp);
//关闭文件
fclose(fp);
//使用读权限再次打开文件
fp = fopen("fputc.txt","r");
if(NULL == fp)
{
perror("fopen");
return -1;
}
printf("fopen success\n");
//循环读取fputc.txt文件中的字符,并输入
int c=0;
while(1)
{
c=fgetc(fp);
if(EOF == c)
break;
printf("%c %d\n", c, c);
}
//关闭文件
fclose(fp);
return 0;
}