标准I/O函数

标准IO是带缓冲的IO,IO流,它的效率要比系统IO要高
系统IO:
read 1byte   从硬件上面读取一个字节

标准IO:
read 1byte     从硬件上面读取一块(512byte)出来,放到标准IO的缓冲区。

 

标准IO缓冲区有三种类型:
行缓冲(_IOLBF):缓冲区的数据达到了一行,自动的同步到你的硬件上面去
                假设你设置的一行的大小最多为512字节
                缓冲区的数据达到了512字节,就会自动的同步
                printf()------>行缓冲
                遇到\n(换行符,一行结束),也会把数据同步到外设上面去
        
        全缓冲(_IOFBF):缓冲区的数据要填满整个缓冲区,才会同步到外设上面去
        
        无缓冲(_IONBF):缓冲区只要有数据,就会同步到外设上面去
                perror ---->无缓冲

 

标准IO也会自动为每一个进程打开三个标准IO流(FILE),对应系统IO中打开的三个文件:
        标准输入文件(流)     FILE *stdin
            stdin是定义在<stdio.h>中的一个全局变量,它指向标准输入文件(一般是终端或者键盘)
                scanf()   <-----stdin 中读取
        标准输出文件(流)    FILE *stdout
            stdout是定义在<stdio.h>中的一个全局变量,它指向标准输出文件(一般是终端)
                printf()    <----stdout
        标准错误文件(流)    FILE *stderr
            stderr是定义在<stdio.h>中的一个全局变量,它指向标准错误文件(一般是终端)
                perror()   <-----stderr

 

1、打开一个文件流(fopen)

#include <stdio.h>
FILE *fopen(const char *pathname, const char *mode);
pathname:你要打开的文件的路径名
mode:打开方式,常用的有如下几种
        "r":只读打开,文件不存在,则报错
            打开后,光标在开头
        "r+":读写打开,文件不存在,则报错
            打开后,光标在开头
        "w":只写打开,文件不存在,则创建
            打开后,文件的内容截短(文件本来的内容就被清理),光标在开头
        "w+":读写打开,文件不存在,则创建
            打开后,文件的内容截短(文件本来的内容就被清理),光标在开头
        "a":append 追加打开(可写),文件不存在,则创建
            打开后,光标在文件末尾,文件的内容不会被截短
        "a+":append 追加打开(可写),文件不存在,则创建
            打开后,原始读的光标在开头,原始写的光标在末尾
            只有一个光标,打开文件后,先读,则光标在开头,如果先写,光标在末尾
返回值:
成功返回一个FILE*指针,指向FILE结构体,保存了文件的信息,在标准IO中,使用FILE结构体表示一个已经打开的文件,后面的操作都需要这个结构体
失败返回NULL,同时errno被设置
            
FILE *fdopen(int fd, const char *mode);
和fopen类似,只不过第一个参数是文件描述符

FILE *freopen(const char *pathname, const char *mode, FILE *stream);
和fopen类似,是使用stream指向一个新打开的文件

 

2、打开一个文件流(fclose)

 #include <stdio.h>
用来关闭一个stream指向的文件流
int fclose(FILE *stream);
stream:你要关闭的流的指针,一般是fopen的返回值
返回值:
成功返回0
失败返回EOF,同时errno被设置

 

3、从指定的文件流stream中读取一个字符

#include <stdio.h>
从指定的文件流stream中读取一个字符
int fgetc(FILE *stream);
int getc(FILE *stream);
stream:指定的文件流
返回值:
成功返回读取到的字符的ASCII码
失败返回-1,同时errno被设置
        
fgetc和getc的区别?
fgetc 是一个函数
getc可能是使用宏定义实现的
            
从标准输入流中读取一个字符,并且把读取到的字符的ASCII码返回
int getchar(void);        
getchar(void) <====> fgetc(stdin)

 

4、把字符(ASCII码)输出到stream指定的文件流中去

#include <stdio.h>
fputc和putc是用来把c这个字符(ASCII码)输出到stream指定的文件流中去
int fputc(int c, FILE *stream);
int putc(int c, FILE *stream);
c:要输出的字符的ASCII码

返回值:
成功返回实际输出的字符的ASCII码(c)
失败返回-1,同时errno被设置

fputc和putc有什么区别呢?
fputc 是一个函数
putc可能是使用宏实现的

putchar用来把c指定的字符输出到标准输出
int putchar(int c);
putchar(c) <====> fputc(c,stdout);

 

4、 每次一行的读

#include <stdio.h>
gets从stdin读取一行字符保存到s所指向的缓冲区,直到遇到换行符或EOF,然后将其替换为空字节(\0)。不检查缓冲区溢出(bugs)
char *gets(char *s);
s:指针,用来指向一个可用的空间,存储读取到的字符串   

