复杂的输入输出
按指定格式输出数据的宽度、小数位数、上下行数据按小数点对齐、用八进制、十六进制输出等。
输出数据格式的控制
整型格式说明符
-
十进制形式(0~9)
说明符 说明 数据类型 %d和%md 用于基本整型 int %ld和%mld 用于长整型 long %u和%mu 用于无符号基本整型 unsigned int %lu和%mlu 用于无符号长整型 unsigned long -
八进制(0~7)
说明符 说明 数据类型 %0和%mo 用于基本整型 int %lo和%mlo 用于长整型 long -
十六进制形式(0~F)
说明符 说明 数据类型 %x和%mx 用于基本整型 int %lx和%mlx 用于长整型 long m表示输出整型数据所占总宽度(即列数),其中:
①当实际数据的位数不到m位时,数据前面将用空格填满;
②若实际数据的位数大于等于m位时,则以数据的实际位数为准进行输出;
一个int型整数也可以用%u输出,反之一个unsigned型整数也可以用%d、%o、%x格式输出。按相互赋值的规则处理。
举例:
/************************************************************************* > File Name:demo03.c > Author:zk > Description: > Created Time: 2025年02月10日 星期一 15时37分14秒 ************************************************************************/#include <stdio.h>int main(int argc,char *argv[]) {printf("%d\n",12);// 实际只占2列,12printf("%6d\n",12);// m是正数,实际占了6列,前面不足的使用空格填充,♦♦♦♦12printf("%-6d\n",12);// m是负数,实际占了6列,后面不足的使用空格填充,12♦♦♦♦printf("%6d\n",12345678); // 如果实际的数据列宽超过了规定的列宽,列宽失效,按照实际显示,12345678return 0; }
字符型格式说明
-
字符型
说明符 说明 举例 %c或者%mc 输出的字符占m列 printf(“%3c\n”,‘a’); -
字符串型
在C语言中,是支持字符串常量的,但是不支持字符串变量。
说明符 说明 %ms 输出的字符串占m列。若串长>=m,全部输出;反之在串前补空格(m为正往前补空格)
举例:printf(“%6s\n”,hello); // ♦hello%-ms 输出的字符串占m列。若串长>=m,全部输出;反之在串后补空格(m为负往后补空格)
举例:printf(“%-6s\n”,hello); // hello♦%m.ns 输出的字符串占m列。只取字符串前n个字符,不足部分串前补空格。
举例:printf(“%6.2s\n”,“hello”); // ♦♦♦♦he%-m.ns 输出的字符串占m列。只取字符串前n个字符,不足部分串后补空格。
举例:printf(“%-6.2s\n”,“hello”); // he♦♦♦♦注意:因为空格本身不是很好区分,笔记中使用♦代替空格显示
一个整数,只要其值在0
~
255范围内,也可以用%c格式按其字符形式输出。这里0~127对应ASCII。在输出前,系统会自动将整数作为ASCII码转换成相应的字符;反之,一个字符也可以输出成一个整数。
案例:
-
要求:字符串输出
-
代码:
#include <stdio.h>int main() {printf("%3s,%7.2s,%-5.3s,%.4s\n","CHINA","CHINA","CHINA","CHINA");return 0; }
-
运行结果:
CHINA,♦♦♦♦♦CH,CHI♦♦,CHIN
浮点型格式说明符
浮点型格式分为三种形式:
- 十进制形式:
%m.nf
或者%-m.nf
- 指数形式:
%m.ne
或者%-mne
- %g或者%G形式:根据数值的大小,自动选择%f或者%e中宽度较短的一种格式,不输出无意义的0
解释:
在输出浮点型数据时,格式说明符中的m表示整个数据所占的列宽,n表示小数点后面所占的位数(保留的小数位)如果在小数点后取n位后,所规定的数据宽度m不够输出数据前面的整数部分(包括小数点),则按实际的位数进行输出。
在C语言中,用于输出单精度浮点型与双精度浮点型数据格式说明符一样的。
案例:
-
要求输出浮点型数时,指定小数位
-
代码:
#include <stdio.h>int main() {float f = 123.456;printf("%8.2f,%-8.2f,%8.6f,%8.2e,%g\n",f,f,f,f,f);return 0; }
-
运行结果:
♦♦123.46,123.46♦♦,123.456001,1.23e+02,123.456 123.456 = = 1.23456 ∗ 1 0 2 = = 1.23456 e 2 123.456 == 1.23456*10^2==1.23456e^2 123.456==1.23456∗102==1.23456e2
案例:
-
要求:求3个圆的周长,输出结果时上下按小数点对齐,取两位小数
-
代码:
#include <stdio.h> #define PI 3.1415926 void main ( ) {double r1=1.53,r2=21.83,r3=123.71,s1,s2,s3;s1=2.0*PI*r1;s2=2.0*PI*r2;s3=2.0*PI*r3;printf("s1=%10.2f\ns2=%10.2f\ns3=%10.2f\n",s1,s2,s3)return 0; }
-
运行结果:
案例:
-
要求:设有如下C程序
-
代码:
#include "stdio.h" main() {double x=34.567;printf("x=%f\n",x);// 34.567000printf("x=%d\n",x);// 27263,这种写法错误,自动类型转换异常printf("x=%d\n",(int)x);// 34 }
-
这个程序的实际运行结果为
x=34.567000
x=27263
x=34
-
说明:
显然,这个程序中的第二个格式输出语句输出的结果是错误的,这是因为在第二个格式输出语句中,格式说明符%d是基本整型格式说明符,而输出项目是双精度型的数据,它们是不匹配的。
输入数据格式的控制
整型格式说明符
-
十进制形式(0~9)
说明符 说明 数据类型 %d 用于基本整型 int %ld 用于长整型 long %u 用于无符号基本整型 unsigned %lu 用于无符号长整型 unsigned long -
八进制(0~7)
说明符 说明 数据类型 %0 用于基本整型 int %lo 用于长整型 long -
十六进制形式(0~F)
说明符 说明 数据类型 %x 用于基本整型 int %lx 用于长整型 long
可见:
① 用于输入与输出整型数据的格式说明符是完全一致的。
② 与输出情形一样,对于八进制与十六进制的输入格式,主要用于输入无符号的整型数
据。
浮点型格式说明符
- 单精度浮点型:%f或者%e
- 双精度浮点型:%lf
可见:
①与输出不同,输入时无论是单精度还是双精度浮点型,都不能用m.n来指定输出的宽度和小数点后的位数。
②可以指定输入数据所占的列数,系统自动按他截取所需数据,如:
scanf("%3d%3d",&a,&b);
当输入1234567时,a得到123,b得到456,多余的7无用。③若在%后有一个
*
和一个数字,表示跳过他指定的列数,如:
scanf("%2d%*3d%3d",&a,&b);
当输入12345678时,a得到12,%*3d表示跳过2列,b得到678
案例:
#include <stdio.h>int main()
{int a,b;scanf("%3d%3d",&a,&b);// 输入1234567,a=123,b=456
}
-
当用于输入整型数据的格式说明符中没有宽度说明时,则在具体输入数据时分为以下两种情
况:① 如果各格式说明符之间没有其它字符,则在输入数据时,两个数据 之间用"空格"、或"Tab"、或"回车"来分隔。
② 如果各格式说明符之间包含其它字符,则在输入数据时,应输入与 这些字符相同的字符作为间隔。
例如,设有如下说明
int a,b;
float c,d;
现要利用格式输入函数输入a=12,b=78,c=12.5,d=7.6。采用不同的格式说明,其输入数
据的形式也是不同的。分别说明如下:- 若输入语句为 scanf(“%d%d%f%f”,&a,&b,&c,&d); (即格式说明符中没有宽度说
明,各格式说明符之间也没有其他字符。)
则输入数据的形式应为12 78 12.5 7.6
↲ (两个数据之间用空格来分隔,当然也可用
“Tab”或“回车”来分隔。) - 若输入语句为 scanf(“%d,%d,%f,%f”,&a,&b,&c,&d);(格式说明符中没有宽度说明,
但各格式说明符之间有其它字符,即逗号)
则输入数据的形式应为12,78,12.5,7.6
↲ (即在输入的两个数据之间同时要输入逗号。) - 若输入语句 scanf(“a=%d,b=%d,c=%f,d=%f”,&a,&b,&c,&d); (即格式说明符中没
有宽度说明,但各格式说明符之间有其它字符。)
输入数据的形式应为a=12,b=78,c=12.5,d=7.6
↲ (即在输入的两个数据之间同时要输入
这些非格式说明符的字符。)
- 若输入语句为 scanf(“%d%d%f%f”,&a,&b,&c,&d); (即格式说明符中没有宽度说
-
在用于输入的实型格式说明符中不能用m.n来指定输入的宽度和小数点后的位数(这是与输出的不同之处)。
例如:
scanf("%7.2f",&a); × 此用法是错误的
-
为了便于程序执行过程中从键盘输入数据,在一个C程序开始执行时,系统就在计算机内存中开辟了一个输入缓冲区,用于暂存从键盘输入的数据。开始时该输入缓冲区是空的。当执行到一个输入函数时,就检查输入缓冲区中是否有数据;
扩展:输入输出缓冲机制
缓冲区的概念
- 缓冲区(也称为缓存)是内存空间的一部分,用于暂存输入或输出的数据。
- 在进行输入操作时,系统从外部设备(如键盘)读取数据,先放入缓冲区,程序再从缓冲区中读取数据。
- 在进行输出操作时,系统先将数据放入缓冲区,然后在特定条件下(如缓冲区满、遇到特定字符、手动刷新等)再将缓冲区中的数据输出到外部设备(如屏幕)。
缓冲区的类型
C语言的缓冲区有三种类型:
- 全缓冲:当缓冲区填满后,才进行实际的输入输出操作。例如,对磁盘文件的读写。 —
window 全缓冲大小4096字节 linux 全缓冲大小1024字节 - 行缓冲:当在输入和输出中遇到换行符时,执行实际的输入输出操作。例如,标准输入
(stdin)和标准输出(stdout)。 - 无缓冲:不进行缓冲,直接进行输入输出操作。例如,标准错误流(stderr)。
缓冲区的刷新条件
缓冲区的刷新(即将缓冲区中的数据实际输出到外部设备)通常发生在以下情况之一:
- 缓冲区满:当缓冲区写满时,会自动刷新。
- 遇到特定字符:如换行符(\n)。
- 手动刷新:使用fflush(stdout)函数手动刷新输出缓冲区。
- 程序关闭时:当程序结束时,缓冲区中的数据会被刷新。
缓冲区的实际应用
- 提高效率:通过缓冲区,可以减少与外部设备的交互次数,提高数据传输的效率。
- 处理输入输出:例如,使用scanf和printf函数时,数据先被放入缓冲区,然后按照特定的规则从缓冲区中读取或输出。
原理实现
注意事项
- 在处理输入时,特别是连续输入多个数据时,需要注意缓冲区中可能残留的数据,这可能会影响后续的输入操作。
- 在使用fflush(stdin)来清空输入缓冲区时,需要注意这是未定义行为,在标准C中并不推荐这种做法。