输出:
在C语言中,有三个函数可以用来在显示器上输出数据,它们分别是:
- puts():只能输出字符串,并且输出结束后会自动换行
- putchar():只能输出单个字符
- printf():可以输出各种类型的数据
格式控制符汇总:
格式控制符 | 说明 |
---|---|
%c | 输出一个单一的字符 |
%hd、%d、%ld | 以十进制、有符号的形式输出 short、int、long 类型的整数 |
%hu、%u、%lu | 以十进制、无符号的形式输出 short、int、long 类型的整数 |
%ho、%o、%lo | 以八进制、不带前缀、无符号的形式输出 short、int、long 类型的整数 |
%#ho、%#o、%#lo | 以八进制、带前缀、无符号的形式输出 short、int、long 类型的整数 |
%hx、%x、%lx%hX、%X、%lX | 以十六进制、不带前缀、无符号的形式输出 short、int、long 类型的整数。如果 x 小写,那么输出的十六进制数字也小写;如果 X 大写,那么输出的十六进制数字也大写。 |
%#hx、%#x、%#lx%#hX、%#X、%#lX | 以十六进制、带前缀、无符号的形式输出 short、int、long 类型的整数。如果 x 小写,那么输出的十六进制数字和前缀都小写;如果 X 大写,那么输出的十六进制数字和前缀都大写。 |
%f、%lf | 以十进制的形式输出 float、double 类型的小数 |
%e、%le%E、%lE | 以指数的形式输出 float、double 类型的小数。如果 e 小写,那么输出结果中的 e 也小写;如果 E 大写,那么输出结果中的 E 也大写。 |
%g、%lg%G、%lG | 以十进制和指数中较短的形式输出 float、double 类型的小数,并且小数部分的最后不会添加多余的 0。如果 g 小写,那么当以指数形式输出时 e 也小写;如果 G 大写,那么当以指数形式输出时 E 也大写。 |
%s | 输出一个字符串 |
%p | 是一个新的格式控制符,它表示以十六进制的形式(带小写的前缀)输出数据的地址 |
printf()高级用法:
printf() 格式控制符的完整形式如下:%[flag][width][.precision]type
[ ] 表示此处的内容可有可无,是可以省略的。
- type 表示输出类型,比如 %d、%f、%c、%lf,type 就分别对应 d、f、c、lf;再如,%-9d中 type 对应 d。type 这一项必须有,这意味着输出时必须要知道是什么类型。
- width 表示最小输出宽度,也就是至少占用几个字符的位置;例如,%-9d中 width 对应 9,表示输出结果最少占用 9 个字符的宽度。
当输出结果的宽度不足 width 时,以空格补齐(如果没有指定对齐方式,默认会在左边补齐空格);当输出结果的宽度超过 width 时,width 不再起作用,按照数据本身的宽度来输出。
- flag 是标志字符。例如,%#x中 flag 对应 #,%-9d中 flags 对应-。下表列出了 printf() 可以用的 flag:
标志字符 | 含 义 |
---|---|
- | -表示左对齐。如果没有,就按照默认的对齐方式,默认一般为右对齐。 |
+ | 用于整数或者小数,表示输出数值的符号(正负号)。如果不填该字符,那么只有负数才会输出符号。 |
空格 | 用于整数或者小数,输出值为正时冠以空格,为负时冠以负号。(m= 192, n=-943) |
# | - 对于八进制(%o)和十六进制(%x / %X)整数,# 表示在输出时添加前缀;八进制的前缀是 0,十六进制的前缀是 0x / 0X。 - 对于小数(%f / %e / %g),# 表示强迫输出小数点。如果没有小数部分,默认是不输出小数点的,加上 # 以后,即使没有小数部分也会带上小数点。 |
例如:
%-9d中,d表示以十进制输出,9表示最少占9个字符的宽度,宽度不足以空格补齐,-表示左对齐。综合起来,%-9d表示以十进制输出,左对齐,宽度最小为9个字符
输入:
键盘获得用户输入:
- scanf():和 printf() 类似,scanf() 可以输入多种类型的数据。
- getchar()、getche()、getch():这三个函数都用于输入单个字符。(单个字符也就是长度为1个字节,智能存储8位数据,也就是只能是ASCAII码里的数值)
- gets():获取一行数据,并作为字符串处理。
scanf():
可获取多种数据类型,有缓冲区。
//&称为取地址符,也就是获取变量在内存中的地址。
//输入数据的格式要和控制字符串的格式保持一致。
scanf("%d", &a); //输入整数并赋值给变量a
scanf("%d %d", &c, &d); //输入两个整数并分别赋值给c、d 注意"%d %d"之间是有空格的,所以输入数据时也要有空格
getchar():
scanf(“%c”, c)的替代品,是scanf的简化版本。有缓冲区,需回车后才清除缓冲区(把内容发送至目的地)
#include <stdio.h>
int main()
{
char c = getchar();//获取屏幕输入的一个字符并赋值给c,即使输入多个字符也只会输出第一个。
printf("c: %c\n", c);
return 0;
}
getche()、getch():
getche() 就比较有意思了,它没有缓冲区,输入一个字符后会立即读取 getch()也没有缓冲区,并且没有回显,回显就是在控制台显示用户输入的字符。没有回显就是不在控制台显示输入的字符。对于用户交互输入密码来说,这是可取的。
gets():
gets()专用的字符串输入函数,可读取空格字符串。 与scanf()不同的是,它认为空格也是字符串的一部分,可以读取含有空格的字符串,而scanf()读取字符串是以空格为分割,遇到空格就认为当前字符结束了,所以无法读取空格字符。 有缓冲区,按下回车键后才从缓冲区读取内容。
对字符串的读取说明
scanf() 读取数据时需要的是数据的地址,整数、小数、单个字符都要加&取地址符,因为是值传递的,这很容易理解;但是对于此处的 url 字符串,我们并没有加 &,这是因为,字符串的名字会自动转换为字符串的地址,所以不用再多此一举加 & 了。当然,你也可以加上,这样虽然不会导致错误,但是编译器会产生警告。
数组或字符串在scanf()中不用添加&,**会自动转换地址,并且**数组和字符串名就指向的是起始地址
总结:
scanf() 可以一次性读取多份类型相同或者不同的数据,getchar()、getche()、getch() 和 gets() 每次只能读取一份特定类型的数据,不能一次性读取多份数据。
getche() 和 getch() 不是标准函数,只能用于 Windows。
缓冲区:
缓存分为两类:
- 完全缓存I/O:缓冲区满时被清空(内容被发送至目的地),通常出现在文件输入中。缓冲区的大小取决于系统,常见为512字节和4096字节。
- 行缓存I/O:遇到一个换行字符时清空缓冲区。键盘输入是标准的行缓存
这里涉及到缓冲区的知识点,暂时先不深入了解。
先知道在Linux中,以下程序会的第一个 printf() 并没有立即输出,而是等待 5 秒以后,和第二个 printf() 一起输出了。
在window中则正常先输出第一个,5秒后输出第二个。
#include<stdio.h>
#include<unistd.h>
int main()
{
printf("C语言中文网");
sleep(5); //程序暂停5秒钟
printf("http://c.biancheng.net\n");
return 0;
}
但是当第一个printf()最后添加了换行符的话,在Linux中也会立即输出,等待五秒后再输出第二个。
#include<stdio.h>
#include<unistd.h>
int main()
{
printf("C语言中文网\n");
sleep(5); //程序暂停5秒钟
printf("http://c.biancheng.net\n");
return 0;
}
这是因为printf()从本质上来说, 执行结束以后数据并没有直接输出到显示器上,而是放入了缓冲区,直到遇见换行符\n才将缓冲区中的数据输出到显示器上。
行缓存I/O
我们从键盘输入的数据并没有直接交给 scanf(),而是放入了缓冲区中,直到我们按下回车键,scanf() 才到缓冲区中读取数据。如果缓冲区中的数据符合 scanf() 的要求,那么就读取结束;如果不符合要求,那么就继续等待用户输入,或者干脆读取失败