一、标准输入输出函数(stdio.h)
1. 字符输入输出函数
(1) getchar()
int getchar(void);
-
功能:从标准输入(stdin)读取一个字符
-
返回值:成功返回读取的字符(转换为unsigned char后提升为int),失败或到达文件末尾返回EOF(-1)
-
特点:
-
无参数
-
通常用于从键盘获取单个字符
-
会缓冲输入,直到用户按下回车
-
-
示例:
int ch; while ((ch = getchar()) != EOF) { putchar(ch); }(2) putchar()
int putchar(int c); -
功能:向标准输出(stdout)写入一个字符
-
参数:c是要输出的字符(转换为unsigned char)
-
返回值:成功返回写入的字符,失败返回EOF
-
特点:
-
比printf效率高
-
只能输出单个字符
-
-
示例:
putchar('A'); // 输出字符A putchar(65); // 同样输出字符A(ASCII码65)
2. 格式化输入输出函数
(1) printf()
int printf(const char *format, ...);
-
功能:格式化输出到标准输出
-
格式说明符:
-
%d/%i:有符号十进制整数
-
%u:无符号十进制整数
-
%o:无符号八进制
-
%x/%X:无符号十六进制
-
%f/%F:浮点数
-
%e/%E:科学计数法
-
%g/%G:自动选择%f或%e
-
%c:字符
-
%s:字符串
-
%p:指针地址
-
%%:百分号本身
-
-
修饰符:
-
宽度:%10d(最小宽度10)
-
精度:%.2f(小数点后2位)
-
左对齐:%-10d
-
填充:%010d(用0填充)
-
-
返回值:成功返回输出的字符数,失败返回负值
-
示例:
printf("Integer: %5d\nFloat: %.2f\nString: %s\n", 123, 3.14159, "hello");(2) scanf()
int scanf(const char *format, ...); -
功能:从标准输入读取格式化输入
-
格式说明符:
-
%d:读取整数
-
%f:读取浮点数
-
%c:读取字符
-
%s:读取字符串(遇到空白字符停止)
-
%[]:扫描字符集合
-
%%:匹配百分号
-
-
修饰符:
-
*:抑制赋值(跳过该输入)
-
宽度:%5s(最多读取5个字符)
-
-
返回值:成功匹配并赋值的输入项数
-
注意事项:
-
必须传递变量地址(&)
-
对%s存在缓冲区溢出风险
-
空白字符(空格、制表符、换行符)会被跳过
-
-
示例:
int age; float height; char name[50]; scanf("%d %f %49s", &age, &height, name);3. 行输入输出函数
(1) gets() (已废弃)
char *gets(char *s); -
问题:无法限制输入长度,极易导致缓冲区溢出
-
替代方案:使用fgets()
(2) fgets()
char *fgets(char *s, int size, FILE *stream);
-
功能:从指定流读取一行
-
参数:
-
s:存储读取数据的缓冲区
-
size:最大读取字符数(包括空字符)
-
stream:文件流(stdin表示标准输入)
-
-
特点:
-
读取直到遇到换行符或EOF
-
保留换行符(如果有)
-
总是添加空字符('\0')
-
比gets()安全
-
-
返回值:成功返回s,失败或到达文件末尾返回NULL
-
示例:
char line[100]; if (fgets(line, sizeof(line), stdin) != NULL) { // 处理读取的行 }(3) puts()
int puts(const char *s); -
功能:向标准输出写入字符串并自动添加换行符
-
参数:s是要输出的字符串(必须以空字符结尾)
-
返回值:成功返回非负值,失败返回EOF
-
特点:
-
比printf简单高效
-
自动添加换行符
-
-
示例:
puts("Hello World"); // 输出"Hello World\n"二、文件输入输出函数
1. 文件打开关闭
(1) fopen()
FILE *fopen(const char *filename, const char *mode); -
功能:打开文件
-
模式:
-
"r":只读(文件必须存在)
-
"w":只写(存在则清空,不存在则创建)
-
"a":追加(存在则追加,不存在则创建)
-
"r+":读写(文件必须存在)
-
"w+":读写(存在则清空,不存在则创建)
-
"a+":读写(存在则追加,不存在则创建)
-
添加"b"表示二进制模式(如"rb")
-
-
返回值:成功返回文件指针,失败返回NULL
-
示例
FILE *fp = fopen("data.txt", "r"); if (fp == NULL) { perror("Error opening file"); exit(EXIT_FAILURE); }(2) fclose()
-
功能:关闭文件
-
返回值:成功返回0,失败返回EOF
-
注意事项:
-
必须关闭所有打开的文件
-
程序结束时未关闭的文件可能丢失数据
-
-
示例:
if (fclose(fp) == EOF) { perror("Error closing file"); }2. 文件读写函数
(1) fprintf()
int fprintf(FILE *stream, const char *format, ...); -
功能:格式化写入文件
-
与printf类似,但指定了输出流
-
示例:
fprintf(fp, "Name: %s, Age: %d\n", name, age);(2) fscanf()
int fscanf(FILE *stream, const char *format, ...); -
功能:从文件格式化读取
-
与scanf类似,但指定了输入流
-
示例:
fscanf(fp, "%s %d", name, &age);(3) fgetc()
int fgetc(FILE *stream); -
功能:从文件读取一个字符
-
返回值:成功返回读取的字符(转换为unsigned char后提升为int),失败或EOF返回EOF
-
示例:
int ch; while ((ch = fgetc(fp)) != EOF) { putchar(ch); }(4) fputc()
int fputc(int c, FILE *stream); -
功能:向文件写入一个字符
-
参数:c是要写入的字符(转换为unsigned char)
-
返回值:成功返回写入的字符,失败返回EOF
-
示例:
fputc('A', fp);(5) fgets() (文件版本)
-
与标准输入版本相同,但可以指定文件流
-
示例:
char line[256]; while (fgets(line, sizeof(line), fp) != NULL) { printf("%s", line); }(6) fputs()
int fputs(const char *s, FILE *stream); -
功能:向文件写入字符串(不自动添加换行符)
-
参数:s是要写入的字符串(必须以空字符结尾)
-
返回值:成功返回非负值,失败返回EOF
-
示例:
fputs("Hello File", fp);3. 二进制文件读写
(1) fread()
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); -
功能:从文件读取二进制数据
-
参数:
-
ptr:存储读取数据的内存指针
-
size:每个数据项的字节大小
-
nmemb:要读取的数据项数量
-
stream:文件流
-
-
返回值:成功读取的数据项数量(可能小于nmemb)
-
示例:
struct Student { char name[50]; int age; } s; size_t n = fread(&s, sizeof(struct Student), 1, fp); if (n != 1) { // 处理错误 }(2) fwrite()
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); -
功能:向文件写入二进制数据
-
参数:与fread相同
-
返回值:成功写入的数据项数量
-
示例:
struct Student s = {"Alice", 20}; fwrite(&s, sizeof(struct Student), 1, fp);4. 文件定位函数
(1) fseek()
int fseek(FILE *stream, long offset, int whence); -
功能:设置文件位置指示器
-
参数:
-
offset:偏移量
-
whence:
-
SEEK_SET:文件开头
-
SEEK_CUR:当前位置
-
SEEK_END:文件末尾
-
-
-
返回值:成功返回0,失败返回非0
-
示例:
fseek(fp, 0, SEEK_SET); // 定位到文件开头 fseek(fp, -10, SEEK_END); // 定位到文件末尾前10字节(2) ftell()
long ftell(FILE *stream); -
功能:获取当前文件位置
-
返回值:当前位置(距文件开头的字节数),失败返回-1L
-
示例:
long pos = ftell(fp);(3) rewind()
void rewind(FILE *stream); -
功能:将文件位置重置到开头
-
相当于fseek(fp, 0, SEEK_SET)
-
示例:
rewind(fp);三、错误处理函数
1. perror()
void perror(const char *s); -
功能:打印最近一次系统错误的描述
-
参数:s是自定义的前缀信息
-
示例:
FILE *fp = fopen("nonexist.txt", "r"); if (fp == NULL) { perror("Error opening file"); // 输出: Error opening file: No such file or directory }
2. feof()
int feof(FILE *stream);
-
功能:检测文件结束标志
-
返回值:如果设置了文件结束标志返回非0,否则返回0
-
注意事项:
-
应该在读取操作失败后检查
-
不能单独用于控制循环
-
-
示例:
while (1) { int ch = fgetc(fp); if (feof(fp)) break; // 处理字符 }3. ferror()
int ferror(FILE *stream); -
功能:检测文件错误标志
-
返回值:如果设置了错误标志返回非0,否则返回0
-
示例:
if (ferror(fp)) { perror("File error occurred"); }四、缓冲区控制函数
1. fflush()
int fflush(FILE *stream); -
功能:刷新输出缓冲区
-
参数:
-
输出流:强制写入缓冲数据
-
输入流:行为由实现定义
-
NULL:刷新所有输出流
-
-
返回值:成功返回0,失败返回EOF
-
示例:
printf("Please wait..."); fflush(stdout); // 立即显示,不等换行符2. setbuf()/setvbuf()
void setbuf(FILE *stream, char *buf); int setvbuf(FILE *stream, char *buf, int mode, size_t size); -
功能:控制文件缓冲
-
模式:
-
_IOFBF:全缓冲
-
_IOLBF:行缓冲
-
_IONBF:无缓冲
-
-
示例:
char buf[BUFSIZ]; setvbuf(fp, buf, _IOFBF, BUFSIZ);五、其他实用函数
1. sscanf()/sprintf()
int sscanf(const char *str, const char *format, ...); int sprintf(char *str, const char *format, ...); -
功能:从字符串格式化输入/输出
-
注意事项:
-
sprintf()存在缓冲区溢出风险,建议使用snprintf()
-
-
示例:
char str[100]; int n = sprintf(str, "Value: %d", 42); // str = "Value: 42" int val; sscanf("123 456", "%d", &val); // val = 1232. snprintf()
int snprintf(char *str, size_t size, const char *format, ...); -
功能:安全版本的sprintf()
-
参数:size指定缓冲区大小
-
返回值:如果缓冲区足够大,返回将要写入的字符数(不包括空字符)
-
示例:
char buf[20]; int n = snprintf(buf, sizeof(buf), "Number: %d", 12345); // n = 12(实际需要13字节,包括空字符) // buf = "Number: 12345"(截断到19字符+空字符)六、最佳实践
-
输入安全:
-
避免使用gets(),总是使用fgets()
-
使用fgets()+sscanf()代替scanf()
-
检查所有输入函数的返回值
-
-
输出安全:
-
使用snprintf()代替sprintf()
-
检查输出是否被截断
-
-
文件操作:
-
总是检查fopen()返回值
-
确保所有打开的文件都被关闭
-
使用二进制模式处理非文本数据
-
-
错误处理:
-
检查所有I/O操作的返回值
-
使用perror()或strerror()报告错误
-
适当处理EOF和错误条件
-
-
性能考虑:
-
减少小规模I/O操作
-
考虑使用缓冲
-
批量读写数据
-


1988

被折叠的 条评论
为什么被折叠?



