-
标准IO
-
什么是标准IO
-
头文件stdio.h
-
用的最多的两个输入输出函数printf和scanf
- 针对终端的输入输出函数
-
-
数据输入到特定的文件需要的条件
-
需要知道指定文件的文件名和位置
-
输入到文件中的内容
-
-
指定文件
-
fopen函数
- FILE *fopen(const char *pathname, const char *mode)
-
功能描述
-
打开pathname文件,并将其关联到一个流指针,该指针通过返回值的形式返回值。
- 通过操作这个返回出来的流指针,就相当于在操作文件本身
-
文件会以mode的方式打开,mode有以下几种情况
-
r:以只读的形式打开文件,如果文件不存在,就会打开失败,fopen就会返回NULL,文件打开成功后,光标位于文件的最开头(即第一个数据的前面)
- 补:光标位于文件的最末尾指文件的最后一个字符的后面(及文件的结束符)
-
r+:以读写的形式打开文件,其他和r一样
- 但是r+打开的文件读写同时存在,并且光标独立管理
-
w:以只写的形式打开文件,若文件不存在,则创建后打开,若文件存在,则清空文件打开(清空操作),文件打开后,光标位于文件的开头
-
补:w打开文件,也存在失败的可能,即文件打开数量超过系统上线(1024个)
-
可通过shell指令ulimit -a查看打开文件数量 同理文件打开失败会返回NULL
-
-
w+:以读写的方式打开文件,其他的和w一样
- 读写光标独立管理
-
a:以追加的方式打开文件
-
若文件不存在,则创建文件后打开,若文件存在,则直接打开(无清空操作)
-
文件打开后光标置于文件末尾
-
-
a+: 以追加和读的方式打开文件
- 注:读光标是在文件的开头,写文件是在文件的结尾 两个光标独立管理
-
-
IO操作与数据库:IO没有办法直接删除某一项数据,只能通过逻辑操作来实现
-
-
-
当不再使用文件时关闭文件
-
int fclose(FILE *stream);
-
功能描述:传入一个文件的的流指针,关闭该文件
-
-
3个特殊文件流指针
- FILE *stdin:标准输入流
-
-
文件的输入输出函数
-
第一组针对文件的输入和输出函数
-
fprintf();
-
int printf(const char *format, ...);
- 调用形式: printf("%d helloworld\n",123) 功能描述:printf默认使用stdout标准输出流 printf会将 format 中的内容通过流指针stdout标准输出流,输出到终端上面去
-
int fprintf(FILE *stream, const char *format, ...);
- 功能描述:fprintf会将format中的内容,通过流指针stream,输出到指定的文件中去 调用形式: fprintf(stream,"%d helloworld",345); 也就是说,当fprintf的第一个参数,写成stdout的话,效果等同于printf
-
int sprintf(char *str, const char *format, ...);
- 功能描述:将format中内容,写入到 str指向的字符数组里面去,实现一个任意数据类型转换成字符串的效果
-
-
fscanf();
-
int scanf(const char *format, ...);
- 功能描述:默认使用流指针 stdin,从stdin所代表的终端中,读取数据,将读取到的数据写入到format中格式占位符所代表的变量中去
-
int fscanf(FILE *stream, const char *format, ...);
-
功能描述:从流指针 stream所指向的文件中,读取数据,将读取到的数据写入到format中格式占位符所代表的变量中去
-
注意:使用fscanf吸收文件中的所有内容的时候,如何确定循环次数
-
a:通过fscanf的返回值来确定循环次数
-
fscanf成功返回成功吸收的数据的项数,也就是格式占位符的数量
-
失败吸收数据或者读取到了文件的末尾,返回 EOF (-1)
-
b:通过函数 feof 来确定是否读取到了文件的末尾
-
-
-
int feof(FILE *stream);
-
功能描述:传入等待判断是否读取到文件末尾的文件流指针,如果该文件已经被读取到了末尾,则返回1,没有读取到末尾,返回0
- 注意:fscanf使用%c的时候,能够吸收空格和回车
-
-
文件内容结束标志
-
res = fscanf(fp,"%s",buf);
-
if(i != res)
- i:fscanf第二个参数格式占位符的数量
-
if(res == EOF)
-
if(feof(fp) == 1)
-
-
-
int sscanf(const char *str, const char *format, ...);
-
功能描述:从指针str所指向的字符数字/字符串中,读取数据,将读取到的数据写入到format中格式占位符所代表的变量中去。
-
最终实现了:将字符串类型的数据,转换成任意类型的数据
-
-
-
-
第二组针对文件的输入输出函数
-
fputc();
-
int fputc(int c, FILE *stream);
-
功能描述:将参数c输出到stream所指向的文件中
-
返回值
-
成功返回写入的字符,以unsigned char 形式返回,失败返回则EOF(-1)
-
fputc('x', stdout)等价于fprintf(stdout,"%c",'x');
-
-
-
fgetc();
-
int fgetc(FILE * stream);
-
功能描述
-
从stream指向的文件中读取一个字节的数据,并以返回值的形式。返回读取到的数据
-
返回值
-
成功读取,以unsigned char 的形式,返回读取到的字符数据,
-
失败返回 -1
-
-
-
-
返回值不能用unsigned char 接收
- 返回值为负一会被强转为255
-
-
第三组针对文件的输入输出函数
-
fputs
-
int fputs(const char * s, FILE *stream);
-
功能描述
-
将字符串或字符数组S写入到文件中
- S最后的结束符不会写入文件
-
-
参数1
- 输入到文件中的字符串/字符数组
-
参数2
- 指定的被输出的数据文件
-
返回值
-
成功:返回写入字符的个数
-
失败返回EOF
- 文件末尾
-
-
-
fgets
-
char *fgets(char *s, int size, FLIE *stream)
-
功能描述
-
从stream指向的文件中,读取最多size - 1个字节的数据,然后将其写入s所指向的字符数组中,所有数据写入完成后,会再次写入一个结束符。
- 当手动输入字节大小时需预留1个字节的空间用于存放结束符
-
-
注意
- fgets只读取一行内容(回车结束)或'\0'或文件结束符,或者当读取字节大小达到size - 1就会结束读取
-
参数1
- 存放读取到的数据的数组
-
参数2
- 存放读取的字节大小,函数内部会自动将size -1 ,即读取size - 1个字节的数据
-
参数3
- 从stream指向的文件中读取数据
-
返回值
-
成功读取,返回第一个参数(字符串数组名)
-
失败或文件末尾
- 返回NULL或EOF
-
-
故使用fgets读取文件中内容时需循环读取
-
循环结束条件
- char *res = fgets(); if(res == NULL){break;} if(feof(fp) == 1){break;}
-
-
-
-
第四组针对文件的输入输出函数
-
fwrite
-
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
-
功能描述
- 将nmemb个数据块(每块size大小)写入stream所指文件中,数据块首地址由ptr决定
-
参数1
- 想要写入文件中的数据块的首地址
-
参数2
- 每个数据块的大小
-
参数3
- 数据块的个数
-
参数4
- 指向文件的流指针
-
返回值
-
成功返回写入数据块的数量
-
失败返回0或小于nmemb的一个数据
-
-
将数据写入文件中使用的是数据流(二进制字节流)
-
文件流
- 前面学习的fprintf,fputc,fputs无论什么数据,都会以字符串的形式传入文件
-
数据流
- 只有字符或字符串,在文件中是以字符串的形式传入,其余以二进制方式存在
-
-
-
fread
-
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
-
功能描述
- 从stream指向的文件中,读取nmemb个数据块,每个数据块size大小,然后将读取到的数据块存入ptr指向的内存中
-
第一个参数
- 读取数据的存放空间
-
第二个参数
- 一个数据块的字节大小
-
第三个参数
- 数据块的数量
-
第四个参数
- 传入的文件流指针
-
返回值
-
通过if语句对其结束进行判断
-
成功返回读取数据块的数量,
-
失败返回0或nmemb的第一个数据
-
-
注意
-
fread读取数据块时,可能导致某个数据块出现文件结束符,从而导致fread函数返回0,我们需要做到
-
数据明确时严格按照数据字节大小进行读取
-
数据块大小不明确时,1个字节一个字节读取
-
-
fwrite将数据写入文件中,使用的是数据流,
-
-
-
-
-
光标偏移函数
-
fseek
-
int fseek(FILE *stream, long offset, int whence)
-
将文件的光标位置从whence位置偏移offset个字节
-
参数一
- 文件流指针
-
参数二
- 光标偏移量,+为从左向右偏移,-为从右向左偏移
-
参数三
-
偏移起始位置
-
SEEK_SE
- 文件开头
-
SEEK_CUR
- 文件当前位置
-
SEEK_END
- 文件末尾(结束符脸上)
-
-
-
fseek读写光标是一起偏移的,不做区分
-
-
-
标准IO缓存区
-
printf换区验证
-
printf("hello"); while(1);
-
上述代码运行之后,发现终端并未出现"hello" 说明其没有写入终端文件,而是进入printf缓存区
-
缓存区刷新时缓存区的内容进入终端
-
缓存区刷新条件
-
遇到回车('\n')
-
缓存区满刷新
-
while(1){ printf("hello world") usleep(8000); }
-
usleep
- 休眠(us)
-
sleep
- 休眠(s)
-
-
-
程序结束
-
IO切换
-
输入输出切换
-
stdout函数
-
getchar()
-
get
-
-
stdin函数
-
-
-
文件关闭刷新
- fclose
-
调用函数fflush(传入流指针),手动刷新
- fflush(stdin);
-
-
scanf缓存区
-
当缓存区存在数据时,会读取数据,将数据取走
-
若数据不能读取,则会重复读取
-
-
-
标准IO中的缓存区分类
-
行缓存
-
1024字节
-
printf向终端输出的数据就是行缓存
-
对应stdou函数
-
-
全缓存
-
4096字节
-
fprintf,fputc,fputs,fwrite这些向外部文件输入内容的用的都是全缓存
-
刷新条件比行缓存少一个'\n'
-
-
无缓存
- perror使用标准错误流向终端输出错误信息用的是无缓存,没有刷新规则
-
标准IO的所有函数都在流指针所指向的内存空间里
-
-
计算缓存区大小
-
直接让 文件流指针._IO_buf_end - 文件流针._IO_buf_base
-
注意:使用这种方法计算缓存区的话 一定提前激活一下缓存区(调用函数)
-
-
-
作业
#include <myhead.h>
int main(int argc, const char *argv[])
{
printf("__-__-__-__");
int i = 1;
do
{
fflush(stdout);
sleep(1);
for(int i = 0; i < 11; i++)
{
printf("\b");
}
switch(i)
{
case 1:printf("1_-__-__-__");break;
case 2:printf("12-__-__-__");break;
case 3:printf("12-3_-__-__");break;
case 4:printf("12-34-__-__");break;
case 5:printf("12-34-5_-__");break;
case 6:printf("12-34-56-__");break;
case 7:printf("12-34-56-7_");break;
case 8:printf("12-34-56-78");break;
}
i++;
}while(i != 9);
return 0;
}