• Linux 标准I/O函数库


    标准I/O函数库:
     C标准库提供了文件的标准 I/O 函数库,相比前述的系统调用,主要差别是实现了跨平台的用户态缓冲的解决方案。标准I/O库使

    用简单,与系统调用I/O相似,也包括打开、读写、关闭这些操作,主要的函数列举如下。
     ◆ 打开与关闭文件:fopen,fclose。
     ◆ 读写文件:fread,fwrite。
     ◆ 读写文本行:fgets,fputs。
     ◆ 格式化读写:fscanf,fprintf。
     ◆ 标准输入输出:printf,scanf。
     ◆ 读写字符:fgetc,getc,getchar,fputc,putc,putchar。
     ◆ 其他:fflush,fseek。

     所谓标准 I/O 函数实际上是对底层系统调用的包装,最终读写设备或文件的操作仍需调用系统I/O函数来完成。

     两个重要的概念:文件指针和流。
     标准I/O函数并不直接操作文件描述符,而是使用文件指针。文件指针与文件描述符是一一对应的关系,这种对应关系由标准I/O库

    自己内部维护。应用程序调用时,只需要提供文件指针即可。文件指针指向的数据类型为FILE型,但应用程序无须关系它的具体内容。
     在标准I/O中,一个打开的文件称为流(stream),流可以用于读(输入流)、写(输出流)或者是读写(输入输出流)。每个进

    程在启动后就会打开三个流,与打开的三个文件相对应:stdin代表标准输入流,stdout代表标准输出流,stderr代表标准错误输出流,它

    们都是(FILE*)型的指针。

     标准错误输出流不进行缓冲,输出的内容会马上同步到文件(控制台设备)。

     与标准 I/O 相关的定义和声明都放在以下头文件中:#include <stdio.h>

    fopen:
     fopen函数用于打开一个文件流,其原型如下:
     FILE *fopen(const char *filename, const char *mode);

     ◆ filename:被打开的文件的名称(可包含路径)。
     ◆ mode:字符串,用于表示打开的模式。
     ◆ 返回值:打开成功后的文件指针,失败则返回NULL。

     mode如下:
     字符串    含义
     r 或 rb    以只读方式打开
     w 或 wb    以只写方式打开,若文件有内容,则清空
     a 或 ab    以只写方式打开,原内容保留,写入的内容附加在文件流尾部
     r+ 或 rb+ 或 r+b  以更新方式打开,此时文件可读可写
     w+ 或 wb+ 或 w+b  以更新方式打开,文件可读可写,但打开时清空文件内容
     a+ 或 ab+ 或 a+b  以更新方式打开,文件可读可写,写入的内容附加在文件流尾部

    fread 和 fwrite:
     fread函数用于从打开的文件流中读数据,其原型如下:
     size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);

     ◆ ptr:指向用于存放读取到的数据的缓冲区。
     ◆ size:被读取的数据块的长度。
     ◆ nitems:要读取的数据块的个数。
     ◆ stream:被读取的文件指针。 
     ◆ 返回值:实际读取到的数据块的个数。

     使用 fread 函数需要注意的是,它以数据块(或称记录)为单位进行读取,返回值也是成功读取的数据块的个数,而不是字节数

    ,这个数目有可能比要读取的个数 nitems 少。

     fwrite 函数用于向打开的文件流写入数据,其原型如下:
     size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream);

     ◆ ptr:指向存放写入数据的缓冲区。
     ◆ size:要写入的数据块的长度。
     ◆ nitems:要写入的数据块的个数。
     ◆ stream:要写入的文件指针。
     ◆ 返回值:实际写入的数据块的个数。

     与 fread 函数类似,fwrite 函数也是数据块为单位向文件流写入数据的。

    fclose:
     fclose 函数用于关闭文件,其原型如下:
     int fclose(FILE *stream);
     
     这个函数可以改变 stream 参数所代表的文件,如果改变成功则返回 0,否则将返回 EOF 并且设置变量 errno 的值以指示错误。

    改变前会自动将文件流中的数据写入文件。

    fflush:
     fflush 函数用于将文件流中的数据更新到真实的文件中,其原型如下:
     int fflush(FILE *stream);

     其中参数 stream 是要操作的文件指针,如果更新成功则返回 0,否则将返回 EOF 并且设置变量 errno 的值以指示错误。
     在用 fclose 关闭文件前,系统会自动调用 fflush 更新数据。

    fseek 和 ftell:
     fseek 用于移动文件流的读写位置,其原型如下:
     int fseek(FILE *stream, long offset, int whence);

     ◆ stream:被操作的文件指针。
     ◆ offset:读写位置的偏移量。
     ◆ whence:用于指定偏移量的相对启点。
     ◆ 返回值:0 表示操作成功, -1 表示操作失败并且设置 errno 变量的值为错误码。

     whence 参数的取值及含义:
     ◆ SEEK_SET:表示偏移量相对于文件的开头。
     ◆ SEEK_CUR:表示偏移量相对于当前的读写位置。
     ◆ SEEK_END:表示偏移量相对于文件末尾。
     
     如果要将读写位置移动到文件的开头,还可以使用这个函数:
     void rewind(FILE *stream);
     
     ftell 函数可以得到文件流的读写位置,其原型:
     long ftell(FILE *stream);
     参数 stream 是文件指针,返回值就是文件流的当前读写位置(相对于文件开头)。

    fgetc,getc,getchar:
     fgetc 函数用于从文件流中读取一个字符,其原型如下:
     int fgetc(FILE *stream);

     与它功能相同的函数时 getc,原型如下:
     int getc(FILE *stream);

     其中 stream 参数是要读取的文件流。它们返回值虽然是整型,但实际表示的是读到的字符,只不过进行了类型转换。如果读操作

    发送错误或者到达文件尾,则返回值是 EOF。
     
     getc 与 fgetc 的区别在于它可能是由宏定义实现的,因此参数可能在宏展开以后被使用多长,如果参数本身是一个表达式就会被

    多长求值,这种情况在使用中应该避免。

     getchar 函数用于从标准输入流读取一个字符,其原型如下:
     int getchar(void);

     实际上对 getchar 的调用完成等价于一下函数的调用:
     getc(stdin);

    fputc,putc 和 putchar:
     fputc 函数用于向文件流写入一个字符,其原型如下:
     int fputc(int c, FILE *stream);

     putc 函数与它的功能相同:
     int putc(int c, FILE *stream);

     ◆ c:是要写入的字符,它虽然是整型,但写入时会将其转换为无符号字符型。
     ◆ stream:要写入的文件指针。
     ◆ 返回值:写入的字符转换成整型后的值,发送错误则返回 EOF。

     putc 函数与fputc函数的区别在于它有可能是用宏定义实现的。

     putchar 用于向标准输出写入一个字符:
     int putchar(int c);

     与putc等同:
     putc(c,stdout);


    fgets 和 gets:
     fgets 用于从文件流中读取一行数据,其原型如下:
     char *fgets(char *s, int size, FILE *stream);

     ◆ s:指向一个缓冲区,用于存放读到的数据。
     ◆ size:读取的字节数上限,实际读取的字节数不会超过 size-1。
     ◆ stream:要读取的文件指针。
     ◆ 返回值:等于 s,如果有错误发生或文件结束,则返回 NULL。

     用 fgets 函数读取数据时,当读到一个换行符,或者文件结束,或者读取的字节数达到 size-1,则读取操作不再继续,函数返回

    。fgets 函数还会在读到的数据最后加一个字符 \0,使之变成一个合法的字符串。注意,如果读到换行符,则换行符也在读到数据中。
     
     gets 函数用于从标准输入读取一行数据,其原型如下:
     char *gets(char *s);
     参数 s 指向用于存放数据的缓冲区,如果读取成功则返回值就是 s,否则返回 NULL。

     gets 是一个不提倡使用的函数,因为它对读入的字节数没有控制,缓冲区是否会溢出完全取决于用户的输入。

    fputs 和 puts:
     fputs 函数用于向文件流写入一个字符串,其原型如下:
     int fputs(cnost char *s, FILE *stream);

     ◆ s:要写入的字符串,必须是以 \0 结尾的合法字符串。
     ◆ stream:要写入的文件指针。
     ◆ 返回值:非负数表示写入成功,有错误发生则返回 EOF。

     fputs 函数在向文件流写入字符串时,字符串的结束符 \0 并不会被写入。
     
     puts 函数将字符串写入标准输出,其原型如下:
     int puts(const char *s);
     
     其中 s 参数是要写入的字符串,它的返回值的含义与 fputs 函数相同。
     与 fputs 函数不同的是,puts 函数在将字符串写入之后会再写入一个换行符。
     
    fprintf,printf 和 sprintf:
     fprintf 是向文件流格式化写入数据的函数,其原型如下:
     int fprintf(FILE *stream, const char *format,...);

     ◆ stream:要写入的文件指针。
     ◆ format:格式字符串。
     ◆ 可变参数:要写入的数据。
     ◆ 返回值:如果写入成功,则返回格式化后字符串的长度,也就是写入数据的长度,负数表示有错误发生。

     常用输出转换符:
     格式符       功能
     %d 或 %i   按有符号十进制格式输出整型参数
     %u       按无符号十进制格式输出无符号整型参数
     %o      按无符号八进制格式输出无符号整型参数
     %x      按无符号十六进制格式输出无符号整型参数,使用字母 a,b,c,d,e,f
     %X      按无符号十六进制方式输出无符号整型参数,使用字母 A,B,C,D,E,F
     %c      将整型参数转换为无符号字符型,并输出为字符
     %f       按十进制格式输出高精度浮点型参数
     %e      按科学计数法格式输出高精度浮点型参数,使用字母 e
     %E      按科学计数法格式输出高精度浮点型参数,使用字母 E
     %g 或 %G  可理解为系统自带选择 %f 或 %e 格式输出
     %p      按十六进制格式输出指针型参数
     %s  将字符指针型参数视为字符串输出

     因为格式字符串中的符号 % 有了特殊的含义,所以要原样输出一个 %,则需要连续写两个 %,即 %%。

     常用输出格式符标志(放在 % 的后面):
     字符  作用
     数字 0  当输出数字时,填充 0 而不是空格
     减号 -  修改为左对齐方式,空格填充在右边
     空格   对应正数来说,左边预留一个空格作为符号位
     加号 +  总是在正数左边加上 + 符号,在负数左边加上 - 符号

     我们常用的 printf 函数实际上是对 fprintf 函数的包装,它用来向标准输出写入格式的字符串,其原型如下:
     int printf(const char *format, ...);
     它比 fprintf 函数少一个文件指针参数,因为这个文件指针一定是 stdout。

     与格式化输出相关的还有一个函数 sprintf,它并不是文件 I/O 操作,而是将格式化的字符串输出到一个缓冲区中,原型:
     int sprintf(char *str, const char *format, ...);
     其中 str 参数就指向用于存放结果的缓冲区。sprintf 函数会在输出字符串的末尾加上结束符 \0。使用这个函数时要注意,str

    指向的缓冲区要有足够的大小来容纳生成的字符串,否则就有内存访问越界的问题。很多情况下并不能事先知道结果字符串的长度,这时可

    以用下面这个函数:
     int snprintf(char *str, size_t size, const char *format, ...);
     
     ◆ size:限制生成字符串的长度,即写入缓冲区的字节数。如果格式化后的字符串长度等于或大于 size,则只写入前 size-1个 

      字节,然后写入结束符 \0。
     ◆ 返回值:格式化后的字符串长度。

    fscanf,scanf 和 sscanf:
     fscanf 可以从文件流以一定的格式读取数据,其原型如下:
     int fscanf(FILE *stream, const char *format, ...);

     ◆ stream:要读取的文件指针。
     ◆ format:格式字符串。
     ◆ 可变参数:一般是指针,指向用于存储到的数据流量。
     ◆ 返回值:成功解析的数据项的个数(不是字节数),失败则返回 EOF。

     格式字符串中的字符将与输入流中读到的字符进行匹配,具体来说有以下几种情况。
     ◆ 空白字符:包括空格、制表、换行等字符,将与输入流中的连续 0 个或多个空白字符相匹配,也就是说,一个空白字符可以消 

      耗多个空白字符。
     ◆ 普通字符:不想与从输入流读入的字符相同。
     ◆ 转换符:以符合 % 开始的多个字符,这时输入流中读入的字符将按某种格式解析为数据,存入对应的可变参数指向的变量中。
     
     常用输入转换符:
     转换符            作用
     %d            以十进制格式读入整数,存在整型变量中
     %i             当下一个字符是 0 时,以八进制格式读取整数;当下两个字符是 0x 或 0X 时,以十六进制格式读入整数;否则以十进制格式读入整数,存放在整型                                                  变量中。
     %u            以十进制格式读入整数,存放在无符号整型变量中
     %o             以八进制格式读入整数,存放在无符号整型变量中
     %x 或 %X         以十六进制格式读入整数,存放在无符号整型变量中
     %f,%g,%e 或 %E   读入浮点数,存放在浮点型变量中
     %s               读入字符串,字符串从下一个非空白字符开始,再遇到一个空白字符或者达到指定的域宽后结束。字符串存放在对应的参数指向的缓冲区中,末尾会自                                            动加上 \0
     %c             读入域宽所指定个数的字符,默认是一个。不跳过开始的空白字符,读入的字符放在对应参数指向的字符数组中,末尾不加 \0
     

     scanf 函数类似于 fscnaf 函数,只不过是从标准输入读取数据,原型:
     int scanf(const char *format, ...);

     还有一个 sscanf 函数可以从字符串中格式化读取数据,原型:
     int sscanf(const char *str, const char *format, ...);
     其中,str 参数就是被读取的字符串。

    标准 I/O 错误处理:
     当标准 I/O 操作发送错误时,比如返回 NULL 指针或者 EOF,可以通过读 errno 变量得到错误码。
     更方便的是使用标准 I/O 的错误判断函数,如:
     int ferror(FILE *stream);
     int feof(FILE *stream);

     ferror 函数用于判断文件流是否发送错误,若返回非 0 值则表示发生了错误。
     feof 函数用于判断对文件流的读写是否已到达尾部,若返回非 0 值则表示已到达尾部。

  • 相关阅读:
    TCP通信
    TCP/IP与套接字
    SPA页面性能优化
    webpack打包css样式出错
    《转》理解Object.defineProperty的作用
    vue2.0 自定义时间过滤器
    axios post提交数据格式不对的问题
    vue-cli开发时,ajax跨域详细解决办法
    关于Vue实例的生命周期created和mounted的区别
    npm install 报错(npm ERR! errno -4048,Error: EPERM: operation not permitted,)解决方法
  • 原文地址:https://www.cnblogs.com/wblyuyang/p/2759423.html
Copyright © 2020-2023  润新知