C标准库头文件 <stdio.h> 中定义了三个变量类型、一些宏和各种函数来执行输入和输出。
下面是头文件 <stdio.h> 中定义的变量类型:
序号 | 变量 & 描述 |
---|---|
1 | size_t 这是无符号整数类型,它是 sizeof 关键字的结果。 |
2 | FILE 这是一个适合存储文件流信息的对象类型。 |
3 | fpos_t 这是一个适合存储文件中任何位置的对象类型。 |
下面是头文件 stdio.h 中定义的宏:
序号 | 宏 & 描述 |
---|---|
1 | NULL 这个宏是一个空指针常量的值。 |
2 | _IOFBF、_IOLBF 和 _IONBF 这些宏扩展了带有特定值的整型常量表达式,并适用于 setvbuf 函数的第三个参数。 |
3 | BUFSIZ 这个宏是一个整数,该整数代表了 setbuf 函数使用的缓冲区大小。 |
4 | EOFM 这个宏是一个表示已经到达文件结束的负整数。 |
5 | FOPEN_MAX 这个宏是一个整数,该整数代表了系统可以同时打开的文件数量。 |
6 | FILENAME_MAX 这个宏是一个整数,该整数代表了字符数组可以存储的文件名的最大长度。如果实现没有任何限制,则该值应为推荐的最大值。 |
7 | L_tmpnam 这个宏是一个整数,该整数代表了字符数组可以存储的由 tmpnam 函数创建的临时文件名的最大长度。 |
8 | SEEK_CUR、SEEK_END 和 SEEK_SET 这些宏是在These macros are used in the fseek 函数中使用,用于在一个文件中定位不同的位置。 |
9 | TMP_MAX 这个宏是 tmpnam 函数可生成的独特文件名的最大数量。 |
10 | stderr、stdin 和 stdout 这些宏是指向 FILE 类型的指针,分别对应于标准错误、标准输入和标准输出流。 |
下面是头文件 stdio.h 中定义的函数:
序号 | 函数 & 描述 |
---|---|
1 | int fclose(FILE stream) 关闭流 stream。刷新所有的缓冲区。 |
2 | void clearerr(FILE stream) 清除给定流 stream 的文件结束和错误标识符。 |
3 | int feof(FILE stream) 测试给定流 stream 的文件结束标识符。 |
4 | int ferror(FILE stream) 测试给定流 stream 的错误标识符。 |
5 | int fflush(FILE stream) 刷新流 stream 的输出缓冲区。 |
6 | int fgetpos(FILE stream, fpos_t pos) 获取流 stream 的当前文件位置,并把它写入到 pos。 |
7 | FILE fopen(const char filename, const char mode) 使用给定的模式 mode 打开 filename 所指向的文件。 |
8 | size_t fread(void ptr, size_t size, size_t nmemb, FILE stream) 从给定流 stream 读取数据到 ptr 所指向的数组中。 |
9 | FILE freopen(const char filename, const char mode, FILE stream) 把一个新的文件名 filename 与给定的打开的流 stream 关联,同时关闭流中的旧文件。 |
10 | int fseek(FILE stream, long int offset, int whence) 设置流 stream 的文件位置为给定的偏移 offset,参数 offset 意味着从给定的 whence 位置查找的字节数。 |
11 | int fsetpos(FILE stream, const fpos_t pos) 设置给定流 stream 的文件位置为给定的位置。参数 pos 是由函数 fgetpos 给定的位置。 |
12 | long int ftell(FILE stream) 返回给定流 stream 的当前文件位置。 |
13 | size_t fwrite(const void ptr, size_t size, size_t nmemb, FILE stream) 把 ptr 所指向的数组中的数据写入到给定流 stream 中。 |
14 | int remove(const char filename) 删除给定的文件名 filename,以便它不再被访问。 |
15 | int rename(const char old_filename, const char new_filename) 把 old_filename 所指向的文件名改为 new_filename。 |
16 | void rewind(FILE stream) 设置文件位置为给定流 stream 的文件的开头。 |
17 | void setbuf(FILE stream, char buffer) 定义流 stream 应如何缓冲。 |
18 | int setvbuf(FILE stream, char buffer, int mode, size_t size) 另一个定义流 stream 应如何缓冲的函数。 |
19 | FILE tmpfile(void) 以二进制更新模式(wb+)创建临时文件。 |
20 | char tmpnam(char str) 生成并返回一个有效的临时文件名,该文件名之前是不存在的。 |
21 | int fprintf(FILE stream, const char format, ...) 发送格式化输出到流 stream 中。 |
22 | int printf(const char format, ...) 发送格式化输出到标准输出 stdout。 |
23 | int sprintf(char str, const char format, ...) 发送格式化输出到字符串。 |
24 | int vfprintf(FILE stream, const char format, va_list arg) 使用参数列表发送格式化输出到流 stream 中。 |
25 | int vprintf(const char format, va_list arg) 使用参数列表发送格式化输出到标准输出 stdout。 |
26 | int vsprintf(char str, const char format, va_list arg) 使用参数列表发送格式化输出到字符串。 |
27 | int fscanf(FILE stream, const char format, ...) 从流 stream 读取格式化输入。 |
28 | int scanf(const char format, ...) 从标准输入 stdin 读取格式化输入。 |
29 | int sscanf(const char str, const char format, ...) 从字符串读取格式化输入。 |
30 | int fgetc(FILE stream) 从指定的流 stream 获取下一个字符(一个无符号字符),并把位置标识符往前移动。 |
31 | char fgets(char str, int n, FILE stream) 从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。 |
32 | int fputc(int char, FILE stream) 把参数 char 指定的字符(一个无符号字符)写入到指定的流 stream 中,并把位置标识符往前移动。 |
33 | int fputs(const char str, FILE stream) 把字符串写入到指定的流 stream 中,但不包括空字符。 |
34 | int getc(FILE stream) 从指定的流 stream 获取下一个字符(一个无符号字符),并把位置标识符往前移动。 |
35 | int getchar(void) 从标准输入 stdin 获取一个字符(一个无符号字符)。 |
36 | char gets(char str) 从标准输入 stdin 读取一行,并把它存储在 str 所指向的字符串中。当读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。 |
37 | int putc(int char, FILE stream) 把参数 char 指定的字符(一个无符号字符)写入到指定的流 stream 中,并把位置标识符往前移动。 |
38 | int putchar(int char) 把参数 char 指定的字符(一个无符号字符)写入到标准输出 stdout 中。 |
39 | int puts(const char str) 把一个字符串写入到标准输出 stdout,直到空字符,但不包括空字符。换行符会被追加到输出中。 |
40 | int ungetc(int char, FILE stream) 把字符 char(一个无符号字符)推入到指定的流 stream 中,以便它是下一个被读取到的字符。 |
41 | void perror(const char str) 把一个描述性错误消息输出到标准错误 stderr。首先输出字符串 str,后跟一个冒号,然后是一个空格。 |
int scanf(const char *format, ...);
从标准输入 stdin 读取格式化输入。
如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回EOF(-1)。
int sscanf(const char *str, const char *format, ...);
从字符串读取格式化输入。
针对检索数据的format字符串中的每个format说明符,应指定一个附加参数。如果您想要把sscanf操作的结果存储在一个普通的变量中,您应该在标识符前放置引用运算符(&),例如:
int n; sscanf (str,"%d",&n);
如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回EOF(-1)。
int fscanf(FILE *stream, const char *format, ...);
从流stream读取格式化输入。
如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回EOF(-1)。
又称格式化字符串,输入流的format形式为%[*][width][modifiers]type],具体讲解如下:
参数 | 描述 |
---|---|
* | 这是一个可选的星号,表示从流stream中读取数据,但是忽略(跳过)它,即不将它存储在参数中。 |
width | 指定了当前读取操作中可读取的最大字符数。 |
modifiers |
为对应的附加参数所指向的数据指定一个不同于整型、无符号整型或浮点型的大小。 h:短整型(针对d、i和n)或无符号短整型(针对o、u和x) l:长整型(针对d、i和n)或无符号长整型(针对o、u和x),或双精度型(针对e、f和g) L:长双精度型(针对e、f和g) |
type | 一个字符,指定了要被读取的数据类型以及数据读取方式,具体参见下一个表格。 |
类型 | 合格的输入 | 参数的类型 |
---|---|---|
c | 单个字符:读取下一个字符。如果指定了一个不为1的宽度 width,函数会读取width个字符,并通过参数传递,把它们存储在数组中连续位置。在末尾不会追加空字符。 | char |
d | 十进制整数:数字前面的+或-号是可选的。 | int |
e,E,f,g,G | 浮点数:包含了一个小数点、一个可选的前置符号+或-、一个可选的后置字符e或E,以及一个十进制数字。两个有效的实例 -732.103和7.12e4 | float |
o | 八进制整数。 | int |
s | 字符串。这将读取连续字符,直到遇到一个空格字符(空格字符可以是空白、换行和制表符)。 | char |
u | 无符号的十进制整数。 | unsigned int |
x,X | 十六进制整数。 | int * |
int printf(const char *format, ...);
发送格式化输出到标准输出stdout。
如果成功,则返回写入的字符总个数,否则返回一个负数。
int sprintf(char *str, const char *format, ...);
发送格式化输出到 str 所指向的字符串。
如果成功,则返回写入的字符总数,不包括字符串追加在字符串末尾的空字符。如果失败,则返回一个负数。
int fprintf(FILE *stream, const char *format, ...);
发送格式化输出到流stream中。
如果成功,则返回写入的字符总个数,否则返回一个负数。
int vfprintf(FILE *stream, const char *format, va_list arg);
使用参数列表发送格式化输出到流 stream 中。
如果成功,则返回写入的字符总数,否则返回一个负数。
int vsprintf(char *str, const char *format, va_list arg);
使用参数列表发送格式化输出到字符串。
如果成功,则返回写入的字符总数,否则返回一个负数。
int vfprintf(FILE *stream, const char *format, va_list arg);
使用参数列表发送格式化输出到流stream中。
如果成功,则返回写入的字符总数,否则返回一个负数。
输出流以printf函数为基础,有一系列功能各异的输出函数(fprintf、sprintf、snprintf等),它们都在输出时使用了强大的格式化字符串。格式化字符串以一个%开始,以类型字段(d、f、x等)结束,完整格式如下:
%[参数][标志][宽度][.精度][长度]类型
注意:除了%和类型之外均为可选字段。
参数字段为POSIX扩展功能,非C99标准定义。使用 m$ 指定格式化字符串之后的第$m$个参数,从$14开始编号。假如使用了参数字段,则所有的参数必须都至少使用一次,即从 1$ 到 n$ 都必须至少出现一次(其中 n 为格式化字符串之后的参数个数),否则编译时将产生如下警告:
warning: missing $ operand number in format [-Wformat=]
借助参数字段,可以实现参数的多次使用、乱序使用等,而不需要重复书写参数。例如: printf("%2$d %2$#x; %1$d %1$#x",16,17); 将输出 17 0x11; 16 0x10 ,两个参数都使用了两次,且先使用第二个参数(同时也使用了下一节的 # 标志)。
宽度字段指定输出字符的最小长度。长度不足的输出将使用填充字符补齐,填充字符及对齐方式使用上述的 0 标志和 - 标志确定;超长的输出不受影响(当然可使用下文的精度字段限定)。
当指定宽度字段时,可使用确定的整数值静态指定,也可使用 * 号由某个参数动态指定。例如 printf("%0*d", 5, 10); 将输出 00010 。注意:此例不能写成 %*0d 即颠倒了标志字段和宽度字段,否则将产生编译警告:
warning: unknown conversion type character ‘0’ in format [-Wformat=] warning: too many arguments for format [-Wformat-extra-args]
精度字段指定输出字符的最大长度。对浮点型数据来说,精度字段指定了小数点后的最长有效位数;对字符串来说,精度字段指定了输出的最大字符数。
与宽度字段相同,指定精度字段时,也可使用确定的整数值静态确定或 * 号动态确定。为了与宽度字段做区分,精度字段前必须加句点。例如 printf("%.*s", 3, "abcdef"); 将输出 abc 。假如没有句点,将被解析成宽度字段(最小长度)为$3$而精度字段(最大长度)未指定,因此将输出 abcdef 。
另有一些平台特定的非标准长度字符,如 I 、 I32 、 I64 、 q 等,可参考维基百科printf format string词条。
可变宽度对于根据不同层次输出不同的缩进有奇效,例如:
<kernel/resource.c> seq_printf(m, "%*s%0*llx-%0*llx : %s\n", depth * 2, "", width, start, width, end, r->name ? r->name : "<BAD>");
其中的 %*s 表示输出 depth * 2 个空字符,字符个数是深度的两倍;两个 %0*llx 分别将 start 和 end 以十六进制 long long 型输出,最小宽度为 width ,宽度不足则以前导 0 补足。
内核中大量使用了 # 标志配合 x 类型输出十六进制数,随便举一个例子:
<mm/slab.c> seq_printf(m, "%s+%#lx/%#lx", name, offset, size);
其中的两个 %#lx 即分别将 offset 和 size 以十六进制 long 型输出,并自动附加0x前缀。注意:此例中的 + 号不是 + 标志而是原样输出的字符,因为并不出现在 % 与类型字段之间。
另外,内核的 printk 所使用的格式化字符串有一些自定义的格式,可参考内核文档 How to get printk format specifiers right。
(整理自网络)
参考资料:
https://wiki.jikexueyuan.com/project/c/c-standard-library-stdio-h.html
https://blog.lancitou.net/format-string-in-printf/
原文:https://www.cnblogs.com/MinPage/p/14203734.html