C语言标准I/O

C语言标准io

    • 流和缓冲区
    • 文件指针
    • fopen打开流
    • fclose关闭流
    • 字符I/O
    • 行I/O
    • 格式化的行I/O
      • scanf
      • printf
    • 二进制I/O
    • 定位函数
    • 流错误函数
    • 刷新函数
    • 删除文件和文件重命名

流和缓冲区

  • 流是C语言对I/O操作的一种抽象,在C语言的I/O操作只是从程序移进或移出字节,这便是字节流。
  • C程序中大多数流是全缓冲的,即写入数据时,程序先把数据放入缓存(buffer),等到缓存满了,再把里面的数据会一次性刷新(flush)到设备或磁盘文件。这时,缓存区就空了,程序再把新的数据放入缓存,重复整个过程。
  • 程序运行时系统至少提供3个流:
    设备 文件指针(FILE*)
    标准输入(键盘) stdin
    标准输出(屏幕) stdout
    标准出错(屏幕) stderr

文件指针

  • FILE指针:每个被使用的文件都在内存中开辟出一个区域,用来存放文件的相关信息,这些信息是保存在一个名为FILE的结构体中,其定义在头文件stdio.h中。
  • C语言标准io中通常用该结构体的指针 FILE* 作为句柄操作要处理的流。

fopen打开流

#include 
FILE *fopen(const char *pathname, const char *mode);
  • 参数pathname为文件名
  • 参数mode为打开文件的模式:
    • r:读模式,只用来读取数据。如果文件不存在,返回 NULL 指针。
    • w:写模式,只用来写入数据。如果文件存在,文件长度会被截为0,然后再写入;如果文件不存在,则创建该文件。
    • a:写模式,只用来在文件尾部追加数据。如果文件不存在,则创建该文件。
    • r+:读写模式。如果文件存在,指针指向文件开始处,可以在文件头部添加数据。如果文件不存在,返回 NULL 指针。
    • w+:读写模式。如果文件存在,文件长度会被截为0,然后再写入数据。这种模式实际上读不到数据,反而会擦掉数据。如果文件不存在,则创建该文件。
    • a+:读写模式。如果文件存在,指针指向文件结尾,可以在现有文件末尾添加内容。如果文件不存在,则创建该文件。
  • 成功打开文件以后,返回一个 FILE 指针代表一个新创建的流;否则返回NULL

fclose关闭流

#include 
int fclose(FILE *stream);
  • stream为要关闭的流,若其为输出流,则会刷新缓冲区。
  • 如果成功关闭文件,函数返回整数0;如果操作失败(比如磁盘已满,或者出现 I/O 错误),则返回EOF(通常是-1)。

字符I/O

  • 字符输入

    #include 
    
    int fgetc(FILE *stream);
    
    int getc(FILE *stream);
    
    int getchar(void);
    
    • fgetc和getc用于从文件读取一个字符,getc一般用宏来实现,而fgetc用函数实现。而getchar只从stdin读取。
    • 函数返回读到的字符,但是它们的返回值类型却不是char,而是int,这是因为读取失败或读取到文件尾的情况下,它们会返回 EOF
  • 字符输出

    #include 
    
    int fputc(int c, FILE *stream);
    
    int putc(int c, FILE *stream);
    
    int putchar(int c);
    
    • fputc和putc用于写入一个字符c到流stream,putc一般用宏来实现,而fputc用函数实现。而putchar只从stdout读取。
    • 函数返回成功写入到流的字符,写入失败则会返回 EOF
  • 撤销字符I/O

    #include 
    int ungetc(int c, FILE *stream);
    
    • ungetc是将从输入流读到的字符退回到该流,下一次读数据时该字符便不会丢失。
    • 每个流都允许至少退回一个字符。

行I/O

#include 
char *fgets(char *s, int size, FILE *stream);
char *gets(char *s);

int fputs(const char *s, FILE *stream);
int puts(const char *s);
  • fgets用于从文件流stream中读取指定长度的字符串储存在s,读取 size - 1 个字符后或者遇到换行符与文件结尾,就会停止读取,然后在已经读取的内容末尾添加一个空字符\0。如果s够大,会将换行符 \n 存储进读取的数据末尾再添加空字符\0到s。读取成功时,fgets的返回值是它的第一个参数,即指向字符串的指针,否则(比如当文件读到末尾时)返回空指针 NULL。
  • fputs函数用于向文件流stream写入字符串s,它不会在字符串末尾添加换行符。fputs出错时返回EOF,否则返回一个非负值。
  • gets和puts向标准输入和标准输出上读取和写入一行内容,gets与fgets不同的是不会在s后添加换行符,而puts会在s后添加换行符到标准输出。值得一提的是gets并不检查字符数组的长度,多出的字符可能写到字符数组后面产生错误,使用gets时要谨慎!

格式化的行I/O

scanf

#include 

