跳到主要内容

1. stdio.h — 标准输入输出

提供标准输入输出操作,按功能分组说明。

头文件说明:本章按功能分组,下面几节的内容不在 <stdio.h> 中,使用时需要包含 <wchar.h>:

  • 1.3、1.4、1.7 中的宽字符函数(wprintf 族、wscanf 族、fgetwc/fputwc 等)以及 fwide。

文件 I/O:本库实现了 fopen/fclose/remove,但裸机上没有文件系统,运行时这些调用会失败;rename 没有实现,使用它会导致链接失败(见 10.2 G3)。

1.1 格式化输出​

int printf(const char *fmt, ...)

格式化输出到 stdout。

  • 输入: fmt 格式字符串, ... 可变参数
  • 输出: int 输出字符数,负值表示错误

int fprintf(FILE *fp, const char *fmt, ...)

格式化输出到文件。

  • 输入: fp 文件指针, fmt 格式串, ... 参数
  • 输出: int 输出字符数

int sprintf(char *buf, const char *fmt, ...)

格式化输出到字符串。

  • 输入: buf 缓冲区, fmt 格式串, ... 参数
  • 输出: int 输出字符数
  • 注意: 不检查缓冲区溢出,已弃用,改用 snprintf

int snprintf(char *buf, size_t n, const char *fmt, ...)

安全格式化到字符串。

  • 输入: buf 缓冲区, n 最大字节数, fmt 格式串, ... 参数
  • 输出: int 应写入字符数(不含\0),超过 n 时被截断

int vprintf(const char *fmt, va_list ap)

printf 的 va_list 版本。

  • 输入: fmt 格式串, ap 参数列表
  • 输出: int 输出字符数

int vfprintf(FILE *fp, const char *fmt, va_list ap)

fprintf 的 va_list 版本。

  • 输入: fp 文件指针, fmt 格式串, ap 参数列表
  • 输出: int 输出字符数

int vsprintf(char *buf, const char *fmt, va_list ap)

sprintf 的 va_list 版本。

  • 输入: buf 缓冲区, fmt 格式串, ap 参数列表
  • 输出: int 输出字符数

int vsnprintf(char *buf, size_t n, const char *fmt, va_list ap)

snprintf 的 va_list 版本。

  • 输入: buf 缓冲区, n 大小, fmt 格式串, ap 参数列表
  • 输出: int 应写入字符数

1.2 格式化输入​

int scanf(const char *fmt, ...)

从 stdin 格式化输入。

  • 输入: fmt 格式字符串, ... 参数(取地址)
  • 输出: int 成功匹配项数,EOF 表示失败

int fscanf(FILE *fp, const char *fmt, ...)

从文件格式化输入。

  • 输入: fp 文件指针, fmt 格式串, ... 参数
  • 输出: int 成功匹配项数

int sscanf(const char *str, const char *fmt, ...)

从字符串格式化输入。

  • 输入: str 字符串, fmt 格式串, ... 参数
  • 输出: int 成功匹配项数

int vscanf(const char *fmt, va_list ap)

scanf 的 va_list 版本。

  • 输入: fmt 格式串, ap 参数列表
  • 输出: int 成功匹配项数

int vfscanf(FILE *fp, const char *fmt, va_list ap)

fscanf 的 va_list 版本。

  • 输入: fp 文件指针, fmt 格式串, ap 参数列表
  • 输出: int 成功匹配项数

int vsscanf(const char *str, const char *fmt, va_list ap)

sscanf 的 va_list 版本。

  • 输入: str 字符串, fmt 格式串, ap 参数列表
  • 输出: int 成功匹配项数

1.3 宽字符格式化输出​

int wprintf(const wchar_t *fmt, ...)

宽字符格式化输出到 stdout。

  • 输入: fmt 宽格式串, ... 参数
  • 输出: int 输出字符数

int fwprintf(FILE *fp, const wchar_t *fmt, ...)

宽字符格式化输出到文件。

  • 输入: fp 文件指针, fmt 宽格式串, ... 参数
  • 输出: int 输出字符数

int swprintf(wchar_t *buf, size_t n, const wchar_t *fmt, ...)

