敲击键盘输入的数据会缓存到 stdin 缓冲区中,scanf函数就从缓冲区中取出数据。printf函数会把要显示的数据放到 stdout 缓冲区中,由显示器从中取出并显示。缓冲区中的数据都是一次性的,读取之后就会消失,你完全可以理解为管道。
由于不同系统,不的硬件底层实现输入输出的具体方法可能不一样,C语言要求系统为每个程序提供两个指针,这两个指针分别指向两个结构体,这两个结构体分别表示了键盘和屏幕在内存中的抽象表示(缓冲区的地址值被记录在这个结构体中),并将指向这两个结构体的指针命名为stdin和 stdout.这两个指针就是所谓的标准输入和标准输出。
标准输出
格式:printf(格式串,表达式1,表达式2,…)
原理:打印格式串的内容,并用后面的表达式替换格式串中的转换说明
格式串里面包含两个内容:普通字符和转换说明。
普通字符原样输出即可,因为内容已经写死。所以这里最值得讲的就是转换说明,也是很多人没有弄明白的地方。
转换说明的作用就是起到占位符的作用,它的格式:%[符号][宽度][.精度]类型
1 |
|
m 用来控制最小字段宽度。如果输出字段大于等于指定宽度就正常输出,否则 -
右补空格 或 0
左边 0 来满足欠缺的长度;如果你没有指定符号的话,就会左补空格。
1 |
|
p 用来控制精度。如果指定的精度大于要输出的精度就会补0,否则显示指定长度的精度。
1 |
|
X代表发生的类型转换。
1 |
|
标准输入
格式:scanf(格式串,表达式1,表达式2,…)
原理:本质是模式匹配
从左到右,根据格式串匹配 stdin 中的字符。如果匹配成功,继续匹配下一项;如果匹配失败,立即返回。最后,返回匹配成功的转换说明的个数。
我们的格式串包含三块内容:普通字符,空白字符,转换说明。
(一)普通字符需要精确匹配,如果匹配失败就会立即退出
1 |
|
如果你在输入字符的时候没有正常输入前面的 / 或 后面的 / ,那么就会匹配失败,并且立即退出。如果你没有成功匹配前面的 / ,那么立即匹配失败并退出,导致 num 为随机值,因为你不会有输入 num 值的机会。如果你没有匹配后面的 /,那么立即匹配失败并退出,但是 num 会正常输出,因为在此之前你已经成功输入 num 值并匹配到占位符中,只是后面的 / 没有匹配成功。如果 / 后面还有其他字符,也不会得到输出的,因为后面的 / 匹配失败导致后续的格式串也得不到匹配了,即没有被加入到 stdin 缓冲区中。
(二)在寻找数的起始位置时,会忽略任意零个或多个空白字符(如空格、制表符、换行符)
1 |
|
你可以看到数字 10 前面的空白字符会被忽略,数字 20 前面的空白字符会被忽略。因为 scanf 函数在寻找每个数的起始位置时会跳过空白字符,所以它可以成功读取这些数。
下面强调几个使用 scanf 容易忽视的地方:
- 在
scanf
的格式字符串中,任何空白字符(空格、制表符、换行符)都会使得scanf
忽略输入中的空白字符,直到遇到下一个非空白字符。 - scanf 有返回值,返回匹配成功的个数。不要将 scanf 放到 while 循环中使用。
- 使用
%c
时需要注意,scanf
不会跳过空白字符,可能会读取到空格或换行符。因此要在 占位符前面加上一个空格,比方说 ‘ %c’。 - 使用
%s
读取字符串时,scanf
会跳过前导空白字符,并在遇到第一个空白字符时停止读取。
getchar 和 putchar
前面我们将 scanf 获取单个字符存在问题,你必须占位符前面添加一个空格才可以,但是这很容易让人忘记。getchar
函数用于从标准输入读取一个字符。
getchar 从标准输入(通常是键盘)读取一个字符。如果输入的字符是 EOF 或在按下回车键之前没有输入字符,它将返回 EOF。
1 |
|
而 putchar 就用于输出一个字符了。
1 |
|
参考阅读:C语言的标准输入输出