"C语言-输入输出函数"

  "C语言基础复习九"

Posted by Xu on January 26, 2018

输入输出函数

我们讨论的是ANSI C的输入输出函数

in&out

错误报告

标准库函数在一个外部整型变量errno(error.h中定义)中保存错误代码之后把这个信息传递给用户程序,提示操作失败的准确原因

当程序执行失败后,会给errno赋值指示错误类型

void perror(char const *message);//message不为NULL则打印该字符串,后面跟一个分号空格,然后打印用于解释errno当前错误代码的描述信息。

终止执行

void exit(int status);//status用于给操作系统返回提示程序终止成功还是失败

标准I/O函数库

这些ANSI C标准函数库在stdio.h中声明

所有的I/O操作只是简单地从程序移进和移出字节,这种字节流就称为流,并且绝大多数流都是全缓冲的,所以读取和写入操作实际上是从一块被称为缓冲区的内存区域来回复制数据,输出流的缓冲区只有当其写满时才会被刷新到设备和文件中

如果我们想把输出立即显示到设备,可以利用:

printf("something");
fflush(stdout);

流又分为两种类型:文本流和二进制流

文本流

数据先转换成字符,然后读入到程序

文本行的最大长度,标准规定至少允许254个字符,文本行的结尾在不同的系统中可能结束方式不同MS_DOS以一个回车符和换行符结尾,UNIX以一个换行符结尾

二进制流

在数据读取和写入过程中不做任何形式改变,直接读入到程序

文件:

stdio.h中有一个数据结构的声明为FILE,该数据结构用于访问一个流,每个流都应该又一个相应的FILE结构与之对应

    • 对于每个ANSI C程序来说运行时系统必须提供至少三个流:标准输入(stdin,一般是键盘设备),标准输出(stdout一般是屏幕和终端),和标准错误(stderr,一般同标准输出相同)

      标准I/O常量:

      在stdio.h中定义了很多与输入输出有关的常量

    • EOF:提示达到文件尾
    • FOPEN_MAX:提示一个程序可以同时打开的文件个数,它的值至少是8
    • FILENAME_MAX:提示最长文件名的长度

文件I/O步骤

  1. 程序必须为同时处于活动状态的每个文件声明一个指针变量FILE *用于流操作
  2. 流通过fopen打开,初始化FILE结构
  3. 对文件进行读写
  4. 调用fclose()关闭流,并将缓冲区的数据正确写入文件

标准I/O步骤

更为简单,不需要打开和关闭文件:

  • 字符:putchar,getchar
  • 文本行:gets,puts,scanf,printf
  • 二进制数据:fread,fwrite

上面的函数只用于标准输入和输出,对应的可用于流的如下:

  • 字符:fgetc,getc,fputc,putc
  • 文本行:fgets,fputs
  • 二进制数据:fscanf,fprintf

还有sscanf及sprintf用于输入输出内存中的字符串

打开流

fopen函数以指定方式打开一个特定文件,并将一个流与FILE结构相关联

FILE *fopen(char const *name,char const *mode);

模式:

mode 读取 写入 追加
文本 “r” “w” “a”
二进制 “rb” “wb” “ab”

FILE *freopen(char const *name,char const *mode,FILE *stream);//用于重新打开文件流,首先尝试关闭之前打开的文件流stream,然后再打开

关闭流

void *fclose(FILE *stream);//在文件关闭之前刷新缓存区,执行成功返回0,否则返回EOF,关闭是否成功也需要进行错误检查

IOfunc

字符I/O

输入:

  • int fgetc(FILE *stream);//从流中读取字符,并返回字符的整型值,如果没有更多字符可以读取,返回EOF
  • int getc(FILE *stream);//同上,宏定义
  • int getchar(void);//始终从标准输入中读取字符,宏定义

输出:

  • int fputc(int character,FILE *stream);//将指定字符输出到流,函数失败返回EOF
  • int putc(int character,,FILE *stream);//同上,宏定义
  • int putchar(int character);//始终从标准输入中输出字符,宏定义