宽字符格式化到字符串。

  • 输入: buf 宽缓冲区, n 大小, fmt 宽格式串, ... 参数
  • 输出: int 应写入字符数

int vwprintf(const wchar_t *fmt, va_list ap)

wprintf 的 va_list 版本。

  • 输入: fmt 宽格式串, ap 参数列表
  • 输出: int 输出字符数

int vfwprintf(FILE *fp, const wchar_t *fmt, va_list ap)

fwprintf 的 va_list 版本。

  • 输入: fp 文件指针, fmt 宽格式串, ap 参数列表
  • 输出: int 输出字符数

int vswprintf(wchar_t *buf, size_t n, const wchar_t *fmt, va_list ap)

swprintf 的 va_list 版本。

  • 输入: buf 宽缓冲区, n 大小, fmt 宽格式串, ap 参数列表
  • 输出: int 应写入字符数

1.4 宽字符格式化输入​

int wscanf(const wchar_t *fmt, ...)

从 stdin 宽字符格式化输入。

  • 输入: fmt 宽格式串, ... 参数
  • 输出: int 成功匹配项数

int fwscanf(FILE *fp, const wchar_t *fmt, ...)

从文件宽字符格式化输入。

  • 输入: fp 文件指针, fmt 宽格式串, ... 参数
  • 输出: int 成功匹配项数

int swscanf(const wchar_t *str, const wchar_t *fmt, ...)

从宽字符串格式化输入。

  • 输入: str 宽字符串, fmt 宽格式串, ... 参数
  • 输出: int 成功匹配项数

int vwscanf(const wchar_t *fmt, va_list ap)

wscanf 的 va_list 版本。

  • 输入: fmt 宽格式串, ap 参数列表
  • 输出: int 成功匹配项数

int vfwscanf(FILE *fp, const wchar_t *fmt, va_list ap)

fwscanf 的 va_list 版本。

  • 输入: fp 文件指针, fmt 宽格式串, ap 参数列表
  • 输出: int 成功匹配项数

int vswscanf(const wchar_t *str, const wchar_t *fmt, va_list ap)

swscanf 的 va_list 版本。

  • 输入: str 宽字符串, fmt 宽格式串, ap 参数列表
  • 输出: int 成功匹配项数

1.5 字符 I/O​

int fgetc(FILE *fp)

从文件读取一个字符。

  • 输入: fp 文件指针
  • 输出: int 读取的字符(转为 unsigned char)或 EOF

int getc(FILE *fp)

fgetc 的宏版本。

  • 输入: fp 文件指针
  • 输出: int 读取的字符或 EOF
  • 注意: 可能多次求值 fp,避免传入含副作用的表达式

int getchar(void)

从 stdin 读取一个字符。

  • 输入: 无
  • 输出: int 读取的字符或 EOF

char* fgets(char *s, int n, FILE *fp)

从文件读取一行。

  • 输入: s 缓冲区, n 最大读取字符数, fp 文件指针
  • 输出: char* s 或 NULL(EOF/错误)
  • 注意: 保留换行符,最多读 n-1 字符,末尾补 \0

char* gets(char *s)

从 stdin 读取一行。

  • 输入: s 缓冲区
  • 输出: char* s 或 NULL
  • 注意: 不检查缓冲区溢出,C11 已移除,极度危险

int fputc(int c, FILE *fp)

向文件写入一个字符。

  • 输入: c 字符, fp 文件指针
  • 输出: int 写入的字符或 EOF

int putc(int c, FILE *fp)

fputc 的宏版本。

  • 输入: c 字符, fp 文件指针
  • 输出: int 写入的字符或 EOF

int putchar(int c)

向 stdout 写入一个字符。

  • 输入: c 字符
  • 输出: int 写入的字符或 EOF

int fputs(const char *s, FILE *fp)

向文件写入字符串(不含换行)

  • 输入: s 字符串, fp 文件指针
  • 输出: int 非负成功,EOF 失败

int puts(const char *s)

向 stdout 写入字符串(自动加换行)

  • 输入: s 字符串
  • 输出: int 非负成功,EOF 失败