int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *str, const char *format, ...);
  • scanf、fscanf和sscanf分别以标准输入、流和字符串作为输入源根据format字符串的格式将处理后的数据逐个保存在参数列表对应的变量(指针传递)中。
  • 这些函数处理format时,会自动过滤空白字符,包括空格、制表符、换行符等。
  • 返回值是一个整数,表示成功读取的变量个数。如果读取到文件结尾,则返回常量 EOF。
  • 一些格式码:
    格式 含义
    %c 一个字符
    %d或%i 一个十进制数
    %f或%e或%g 一个浮点数
    %u 一个无符号十进制数
    %o 一个无符号八进制数
    %x 一个无符号十六进制数
    %n scanf函数已读的字符数量
    %% %号
    %*d 跳过一个十进制数
    %宽度d 指定宽度个十进制数,数据宽度不够左面补空格
    %[a-z] 匹配a到z中任意字符(尽可能多的匹配)
    %[aBc] 匹配a、B、c中一员,贪婪性
    %[^a] 匹配非a的任意字符,贪婪性
    %[^a-z] 表示读取除a-z以外的所有字符

printf

#include 

int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int sprintf(char *str, const char *format, ...);
0nt snprintf(char *str, size_t size, const char *format, ...);
  • sprintf、fprintf和sprintf将处理后的格式化字符串分别写入到标准输出、流和字符串。
  • 返回值是一个整数,表示输出的字符数量
  • 一些格式码:
    格式 含义
    %c 一个字符
    %d或%i 一个十进制数
    %f 一个浮点数
    %e 一个浮点数,科学计数法表示
    %g 一个6个有效数字的浮点数。整数部分超过6位为科学计数法表示
    %u 一个无符号十进制数
    %o 一个无符号八进制数
    %x 一个无符号十六进制数
    %n scanf函数已读的字符数量
    %% %号
    %*d 跳过一个十进制数
    %宽度d 输出指定宽度个十进制数,数据宽度不够左面补空格
    %宽度.精度f 输出指定宽度并确定小数点后位数的浮点数,数据宽度不够左面补空格

二进制I/O

#include 

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

size_t fwrite(const void *ptr, size_t size, size_t nmemb,
                     FILE *stream);
  • fread和fwrite用于读取和写入二进制数据。
  • ptr为储存数据的一段连续缓冲区的地址,size为缓冲区中每个元素的字节数,nmemb是元素的数目,stream即要读取或写入的流。
  • 正常情况下,返回值为第三个参数nmemb(非字节数),但如果出现读取错误或读到文件结尾,该返回值就会比请求的nmemb小。

定位函数

#include 

int fseek(FILE *stream, long offset, int whence);

long ftell(FILE *stream);

void rewind(FILE *stream);

int fgetpos(FILE *stream, fpos_t *pos);

int fsetpos(FILE *stream, const fpos_t *pos);
  • ftell返回流当前的位置,即从文件开头到当前的偏移量,发生错误会返回-1L。
  • fseek用来改变流当前相对于文件的位置。stream是打开的流,whence用来确定计算起点,它的值是以下三个宏:SEEK_SET(文件开始处)、SEEK_CUR(当前位置)、SEEK_END(文件末尾)。offset为相对whence的字节数,可取正、负和0.。调用成功返回0。
  • rewind函数可以让读/写指针回到流的起始位置,相当于fseek(fp, 0L, seek_set),且会清除当前流的错误提升标志。
  • 由于long类型的大小有限,fgetpos和fsetpos可用于替代ftell和fseek,他们用fops_t类型来储存流的当前位置,fgetpos接收fops_t指针保存当前位置,fsetpos把流设置在pos储存的位置上。执行成功都会返回0.

流错误函数

#include 

void clearerr(FILE *stream);

int feof(FILE *stream);

int ferror(FILE *stream);

  • 所有的标准I/O操作函数如果执行失败,都会在文件指针里面记录错误状态。
  • 如果前面的操作出现错误,ferror返回真(非0值)),否则返回0。
  • clearerr函数用来重置流的错误标志。
  • feof函数用于判断流当前是否处于文件结尾,是则返回真(非0值),可以通过fseek、rewind、fsetpos函数清除这个函数的状态;否则返回0。

刷新函数

#include 

int fflush(FILE *stream);

  • fflush强制将一个输出流缓冲区的数据进行物理写入。
  • 如果不需要保存缓存区内容,则可以传入空指针 NULL。
  • 如果清空成功,fflush返回0,否则返回 EOF。

删除文件和文件重命名

#include 

int remove(const char *pathname);

int rename(const char *oldpath, const char *newpath);
  • remove函数用于删除指定文件,如果删除成功,remove()返回0,否则返回非零值。如果该文件被打开,则该函数行为未知。
  • rename函数用于文件重命名,也用于移动文件。第一个参数是现在的文件名,第二个参数是新的文件名。如果改名成功,rename返回0,否则返回非零值。如果newpath已存在,则该函数行为未知。

你可能感兴趣的:(Linux系统编程,C语言,c语言,开发语言)