设为首页 加入收藏

TOP

C/C++标准输入输出函数终极最全解析(不全捶我)(一)
2023-07-23 13:35:28 】 浏览:73
Tags:C/C 终极最 全解析 全捶我

C/C++的一众输入输出函数的区别常常搞得人晕头转向,二者之中又以输入函数更加令人头疼。本文尝试整理C/C++的各种输入输出函数。

由于输入涉及空格、换行符的读取、忽略等问题,因此输入比输出更麻烦。所以本文将以输入为主线,对应的输出用法是类似的。

水平有限,如有疏漏,欢迎提出。

标准输入流

C 标准输入

C语言使用标准输入输出函数,需要包含头文件<stdio.h>。而在 C++ 中,只要包含头文件<iostream>,就完全可以使用这些 C 中的输入输出函数。

标准输入流及对缓冲区的理解

stdin是一个文件描述符(Linux)或句柄(Windows),它在 C 程序启动时就被默认分配好。在 Linux 中一切皆文件,stdin也相当于一个可读文件,它对应着键盘设备的输入。因为它不断地被输入,又不断地被读取,像流水一样,因此通常称作输入流

stdin是一种行缓冲I/O。当在键盘上键入字符时,它们首先被存放在键盘设备自身的缓存中(属于键盘硬件设备的一部分)。只有输入换行符时,操作系统才会进行同步,将键盘缓存中的数据读入到stdin的输入缓冲区(存在于内存中)。所有从stdin读取数据的输入流,都是从内存中的输入缓冲区读入数据。当输入缓冲区为空时,函数将被阻塞。

若无特殊说明,以下所有的“缓冲区”均是指内存中的stdin输入缓冲区。用户程序中自定义的buffer数组、str数组等,将称作“数组”、“变量”,以免产生混淆。

scanf()

按照特定格式从stdin读取输入。

用法示例:

char str[100];
int a;
scanf("%s %d", str, &a);    // 注意,传入的一定是变量的地址

对空白字符的处理:

  1. 缓冲区开头:丢弃空白字符(包括空格、Tab、换行符),直到第一个非空白字符才认为是第一个数据的开始。
  2. 缓冲区中间:开始读取第一个数据后,一旦遇到空白字符(非换行符), 就认为读取完毕一次。遇到的空白字符残留在缓冲区,直到下一次被读取或刷新。例如输入字符串this is test,则会被认为是3个字符串。
  3. 缓冲区末尾:按下回车键时,换行符\n残留在缓冲区。换行符之前的空格可以认为是中间的空白字符,处理同上。

注意,格式控制符只会读取正确类型的变量。如果输入格式不正确,比如在%d处输入了一个字符a,则会使读取中断,即后续不读取任何变量。

格式控制符说明:

类型 类型输入 参数的类型
%d 十进制整数 int *
%u 无符号十进制整数 unsigned int *
%o 八进制整数 int *
%x 十六进制整数 int *
%f、%e、%g 浮点数 float *
%lf、%le、%lg 双精度浮点数 double *
%c 单个字符(含空白字符) char *
%s 字符串 char *
%% 读 % 符号

注意,%c是一个比较特殊的格式符号,它将会读取所有空白字符,包括缓冲区开头的空格、Tab、换行符,使用时要特别注意。

scanf()的读取也没有边界,所以并不安全。C11 标准提供了安全输入scanf_s()

scanf()对应的输出函数是printf()

gets() - 不建议

按下回车键时,从stdin读取一行。

用法示例:

char str[100];
gets(str);

对空白字符的处理:

  1. 所有空格、Tab等空白字符均被读取,不忽略。
  2. 按下回车键时,缓冲区末尾的换行符被丢弃,字符串末尾没有换行符\n,缓冲区也没有残留的换行符\n

注意,gets()不能指定读取上限,因此容易发生数组边界溢出,造成内存不安全。C11 使用了gets_s()代替gets(),但有时编译器未必支持,因此总体来说不建议使用gets()函数来读取输入。

gets()对应的输出函数是puts()

fgets()

从指定输入流读取一行,输入可以是stdin,也可以是文件流,使用时需要显式指定。

读取文件流示例:

char str[100];
memset(str, 0, sizeof(str));
int i = 1;
 
FILE *fp = fopen("...test.txt", "r");
if (fp == NULL) {
    printf("File open Error!\n");
    exit(1);
}
 
while (fgets(str, sizeof(str), fp) != NULL)
    printf("line%d [len %d]: %s", i++, strlen(str), str);
 
fclose(fp);

读取stdin示例:

char str[100];
memset(str, 0, sizeof(str));
int i = 1;
while (fgets(str, sizeof(str), stdin) != NULL)
    printf("line%d [len %d]: %s", i++, strlen(str), str);

对空白字符的处理:

  1. 所有空格、Tab等空白字符均被读取,不忽略。
  2. 按下回车键时,缓冲区末尾的换行符也被读取,字符串末尾将有一个换行符\n。例如,输入字符串hello,再按下回车,则读到的字符串长度为6

fgets()函数会自动在字符串末尾加上\0结束符。

第 2 个参数n指定了读取的最大长度。函数读到n-1个字符(包括换行符\n)就会停止,并在末尾加上\0结束符。剩余字符将残留在缓冲区。

建议使用fgets()完全替代gets()

fgets()对应的输出函数是fputs()

fgetc() & getc()

从指定输入流读取一个字符,输入可以是stdin,也可以是文件流,使用时需要显式指定。

这两个函数完全等效,getc()fgetc()宏定义而来。不同的是,前述的gets()fgets()相互之间没有关系。

用法示例:

char a, b;
a = fgetc(stdin);
b = getc(stdin);

对空白字符的处理:

  1. 所有空格、Tab、换行等空白字符,无论在缓冲区开头、中间还是结尾,均会被读取,不忽略。
  2. 因为只读取一个字符,所以如果输入多于1个字符(包括换行符),则它们均会残留在缓冲区。具体地说,如果什么字符都不输入,直接按下回车键,则读取到的是换行符\n,缓冲区无任何残留;如果输入一个字符如a,然后按下回车键,则读取到的是字符a,同时换行符\n残留在缓冲区。

fgetc()getc()对应的输出函数是fputc()putc()

getchar()

stdin读取一个字符。

getchar()实际上也由fgetc()宏定义而来,只是默认输入流为stdin

用法示例:

char a;
a = getchar();

getchar()常常用于清理缓冲区开头残留的换行符。当知道缓冲区开头有\n残留时,可以调用getchar()但不赋值给任何变量,即可实现冲刷掉\n的效果。

getchar()对应的输出函数是putchar()

C++ 标准输入

C++中使用标准输入输出需要包含头文件<iostream>。一般使用io

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Vim 配置 C/C++使用组合快捷键格.. 下一篇<四>模板的完全特例化和非..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目