int ungetc(int c, FILE *fp) | 【C90 §7.19.7.11】

将一个字符放回输入流。

  • 输入: c 字符(须为 unsigned char 可表示值或 EOF),fp 文件指针
  • 输出: int 成功时返回放回的字符,失败返回 EOF
  • 注意: 至少保证可回推 1 个字符;会清除该流的 EOF 标志。

1.6 二进制 I/O​

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *fp)

从文件读取二进制数据。

  • 输入: ptr 缓冲区, size 元素大小, nmemb 元素数, fp 文件指针
  • 输出: size_t 实际读取元素数

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *fp)

向文件写入二进制数据。

  • 输入: ptr 缓冲区, size 元素大小, nmemb 元素数, fp 文件指针
  • 输出: size_t 实际写入元素数

1.7 宽字符 I/O​

注意:本节偏差:① 宽字符流在交付配置下把 wchar_t 的 4 字节原始表示直灌流,并非标准要求的多字节编码(G4);② fwide 没有"未定向"状态、对已定向流仍会改向,fgetwc 到流尾不置 EOF 标志(G5)。详见 10.2、10.7.1 L9 / L10。

wint_t fgetwc(FILE *fp)

从文件读取一个宽字符。

  • 输入: fp 文件指针
  • 输出: wint_t 宽字符或 WEOF
  • 注意:行为偏差(G5): 读到流尾返回 WEOF,但不置 EOF 标志——feof(fp) 恒为 0。判断宽字符输入结束须直接比较返回值 == WEOF。详见 10.2 G5 / 10.7.1 L10。

wint_t getwchar(void)

从 stdin 读取一个宽字符。

  • 输入: 无
  • 输出: wint_t 宽字符或 WEOF

wchar_t* fgetws(wchar_t *s, int n, FILE *fp)

从文件读取宽字符行。

  • 输入: s 宽缓冲区, n 大小, fp 文件指针
  • 输出: wchar_t* s 或 NULL

wint_t fputwc(wchar_t c, FILE *fp)

向文件写入一个宽字符。

  • 输入: c 宽字符, fp 文件指针
  • 输出: wint_t 宽字符或 WEOF

wint_t putwchar(wchar_t c)

向 stdout 写入一个宽字符。

  • 输入: c 宽字符
  • 输出: wint_t 宽字符或 WEOF

int fputws(const wchar_t *s, FILE *fp)

向文件写入宽字符串。

  • 输入: s 宽字符串, fp 文件指针
  • 输出: int 非负成功,EOF 失败

wint_t ungetwc(wint_t c, FILE *fp)

将宽字符放回输入流。

  • 输入: c 宽字符, fp 文件指针
  • 输出: wint_t 放回的宽字符或 WEOF

int fwide(FILE *fp, int mode)

设置/查询流定向。

  • 输入: fp 文件指针, mode 模式(正=宽字符, 负=字节, 0=仅查询)
  • 输出: int 正=宽字符, 负=字节, 0=未定向
  • 注意:行为偏差(G5): 本库没有"未定向"状态——流初始即视为字节定向,故未定向流上 fwide(fp, 0) 返回 -1 而非 0;且对已定向流调用 fwide(fp, ±1) 会改变其定向(标准要求保持不变)。不要用 fwide 判断流是否已定向,也不要依赖它维持定向。详见 10.2 G5 / 10.7.1 L10。

wint_t getwc(FILE *fp) | 【C99 §7.24.3.1】

从文件读取一个宽字符(fgetwc 的宏版本)。实际头:<wchar.h>。

  • 输入: fp 文件指针
  • 输出: wint_t 宽字符或 WEOF
  • 注意: 实现为 fgetwc 的强别名。

wint_t putwc(wchar_t c, FILE *fp) | 【C99 §7.24.3.3】

向文件写入一个宽字符(fputwc 的宏版本)。实际头:<wchar.h>。

  • 输入: c 宽字符, fp 文件指针
  • 输出: wint_t 宽字符或 WEOF
  • 注意: 实现为 fputwc 的强别名。

1.8 文件定位​

int fseek(FILE *fp, long offset, int whence)