文本行I/O

  • char *fgets(char *buffer,int buffer_size,FILE *stream);//fgets从指定的stream读取字符并复制到buffer,读取到换行符或字符个数达到buffer_size-1时停止读取,然后返回指向下一个字符的指针,如果没有更多的字符读取则返回NULL,最后返回一个NULL字节到buffer构成字符串
  • char *gets(char *buffer);//同上,但只用于标准输入流,最后并不存储NUL做结尾,这里没有指明读取字符的长度,这导致多出的字符会存储在缓存区后面,使得gets一般只用于demo程序

  • int fputs(char const *buffer,FILE *stream);//将buffer中的字符串写入到流stream中,没有指定长度因为预期以NUL字节结尾。成功返回非负值,失败返回EOF
  • int puts(char const *buffer);//同上但只用于标准输出流,最后添加的是换行符用做标准输出结尾

格式化的行I/O

  • scanf家族
    • int fscanf(FILE *stream,char const *format,…);//从流中读取数据并使用format进行格式转换
    • int scanf(char const *format,…);//从标准输入中读取数据并使用format进行格式转换
    • int sscanf(char const *string,char const *format,…);//从字符串string中读取数据,并使用format进行格式转换
    • 返回的值为读取的字符个数,若没有更多的字符可以读取则返回EOF,参数的省略号是根据格式来定义的需要赋值变量的地址列表。
  • printf家族
    • fprintf(FILE *stream,char const *format,…);//将…中的变量以format的格式输出到流stream中
    • printf(char const *format,…);//将…中的变量以format的格式输出到标准输出中
    • sprintf(char *buffer, char const *format,…);//将…中的变量以format的格式输出到buffer中,这里buffer的大小可能是错误的根源,很有可能输出结果溢出buffer

二进制的I/O

把数据写入文件最高效的方法是用二进制形式写入,二进制输出避免了在数值转换为字符串过程中所涉及的开销

  • size_t fread(void *buffer,size_t size,size_t count,FILE *stream);//读取流中的数据到buffer中去,读取数据的大小为size*count
  • size_t fwrite(void *buffer,size_t size,size_t count,FILE *stream);//将buffer中的数据写入到stream中去,写入数据的大小为size*count

stream_control_func

刷新和定位函数

刷新函数:fflush(FILE *stream);//将流缓冲区的数据物理写入到磁盘

随机访问文件:

  • long ftell(FILE *stream);//返回流的当前位置,也就是下一个即将读取字符位置的偏移量
  • int fseek(FILE *stream,long offset,int from);//表示在当前流中,从from开始为起点,移动offset偏移量到达新的流位置,from可以是下面几个值:
    • SEEK_SET:流的起始位置,offset为非负值,文本流中offset必须为0(这是因为行末字符映射?的存在,导致文本的字节数和程序写入的字节数不同)
    • SEEK_CUR:流的当前位置,offset可正可负,文本流中offset必须为0(同上)
    • SEEK_END:流的尾部位置,offset可正可负,当offset为正值,将定位到文件尾的后面,在二进制流中不被支持
  • rewind(FILE *stream);//将读写指针设置回指定流的起始位置
  • fgetpos(FILE *stream,fpos_t *position);//获取文件的当前位置存储到position
  • fsetpos(FILE *stream,fpos)t *position);//设置文件的当前位置为position

改变缓冲方式

改变缓冲方式,必须要在当指定流打开但还没有在它上面执行任何其他操作前才能被调用

  • void setbuf(FILE *stream,char *buf);//指定流缓冲区为buf,这个字符数组的长度必须为BUFSIZ(在stdio.h中定义)
  • void setvbuf(FILE *stream,char *buf,int mode,size_t size);//指定流的缓冲区为buf,其大小为size,该大小应该是BUFSIZ的整数倍,mode指明缓冲的方式如下:
    • _IOFBF:完全缓冲流,写满后刷新
    • _IONBF:不缓冲流,直接刷新
    • _IOLBF:行缓冲流,遇到换行符刷新

流错误函数

用于判断流的状态:

  • int feof(FILE *stream);//判断是否处于文件尾
  • int ferror(FILE *stream);//报告流的错误状态
  • int clearerr(FILE *stream);//对指定流的错误标志进行重置

临时文件

创建一个临时文件用于保存数据,当程序结束后该文件会被删除

  • FILE *tmpfile(void);
  • char *tmpnam(char *name);//创建文件名

文件操作函数:

  • int remove(char const *filename);
  • int rename(char const *oldname,char const *newname);