标准IO函数的学习以及IO概念

什么是IO

  • I:input ——输入,从外部存储设备将数据输入到内存中
  • O:output ——输出,数据从内存到外部存储设备中
    标准IO函数的学习以及IO概念_第1张图片
  • 输入输出就是数据从外存到内存,内存到外存的流向

IO分类

文件IO函数

  • 文件IO是由操作系统提供的基本IO函数,与操作系统绑定,也可以称为操作系统的调用
  • 移植性低,只能运行在对应的操作系统中
  • 文件IO涉及到用户空间到内核空间的切换、cpu模式的切换、C代码调用汇编指令等等,属于一种耗时操作,应该尽量减少文件IO函数的使用
  • 若要操作内核,内核只能使用文件IO函数

标准IO函数

  • 标准IO函数根据ANSI标准,是对文件IO函数的二次封装
  • 最终标准IO函数依然会去调用文件IO函数
  • 提高了代码的可移植性和复用性
  • 提高输入输出效率
    在用户空间设置一个缓冲区,缓冲区满或者满足一定条件之后,调用文件IO函数。
    标准IO函数的学习以及IO概念_第2张图片

标准IO函数

流和流指针

  • 流:流字节,将数据一个一个的移入或移出缓冲区的形式叫做字节流
  • (FILE *)流指针:当要做IO操作时,需要打开一个对应文件,每打开一个文件就会在内存中申请一片缓冲区,同时管理和维护这片空间的变量都存储在FILE结构体中,FILE结构体由系统定义好,可直接调用。

FILE结构体成员

  • 查看指令:vi -t(这个指令可以查看系统定义好的 数据类型、宏、变量)
  • 格式:vi -t FILE
  • 追加代码:
    1>将光标停留在要追的字符上, 按下ctrl + ]
    2>ctrl + 鼠标左键点击要追的内容
  • 返回:
    1>ctrl+t;
    2>ctrl+鼠标右键

标准IO函数

fopen

  • 功能:打开一个文件
  • 原型:FILE *fopen(const char *pathname, const char *mode);
  • 参数:char *pathname:指定要打开的文件路径以及名字
    char *mode:以什么方式打
    (1)r:以读的方式打开文件,流在文件开头位置(从开头开始读取),若不存在,则打开失败
    (2)r+:以读写的方式打开文件,流在文件开头位置,若不存在,则打开失败
    (3)w:以写的方式打开文件,若要写文件,则从开头开始;若文件不存在,则创建并打开;若文件存在,则会清空原文件
    (4)w+:以读写的方式打开文件,若要写文件,则从开头开始;若文件不存在,则创建并打开;若文件存在,则会清空原文件
    (5) a:以写的方式打开文件,不会清空文件,流在文件结尾,若文件不存在,则会创建文件并打开
    (6) a+:以读写的方式打开文件,若文件不存在,则会创建文件并打开;若文件存在,开始为读,则流在文件开头,开始为写,则流在文件结尾
  • 返回值:成功返回FILE *指针类型,失败返回NULL,同时更新error
    errno:本质上是一个整型数,不同的错误会更新不同的errno;

perror

  • 功能:根据errno,打印对应的错误信息
  • 原型:void perror(const char *s)
  • 参数:char *s:用于提示的字符串

fclose

  • 功能:关闭指定的文件,释放资源
  • 原型: int fclose(FILE *stream)
  • 参数:FILE *stream:指定要关闭的文件对应的流指针
  • 返回值:成功返回0,失败返回EOF,同时更新error

fprintf

  • 功能:将数据格式化输出到指定文件中
  • 原型: int printf(const char *format, …)
    int fprintf(FILE *stream, const char *format, …)
  • FILE *stream:流指针,指定要输出到哪个文件中,就填对应文件的流指针
    char *format:格式化字符串:字符,占位符,转义字符
    …:不定参数,不定数据个数,不定数据类型
  • 返回值:成功:返回被打印的字符个数
    失败:返回负数