设置文件位置。

  • 输入: fp 文件指针, offset 偏移量, whence 起始位置(SEEK_SET/SEEK_CUR/SEEK_END)
  • 输出: int 0 成功,非零失败

long ftell(FILE *fp)

获取当前文件位置。

  • 输入: fp 文件指针
  • 输出: long 当前位置,-1L 表示错误

void rewind(FILE *fp)

重置文件位置到开头。

  • 输入: fp 文件指针
  • 输出: 无
  • 注意: 同时清除错误标志和 EOF 标志

int fgetpos(FILE *fp, fpos_t *pos)

获取当前文件位置。

  • 输入: fp 文件指针, pos 位置指针
  • 输出: int 0 成功,非零失败

int fsetpos(FILE *fp, const fpos_t *pos)

设置文件位置。

  • 输入: fp 文件指针, pos 位置指针
  • 输出: int 0 成功,非零失败

1.9 缓冲控制​

int fflush(FILE *fp)

刷新输出缓冲区。

  • 输入: fp 文件指针(或 NULL 刷新所有输出流)
  • 输出: int 0 成功,EOF 失败

void setbuf(FILE *fp, char *buf)

设置缓冲区。

  • 输入: fp 文件指针, buf 缓冲区(为 NULL 则关闭缓冲)
  • 输出: 无
  • 注意: 等价于 setvbuf(fp, buf, buf ? _IOFBF : _IONBF, BUFSIZ)

int setvbuf(FILE *fp, char *buf, int mode, size_t size)

设置缓冲区模式。

  • 输入: fp 文件指针, buf 缓冲区, mode 模式, size 大小
  • 输出: int 0 成功,非零失败
  • 注意: mode 为 _IOFBF(全缓冲)/_IOLBF(行缓冲)/_IONBF(无缓冲)

1.10 错误与状态​

int feof(FILE *fp)

检查文件结束标志。

  • 输入: fp 文件指针
  • 输出: int 非零表示已到 EOF

int ferror(FILE *fp)

检查错误标志。

  • 输入: fp 文件指针
  • 输出: int 非零表示有错误

void clearerr(FILE *fp)

清除文件错误和 EOF 标志。

  • 输入: fp 文件指针
  • 输出: 无

void perror(const char *s)

输出错误信息。

  • 输入: s 前缀字符串(可为 NULL)
  • 输出: 无
  • 注意: 输出格式为 "s: 错误描述\n"

1.11 文件操作​

注意:可用性说明 —— 本节的函数在交付库中均可正常链接,但交付配置无文件系统:底层 open/unlink 落到 nosys 桩,故 fopen/freopen/tmpfile/remove 等在运行时返回失败。唯一例外是 rename:本库无实现,使用会导致链接失败(见 10.2 G3)。

FILE* fopen(const char *path, const char *mode)

打开文件。

  • 输入: path 文件路径, mode 打开模式("r"/"w"/"a" 等)
  • 输出: FILE* 文件指针,失败返回 NULL
  • 注意: mode 决定读写权限,如 "r+" 表示读写

int fclose(FILE *fp)

关闭文件。

  • 输入: fp 文件指针
  • 输出: int 0 成功,EOF 失败

FILE* freopen(const char *path, const char *mode, FILE *fp)

重定向流。

  • 输入: path 路径, mode 模式, fp 旧文件指针
  • 输出: FILE* 新文件指针,失败返回 NULL

int remove(const char *path)

删除文件。

  • 输入: path 文件路径
  • 输出: int 0 成功,非零失败

注意:rename 本库未提供 —— 标准函数 int rename(const char *old, const char *new)(C90 §7.9.4.2 / C99 §7.19.4.2)在交付库中无实现,使用它会导致链接失败(undefined symbol: rename)。详见 10.2 G3。


FILE* tmpfile(void)

创建临时文件。

  • 输入: 无
  • 输出: FILE* 临时文件指针,失败返回 NULL
  • 注意: 文件在关闭或程序结束时自动删除

char* tmpnam(char *s)

生成临时文件名。

  • 输入: s 缓冲区(可为 NULL,使用内部静态缓冲区)
  • 输出: char* 临时文件名
  • 注意: 建议改用 tmpfile