目录
1.什么是标准I/O
标准 I/O 库是一个 C 语言库,提供了一组函数和数据结构,用于进行标准输入(stdin)、标准输出(stdout)和标准错误(stderr)的操作,以及对文件进行 I/O 操作。这个库通常被称为 <stdio.h>
,它提供了一种高级抽象的接口,使得程序员可以方便地进行输入和输出操作,而无需关心底层的系统调用和文件描述符
2.标准I/O库函数
在启动程序时,有3个文件流是自动打开的。它们是stain、stdout和stderr。它们都是在staio.h头文件里定义的,分别代表着标准输入、标准输出和标准错误输出,与底层文件描述符0、1和2相对应。
2.1 fopen,fclose函数
FILE *fopen(const char *filename, const char *mode);
- 参数:
filename
是文件名,mode
是打开文件的模式(例如 "r" 表示只读,"w" 表示只写)。 - 返回值:返回指向文件的指针,如果打开文件失败,则返回 NULL。
- 功能:打开一个文件,并返回一个文件指针,后续可以使用该文件指针进行读写操作。
打开模式
- "r"或"rb":以只读方式打开。
- "w"或"wb":以写方式打开,并把文件长度截短为零。
- "a"或"ab":以写方式打开,新内容追加在文件尾。
- "r+"或"rb+"或"r+b":以更新方式打开(读和写)。
- "w+"或"wb+"或"w+b":以更新方式打开,并把文件长度截短为零。
- "a+"或"ab+"或"a+b":以更新方式打开,新内容追加在文件尾。
int fclose(FILE *stream);
- 参数:
stream
是指向要关闭的文件的指针。 - 返回值:成功关闭文件返回 0,如果发生错误则返回 EOF。
- 功能:关闭一个打开的文件,并释放与该文件相关的资源。
2.2 fread ,fwrite函数
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
- 参数:
ptr
是要读取数据的缓冲区指针,size
是每个数据项的大小,nmemb
是要读取的数据项数目,stream
是指向要读取的文件的指针。 - 返回值:返回实际读取的数据项数目,如果发生错误或到达文件尾部,则返回值可能小于
nmemb
。 - 功能:从指定文件中读取数据到指定的缓冲区中。
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
- 参数:
ptr
是要写入的数据的缓冲区指针,size
是每个数据项的大小,nmemb
是要写入的数据项数目,stream
是指向要写入的文件的指针。 - 返回值:返回实际写入的数据项数目,如果发生错误,则返回值可能小于
nmemb
。 - 功能:将指定缓冲区中的数据写入到指定文件中。
2.3 fflush函数
int fflush(FILE *stream);
- 参数:
stream
是指向要刷新的流的指针。如果为 NULL,则刷新所有输出流。 - 返回值:如果成功,则返回 0;如果出现错误,则返回 EOF。
- 功能:刷新输出流的缓冲区,将缓冲区中的数据立即写入到文件中。
2.4 fseek函数
int fseek(FILE *stream, long int offset, int whence);
- 参数:
stream
是指向要设置位置的文件的指针,offset
是相对于whence
的偏移量,whence
是指定偏移量的基准位置(SEEK_SET
表示文件开头,SEEK_CUR
表示当前位置,SEEK_END
表示文件末尾)。 - 返回值:如果成功,则返回 0;如果出现错误,则返回非 0 值。
- 功能:将文件的位置指针设置到指定位置。
2.5 fgetc,getc,getchar函数
int fgetc(FILE *stream);
- 参数:
stream
是指向要读取字符的文件的指针。 - 返回值:返回读取的字符,如果到达文件末尾或者发生错误,则返回 EOF。
- 功能:从指定文件中读取一个字符。
int getc(FILE *stream);
- 参数:
stream
是指向要读取字符的文件的指针。 - 返回值:返回读取的字符,如果到达文件末尾或者发生错误,则返回 EOF。
- 功能:从指定文件中读取一个字符。
int getchar(void);
- 参数:无。
- 返回值:返回读取的字符,如果到达文件末尾或者发生错误,则返回 EOF。
- 功能:从标准输入流 stdin 中读取一个字符。
2.6 fputc,putc,putchar函数
int fputc(int c, FILE *stream);
- 参数:
c
是要写入的字符,stream
是指向要写入字符的文件的指针。 - 返回值:如果成功,则返回写入的字符
c
;如果出现错误,则返回 EOF。 - 功能:将一个字符写入到指定文件中。
int putc(int c, FILE *stream);
- 参数:
c
是要写入的字符,stream
是指向要写入字符的文件的指针。 - 返回值:如果成功,则返回写入的字符
c
;如果出现错误,则返回 EOF。 - 功能:将一个字符写入到指定文件中。
int putchar(int c);
- 参数:
c
是要写入的字符。 - 返回值:如果成功,则返回写入的字符
c
;如果出现错误,则返回 EOF。 - 功能:将一个字符写入到标准输出流 stdout 中。
2.7 fgets,gets函数
char *fgets(char *s, int n, FILE *stream);
- 参数:
s
是指向用于存储读取的字符串的缓冲区的指针,n
是要读取的最大字符数,stream
是指向要读取的文件的指针。 - 返回值:如果成功,则返回
s
;如果到达文件末尾或者发生错误,则返回 NULL。 - 功能:从指定文件中读取一行文本,包括换行符,然后将其存储到指定的缓冲区中。
char *gets(char *s);
- 参数:
s
:是一个指向字符数组的指针,用于存储读取的字符串。这个字符数组必须足够大,以容纳输入的字符串,否则可能会发生缓冲区溢出。 - 返回值:如果成功读取一行字符串,则返回指向字符串的指针,即返回值为
s
;如果发生错误或者到达文件末尾,则返回 NULL。 - 功能:从标准输入流 stdin 中读取一行字符串,并将其存储到指定的字符数组中。
2.8 printf,fprintf,sprintf函数
int printf(const char *format, ...);
- 参数:
format
:格式字符串,包含了要输出的文本以及指示如何格式化变量的控制字符。...
:可变数量的参数,与格式字符串中的格式控制符匹配。
- 返回值:返回输出的字符数(不包括字符串末尾的 null 字符),如果发生错误则返回负值。
- 功能:将格式化的数据输出到标准输出设备(通常是终端)。
int fprintf(FILE *stream, const char *format, ...);
- 参数:
stream
:文件指针,指向要写入的文件。format
:格式字符串,包含了要输出的文本以及指示如何格式化变量的控制字符。...
:可变数量的参数,与格式字符串中的格式控制符匹配。
- 返回值:返回输出的字符数(不包括字符串末尾的 null 字符),如果发生错误则返回负值。
- 功能:将格式化的数据输出到指定文件流中。
int sprintf(char *str, const char *format, ...);
- 参数:
str
:目标字符串的指针,用于存储格式化后的数据。format
:格式字符串,包含了要输出的文本以及指示如何格式化变量的控制字符。...
:可变数量的参数,与格式字符串中的格式控制符匹配。
- 返回值:返回写入到字符串中的字符数(不包括字符串末尾的 null 字符),如果发生错误则返回负值。
- 功能:将格式化的数据写入到字符串中,而不是输出到文件或标准输出。
2.9 scanf,fscanf,sscanf函数
int scanf(const char *format, ...)
- 参数:
format
:格式字符串,包含了指示如何读取输入数据的格式控制符。...
:可变数量的参数,用于接收读取的数据,参数的类型和数量要与格式字符串中的格式控制符匹配。
- 返回值:返回成功读取并赋值的参数数目,如果没有成功匹配到任何参数,则返回 0。如果发生错误或者到达文件结束位置,则返回 EOF。
- 功能:从标准输入流(通常是键盘)中读取格式化的数据。
使用 scanf
函数时,需要注意以下几点:
-
格式字符串:
scanf
函数的第一个参数是格式字符串,用于指定输入的格式。在格式字符串中,可以包含转换说明符(例如%d
、%c
、%s
等)以及任何需要匹配的字符(例如空格、逗号等)。 -
输入变量:
scanf
函数的后续参数是要接收输入值的变量的地址。这些变量必须是已经声明过的,并且类型要与对应的转换说明符相匹配。 -
空白字符:在格式字符串中,空白字符(空格、制表符、换行符等)通常用来分隔输入项。空白字符会在
scanf
函数执行时自动跳过。 -
输入缓冲区:
scanf
函数从标准输入中读取字符时,会根据格式字符串中的转换说明符逐个读取字符,直到匹配整个格式字符串或遇到无法匹配的字符为止。输入的字符会存储在输入缓冲区中,直到被scanf
函数读取完毕。 -
错误处理:
scanf
函数返回成功读取并匹配的输入项数量。如果成功,返回值将是非负数,如果发生错误或到达输入流的末尾,返回值将是 EOF。因此,在使用scanf
函数后,应该检查返回值以确保输入成功。 -
输入时的空白字符:
scanf
函数在读取非字符串数据时会忽略输入项之间的空白字符。但是在读取字符串时,输入项之间的空白字符会被视为字符串的一部分。因此,在读取字符串之前,应该确保输入缓冲区中没有残留的空白字符,可以在格式字符串中使用空白字符(如空格或换行符)来跳过这些空白字符。
int fscanf(FILE *stream, const char *format, ...);
- 参数:
stream
:文件指针,指向要读取的文件。format
:格式字符串,包含了指示如何读取输入数据的格式控制符。...
:可变数量的参数,用于接收读取的数据,参数的类型和数量要与格式字符串中的格式控制符匹配。
- 返回值:返回成功读取并赋值的参数数目,如果没有成功匹配到任何参数,则返回 0。如果发生错误或者到达文件结束位置,则返回 EOF。
- 功能:从指定文件流中读取格式化的数据。
使用 fscanf
函数时,需要注意以下几点:
-
文件指针:
fscanf
函数的第一个参数是一个指向已打开文件的指针。这个文件指针必须是通过fopen
或类似函数打开的,且必须处于可读取状态。 -
格式字符串:
fscanf
函数的第二个参数是格式字符串,用于指定从文件中读取的格式。格式字符串中可以包含转换说明符(例如%d
、%c
、%s
等)以及任何需要匹配的字符。 -
输入变量:
fscanf
函数的后续参数是要接收从文件中读取到的值的变量的地址。这些变量必须是已经声明过的,并且类型要与对应的转换说明符相匹配。 -
空白字符:与
scanf
函数类似,fscanf
函数在读取非字符串数据时会忽略输入项之间的空白字符。但是在读取字符串时,输入项之间的空白字符会被视为字符串的一部分。因此,在读取字符串之前,应该确保文件指针处于正确的位置,以避免读取到意外的空白字符。 -
错误处理:
fscanf
函数返回成功读取并匹配的输入项数量。如果成功,返回值将是非负数,如果发生错误或到达文件的末尾,返回值将是 EOF。因此,在使用fscanf
函数后,应该检查返回值以确保读取成功。 -
字符串长度:当使用
%s
转换说明符读取字符串时,fscanf
函数会根据空白字符(如空格、制表符、换行符等)来确定字符串的结束位置。因此,在读取字符串时,应该确保字符串的长度不会超过目标变量的大小,以避免缓冲区溢出的情况。
int sscanf(const char *str, const char *format, ...);
- 参数:
str
:要读取的字符串。format
:格式字符串,包含了指示如何读取输入数据的格式控制符。...
:可变数量的参数,用于接收读取的数据,参数的类型和数量要与格式字符串中的格式控制符匹配。
- 返回值:返回成功读取并赋值的参数数目,如果没有成功匹配到任何参数,则返回 0。如果发生错误,则返回 EOF。
- 功能:从指定的字符串中读取格式化的数据。
demo
#include <stdio.h>
int main() {
char write[] = "Hello world";
FILE* f = fopen("test.txt", "w+");
fwrite(write, sizeof(char), sizeof(write) - 1, f); // 写入数据到文件
printf("Write data:%s\n", write); // 输出写入的数据到控制台
char readbuf[1024];
fseek(f, 0, SEEK_SET);
size_t num = fread(readbuf, 1, sizeof(readbuf) - 1, f); // 从文件读取数据
if (num == 0)
printf("Error reading from file.\n");
else
readbuf[num] = '\0';
printf("Read data:%s\n", readbuf); // 输出读取的数据到控制台
fseek(f, 0, SEEK_SET);
int retc = fgetc(f); // 从文件读取一个字符
if (retc == EOF)
printf("End of file.\n");
else
printf("Read char:%c from fgetc\n", (char)retc);
int retc2 = getc(f); // 从文件读取一个字符
if (retc2 == EOF)
printf("End of file.\n");
else
printf("Read char:%c from getc\n", (char)retc2);
printf("Echo(please echo a char.):");
char retc3 = getchar(); // 从标准输入读取一个字符
printf("Read char:%c from getchar\n", retc3);
int n;
char c;
printf("please echo an int and a char:"); // 提示用户输入一个整数和一个字符
scanf("%d %c", &n, &c); // 从标准输入读取一个整数和一个字符
printf("Read data:%d %c from scanf\n", n, c); // 输出读取的整数和字符到控制台
char c2;
fscanf(f, " %c", &c2); // 从文件读取一个字符
printf("Read data:%c from fscanf\n", c2);
const char *str = "Shenzhen";
char arr[128];
sscanf(str, "%s", arr); // 从字符串中读取数据
printf("Read data:%s from sscanf\n", arr);
fclose(f);
}