fscanf

  • 功能:从指定文件中格式化读取数据(%d %s不识别空格和转义字符,%c识别空格和转义字符)
  • 原型: int scanf(const char *format, …);
    int fscanf(FILE *stream, const char *format, …);
    参数:FILE *stream:流指针,指定要输出到哪个文件中,就填对应文件的流指针
    char *format:格式化字符串:字符,占位符,转义字符
    …:不定参数,不定数据个数,不定数据类型
  • 返回值:成功:返回成功读取的数据个数
    ==EFO表示文件读取完毕也表示运行失败,同时更新errno

fputc

  • 功能:将单个字符打印到指定的文件中
  • 原型: int fputc(int c, FILE *stream);
  • 参数:int c:指定要输出的字符对应的字符形式或者整型形式
    FILE *stream:流指针,对应的文件的流指针
  • 返回值:成功返回输出字符对应的整型形式;失败返回EOF

fgetc

  • 功能:从指定文件中读取单个字符
  • 原型:int fgetc(FILE *stream)
  • 参数:FILE *stream:指定要从哪个文件中读取
  • 返回值:返回成功读取到字符对应的整型形式;当文件读取完毕或者函数运行失败,返回EOF

注意:

  • %s %d不识别空格 \n \t,若想要获取到上述字符,需要使用%c形式
  • 读写操作后,文件偏移量会自动偏移,所以若想要从头读取数据,就需要想办法将偏移量修改到开头位置

作业

一、实现登录功能。自定义一个usr.txt,手动输入账户密码,格式如下:账户 密码
例如: zhangsan 12345
lisi abcde
wangwu abc123
需求如下:
从终端获取账户密码,与文件中的账户密码比较
若终端输入的账户不存在,则输出账户不存在
若终端输入的账户存在,但是密码不正确,则输出密码错误
若账户密码均正确,则输出登录成功

附加题
实现注册功能,注册的账户密码存储在上一题的文件中。需求:不能重复注册。

#include 
#include 
#include 
int main(int argc, const char *argv[])
{
	FILE *fp=fopen("usr.txt","a+");
	if(NULL==fp)
	{
		printf("打开失败\n");
		return -1;
	}
	char num[20]="";
	char password[20]="";
	printf("请输入账号:");
	scanf("%s",num);
	printf("请输入密码:");
	scanf("%s",password);
	char name_u[20]="";
	char password_u[20]="";
	int c=0;
	char ch;
	while(1)
	{
		 c=fscanf(fp,"%s %s",name_u,password_u);
		 if(EOF==c)
			 break;
		 //登录成功
		 if(0 == strcmp(name_u,num) && 0 == strcmp(password,password_u))
		 {
			 printf("登录成功\n");
			 break;
		 }
		 //账户比较
		 else if(0 != strcmp(name_u,num))
		 {
			 printf("用户名不存在,是否要注册,请输入Y/N:");
			 //注册功能
			 scanf(" %c",&ch);
			 if('N'==ch)
			 {
				 break;
			 }
			 else
			 {
				 fprintf(fp,"%s %s\n",num,password);
				 printf("注册成功\n");
			 }

		 }
		 //密码比较
		 else if(0 == strcmp(name_u,num) || 0 != strcmp(password,password_u))
		 {
			 printf("密码错误\n");
			 break;
		 }
	}
	fclose(fp);
	fp=NULL;
	return 0;
}

二、用fgetc与fputc函数实现:运算符优先级: =号优先级最低。

文件拷贝,例如将1.txt的内容拷贝到2.txt中
要求用fgetc计算一个文件有多少个字节
用fgetc计算一个文件有几行?

#include 
#include 
#include 
int main(int argc, const char *argv[])
{
	FILE *fp_r=fopen("1.txt","r");
	FILE *fp_w=fopen("2.txt","w+");
	if(NULL == fp_r || NULL == fp_w)
	{
		perror("fopen");
		return -1;
	}
	int c=0;
	int count=0;
	int line=0;
	while(1)
	{
		c=fgetc(fp_r);
		if('\n'== c)
			line++;
		if(EOF == c)
			break;
		count++;
		fputc(c,fp_w);
		printf("%c",c);
	}
	printf("fp_r文件有%d个字节,有%d行\n",count,line);
	fclose(fp_r);
	fclose(fp_w);
	fp_r=fp_w=NULL;
	return 0;
}

三、思维导图总结

你可能感兴趣的:(学习,c语言)