返回值:
        成功返回s的首地址
        失败返回NULL,同时errno被设置
        gets有一个巨大的BUG(不检查缓冲区溢出),s指向的这个空间有可能不够大,不能保存读取到的一行字符
        
char *fgets(char *s, int size, FILE *stream);
        s:指针,用来指向一个可用的空间,存储读取到的字符串
        size:表示你最多获取size个字节,size一般是s指向的空间的可用大小
        fgets输入结束有两种情况:
                1.遇到了\n或者文件流结束(EOF)
                2.已经读取了size-1个字符(最后一个字节保存\0)
        stream:你要从哪一个文件流中获取数据

返回值:
        成功返回s的首地址
        失败返回NULL,同时errno被设置

 

5、 每次一行的写

#include <stdio.h>

int fputs(const char *s, FILE *stream);
int puts(const char *s);  //输出到标准输出stdout
       s:指针,指向你要输出的字符串的首地址(从s指向的位置开始,往后找到第一个\0为止)
       stream:你要输出到哪里去(文件流)

返回值:
            成功返回一个非负数
            失败返回-1,同时errno被设置

 

6、直接读写

#include <stdio.h>
fwrite用来把ptr指向的n个元素(每一个元素大小为size个字节)写入到stream指向的文件中去
        size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
            ptr    :指针,要写入的对象的首地址
            size:每一个元素大小
            nmemb:要写入的对象个数
            stream:你要写入到哪一个文件

返回值:
                成功返回实际写入到文件中去的元素个数(<=nmemb)
                失败返回-1,同时errno被设置

 

fread用来从stream指向的文件流中读取n个对象,且每一个对象为size个字节(n*size),读取的内容保存到ptr指向的内存空间中去
        size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
            ptr:指针,指向一个可用的内存空间,保存读取到的对象
            size:每一个元素大小
            nmemb:要读取的对象个数
            stream:你要从哪一个文件流中获取数据

返回值:
                成功返回实际读取到的元素个数( <=nmemb)
                失败返回-1,同时errno被设置

 

7、冲洗一个文件流(把缓冲区的内容同步到外设)

#include <stdio.h>
int fflush(FILE *stream);
        stream:你要冲洗的文件流

返回值:
            成功返回0
            失败返回-1,同时errno被设置

注意:
            对普通文件: *in *out
            对于输入流:fflush把读缓存区中的内容直接丢弃,下一次read,会重新从文件中读取内容
            对于输出流:fflush把写缓冲区的内容同步到文件中去           

stream为NULL,fflush就会把该进程所有打开的文件流都做一个同步    

 

8、定位一个文件流(定位文件的光标)

 #include <stdio.h>
fseek用来定位光标的位置
int fseek(FILE *stream, long offset, int whence);
       stream:你要定位的文件的指针
       offset:偏移量,可正可负,配合第三个参数使用
       whence:定位方式,有如下三个标志
        SEEK_SET 基于文件开头定位
            新光标位置 = 文件开头 + 偏移量(>=0)
        SEEK_CUR 基于文件当前位置定位
            新光标位置 = 文件当前位置 + 偏移量(可正可负)
        SEEK_END 基于文件末尾定位
            新光标位置 = 文件末尾 + 偏移量(可正可负)

返回值:
        成功返回0
        失败返回-1,同时errno被设置

ftell返回当前光标位置离文件开头有多少个字节
       long ftell(FILE *stream);
       可以测试文件大小
       fseek(stream,0,SEEK_END);
       long size = ftell(stream);
       
把指定的文件流的光标重新定位到开头
       void rewind(FILE *stream);
       
int fgetpos(FILE *stream, fpos_t *pos);
int fsetpos(FILE *stream, const fpos_t *pos);

 

9、格式化的输入和输出

格式化输入scanf/sscanf/fscanf
按照用户指定的格式输入

