输出:

在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():

    可获取多种数据类型,有缓冲区。

  1. //&称为取地址符,也就是获取变量在内存中的地址。
  2. //输入数据的格式要和控制字符串的格式保持一致。
  3. scanf("%d", &a); //输入整数并赋值给变量a
  4. scanf("%d %d", &c, &d); //输入两个整数并分别赋值给c、d 注意"%d %d"之间是有空格的,所以输入数据时也要有空格

getchar():

scanf(“%c”, c)的替代品,是scanf的简化版本。有缓冲区,需回车后才清除缓冲区(把内容发送至目的地)

  1. #include <stdio.h>
  2. int main()
  3. {
  4. char c = getchar();//获取屏幕输入的一个字符并赋值给c,即使输入多个字符也只会输出第一个。
  5. printf("c: %c\n", c);
  6. return 0;
  7. }

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秒后输出第二个。

  1. #include<stdio.h>
  2. #include<unistd.h>
  3. int main()
  4. {
  5. printf("C语言中文网");
  6. sleep(5); //程序暂停5秒钟
  7. printf("http://c.biancheng.net\n");
  8. return 0;
  9. }

但是当第一个printf()最后添加了换行符的话,在Linux中也会立即输出,等待五秒后再输出第二个。

  1. #include<stdio.h>
  2. #include<unistd.h>
  3. int main()
  4. {
  5. printf("C语言中文网\n");
  6. sleep(5); //程序暂停5秒钟
  7. printf("http://c.biancheng.net\n");
  8. return 0;
  9. }

这是因为printf()从本质上来说, 执行结束以后数据并没有直接输出到显示器上,而是放入了缓冲区,直到遇见换行符\n才将缓冲区中的数据输出到显示器上。

行缓存I/O

我们从键盘输入的数据并没有直接交给 scanf(),而是放入了缓冲区中,直到我们按下回车键,scanf() 才到缓冲区中读取数据。如果缓冲区中的数据符合 scanf() 的要求,那么就读取结束;如果不符合要求,那么就继续等待用户输入,或者干脆读取失败