#include <stdio.h>

       scanf用来从标准输入缓冲区获取数据
       int scanf(const char *format, ...);
       int a,b,c;
       scanf("%d%d%d",&a,&b,&c);
       
       char buf[128] = "%d%d%d"
        scanf(buf,&a,&b,&c);
       scanf可以带很多个参数,scanf的参可以分为两类:
       第一类就是第一个参数,格式化字符串
       format string:就是告诉用户该如何输入,你必须按照指定的格式输入,不然就会输入失败
       格式化字符串由三种字符组成:
        a.空白符(space tab)
            指示用户,你可以输入任意数量的空白符作为分隔符(包括0个)
            scanf("%d      %d",&a,&b);
        b.非转义字符(普通字符,除了空白符和%开头的字符以外)
            在输入的时候,必须精确匹配,你必须按照格式化字符串一模一样的输入
            scanf("%dabcdefg%d",&a,&b);
            123abcdefg456
        c.转义字符,有特殊含义的字符(%开头的字符)
            %d ----->匹配十进制数字
            %c ----->匹配一个字符(可以输入的字符)
            %s---->字符串(不能有空白字符,scanf把空白字符当成分隔符)
            %f --->匹配一个浮点数
            ....
        
        其他参数为第二类参数,地址列表
            格式化字符串中的每一个转义字符都会对应一个地址,把转义字符匹配到的内容存储到指定的地址上去,如果转义字符和地址个数不匹配,程序的行为是未定义的
            
        scanf从标准输入流中获取数据,如何结束?
            a.该输入的都输入完了
            scanf("%dabcdefg%d",&a,&b);
             123abcdefg456
             所有的字符都匹配成功,scanf就结束了
             
            b.scanf匹配失败了
            scanf("%dabcdefg%d",&a,&b);        
            用户输入:
                123bcdefg456
                123会匹配成功 --->a(123)
                后面的会匹配失败,直接结束
                返回1

返回值:
            成功匹配的变量的个数

sscanf它的功能和用法和scanf类似,只不过,sscanf的输入来源不是标准输入而是从str指向的字符串(内存)中获取。
       int sscanf(const char *str, const char *format, ...);
            char *buf = "123"
            int a;
            r = sscanf(buf,"%d",&a);
            a = 123
            r = 1
fscanf它的功能和用法和scanf类似,只不过,fscanf的输入来源不是标准输入而是从stream指向的文件流中获取。
       int fscanf(FILE *stream, const char *format, ...);

 

格式化输出printf/sprintf/fprintf

#include <stdio.h>

       int printf(const char *format, ...);
        printf可以带很多个参数,printf的参可以分为两类:
       第一类就是第一个参数,格式化字符串
       format string:就是告诉用户该如何输出,输出的时候会按照格式化字符串一模一样输出
       格式化字符串由两种字符组成:
        a.非转义字符(普通字符,除了%开头的字符以外)
            在输出的时候,会按照格式化字符串一模一样的输出
        b.转义字符,有特殊含义的字符(%开头的字符)
            %d ----->把指定的对象按照十进制整数输出
            %lu
            %u
            %c ----->把指定的对象按照字符输出
            %s---->把指定的对象按照字符串输出
            %f
            ....
            每一个转义字符,对应一个输出对象
            
        其他参数为第二类参数,对象列表
            格式化字符串中的每一个转义字符都会对应一个对象,如果转义字符和对象个数不匹配,程序的行为是未定义的

返回值:
            实际输出的字符的数量
            r = printf("abcde");
            r = 5

fprintf它的功能和printf类似,只不过printf把输出的内容输出到标准输出(tdout),而fprintf把输出的内容输出到stream指定的文件流中去    
       int fprintf(FILE *stream, const char *format, ...);
        printf("abcde"); ====>fprintf(stdout,"abcde");

返回值:
            实际输出的字符的数量

dprintf它的功能和printf类似,只不过printf把输出的内容输出到标准输出(tdout),而dprintf把输出的内容输出到fd指定的文件中去    
       int dprintf(int fd, const char *format, ...);

返回值:
            实际输出的字符的数量

sprintf它的功能和printf类似,只不过printf把输出的内容输出到标准输出(tdout),而sprintf把输出的内容输出到str指定的内存中去
       int sprintf(char *str, const char *format, ...);

返回值:
            实际输出的字符的数量
        作用:
            把多个对象按照指定的方式拼接起来
            char filename[512] = {0};
            sprintf(filename,"%s/%s",path,dp->d_name);
            --------------------------------------------
            char filename[512] = {0};
            r = sprintf(filename,"%s/",path);
            r+= sprintf(filename+r,"%s",dp->d_name);
        
        sprintf有一个巨大的bug,不会进行str指向的内存可用大小的检测
        str只是指定了一个内存的起始地址,并没有指定str指向的内存的可用长度,有可能会造成内存越界
        输出的内容的长度  > str指向的空间的可用大小
        ====>内存的非法访问
        所有为了解决这个bug,就有了snprintf

snprintf它的功能和printf类似,只不过printf把输出的内容输出到标准输出(tdout),而snprintf把输出的内容输出到str指定的内存中去,并且进行可用大小的检测

       int snprintf(char *str, size_t size, const char *format, ...);
        实际输出的数据长度最大为size-1个字节(最后一个字节保存\0)
        注意:
            snprintf它的返回值,是原先应该输出的内容长度,而不是实际输出的内容的长度
        
            char s[8];
            char *str = "123456789"
            int r = snprintf(s,8,"%s",str);
            r = 9;//实际应该输出的内容的长度

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值