C语⾔输⼊输出⽤法总结
⽂章⽬录
⼀、输出
名称⽤法
putchar()只能输出单个字符
puts()只能输出字符串,并且输出结束后会⾃动换⾏
printf()可以输出各种类型的数据
对于printf()函数的格式控制符完整形式如下:
%[flag][width][.precision]type
1) type
tpye表⽰输出类型,⽐如 %d、%f、%c、%lf,type 就分别对应 d、f、c、lf;再如,%-9d中 type 对应 d。type 这⼀项必须有,这意味着输出时必须要知道是什么类型。
汇总⼀下常见的格式控制符:
格式控制符说明
%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、%P 以⼗六进制的形式输出数据的地址。P的⼤⼩写决定了⼗六进制前缀的⼤⼩写形式。(这⾥的地址都是虚拟地址,不等于数据在内存中的物理地址)
注意:
⼀个数字,是由默认类型的:对于整数,默认是int类型;对于⼩数,默认是double类型;
%g默认保留六位有效数字,包括整数和⼩数部分;%f和%e默认保留六位⼩数,只包括⼩数部分;
%g不会在最后强加0来凑够有效数字的位数,但是%f和%e会在最后强加0来凑够⼩数部分的位数;
从上表中能看出,能够以有符号形式输出的只有⼗进制的整数
2) width
width表⽰最⼩输出宽度,也就是⾄少占⽤⼏个字符的位置;
当输出结果的宽度不⾜ width 时,以空格补齐(如果没有指定对齐⽅式,默认会在左边补齐空格);当输出结果的宽度超过 width
时,width 不再起作⽤,按照数据本⾝的宽度来输出。
3) .precision
.precision 表⽰输出精度,也就是⼩数的位数
当⼩数部分的位数⼤于 precision 时,会按照四舍五⼊的原则丢掉多余的数字;
当⼩数部分的位数⼩于 precision 时,会在后⾯补 0。
另外,.precision 也可以⽤于整数和字符串,但是功能却是相反的:
⽤于整数时,.precision 表⽰最⼩输出宽度。与 width 不同的是,整数的宽度不⾜时会在左边补 0,⽽不是补空格。
⽤于字符串时,.precision 表⽰最⼤输出宽度,或者说截取字符串。当字符串的长度⼤于 precision 时,会截掉多余的字符;当字符串的长度⼩于 precision 时,.precision 就不再起作⽤。
4) flag
flag 是标志字符。例如,%#x中 flag 对应 #,%-9d中 flags 对应-。下表列出了 printf() 可以⽤的 flag:
标
志
字
符
含义
-- 表⽰左对齐。如果没有,就按照默认的对齐⽅式,默认⼀般为右对齐
+⽤于整数或者⼩数,表⽰输出符号(正负号)。如果没有,那么只有负数才会输出符号
空
格
⽤于整数或者⼩数,输出值为正时冠以空格,为负时冠以负号
#对于⼋进制(%o)和⼗六进制(%x / %X)整数,# 表⽰在输出时添加前缀:⼋进制的前缀是 0,⼗六进制的前缀是 0x / 0X。对于⼩数(%f / %e / %g),# 表⽰强迫输出⼩数点。如果没有⼩数部分,默认是不输出⼩数点的,加上 # 以后,即使没有⼩数部分也会带上⼩数点
⼆、输⼊
1、输⼊函数
名称⽤法
getchar()、getche()、getch()这三个函数都⽤于输⼊单个字符
gets()获取⼀⾏数据,并作为字符串处理
scanf()可以输⼊多种类型的数据2、getchar()、getche()、getch()区别
函数作⽤缓冲区头⽂件回显适⽤平台
getchar()获取⼀个字符(需要回车)有stdio.h有Windows、Linux、Mac OS 等所有平台函数作⽤缓冲区头⽂件回显适⽤平台
getche()获取⼀个字符(⽆需回车)⽆conio.h有Windows
getch()获取⼀个字符(⽆需回车)⽆conio.h⽆Windows
3、gets与scanf区别
get函数:获取字符串。gets() 是有缓冲区的,每次按下回车键,就代表当前输⼊结束了。
gets函数在新版C++中被移除了,因为不安全。可以⽤fgets代替,但注意fgets不会删除⾏末的回车字符。
gets() 和 scanf() 的主要区别是: ⾮常⾮常重要
scanf() 读取字符串时以空格为分隔,遇到空格就认为当前字符串结束了,所以⽆法读取含有空格的字
符串。
gets() 认为空格也是字符串的⼀部分,只有遇到回车键时才认为字符串输⼊结束,所以,不管输⼊了多少个空格,只要不按下回车键,对 gets() 来说就是⼀个完整的字符串。
故对于输⼊⼀串字符串,若字符串中包含有空格,则需要使⽤gets()函数才能正确输⼊。
4、scanf函数
scanf函数,格式控制符与printf函数相差⽆⼏。只是scanf没有了%p地址输出控制符号。
&称为取地址符,也就是获取变量在内存中的地址。
scanf() 控制字符串的完整写法为:
%{*} {width} type
其中,{ } 表⽰可有可⽆。各个部分的具体含义是:
type表⽰读取什么类型的数据,例如 %d、%s、%[a-z]、%[^\n] 等;type 必须有。
width表⽰最⼤读取宽度,可有可⽆。
*表⽰丢弃读取到的数据,可有可⽆。
5、scanf函数的符号匹配(超重点)
匹配特定字符 %[xxx]
使⽤连字符 -
常⽤的连字符举例:
%[a-z]表⽰读取 abc…xyz 范围内的字符,也即⼩写字母;
%[A-Z]表⽰读取 ABC…XYZ 范围内的字符,也即⼤写字母;
%[0-9]表⽰读取 012…789 范围内的字符,也即⼗进制数字。
你也可以将它们合并起来,例如:
%[a-zA-Z]表⽰读取⼤写字母和⼩写字母,也即所有英⽂字母;
%[a-z-A-Z0-9]表⽰读取所有的英⽂字母和⼗进制数字;
%[0-9a-f]表⽰读取⼗六进制数字。
不匹配某些字符
scanf() 允许我们在%[ ]中直接指定某些不能匹配的字符,具体⽅法就是在不匹配的字符前⾯加上^。例如:
c语言char的用法%[^\n]表⽰匹配除换⾏符以外的所有字符,遇到换⾏符就停⽌读取;
%[^0-9]表⽰匹配除⼗进制数字以外的所有字符,遇到⼗进制数字就停⽌读取。
使⽤ scanf() 清空缓冲区的⽅案,就是:
scanf("%*[^\n]"); scanf("%*c");
下⾯我们就来解释⼀下。
⾸先需要明⽩的是,等到需要清空缓冲区的时候,缓冲区中的最后⼀个字符⼀定是换⾏符\n,因为输⼊缓冲区是⾏缓冲模式,⽤户按下回车键会产⽣换⾏符,结束本次输⼊,然后输⼊函数开始读取。
scanf("%*[^\n]"); 将换⾏符前⾯的所有字符清空,scanf("%*c"); 将最后剩下的换⾏符清空。
Scanf函数从缓冲区读取数据时的⼀些特性
当遇到 scanf() 函数时,程序会先检查输⼊缓冲区中是否有数据:
如果没有,就等待⽤户输⼊。⽤户从键盘输⼊的每个字符都会暂时保存到缓冲区,直到按下回车键,产⽣换⾏符\n,输⼊结
束,scanf() 再从缓冲区中读取数据,赋值给变量。
如果有数据,那就看是否符合控制字符串的规则:
如果能够匹配整个控制字符串,那最好了,直接从缓冲区中读取就可以了,就不⽤等待⽤户输⼊了。
如果缓冲区中剩余的所有数据只能匹配前半部分控制字符串,那就等待⽤户输⼊剩下的数据。
如果不符合,scanf() 还会尝试忽略⼀些空⽩符,例如空格、制表符、换⾏符等:
如果这种尝试成功(可以忽略⼀些空⽩符),那么再重复以上的匹配过程。
如果这种尝试失败(不能忽略空⽩符),那么只有⼀种结果,就是读取失败。
注意:
换⾏符也是⼀个字符,也会进⼊缓冲区。
scanf()、gets() 在读取字符串时会忽略换⾏符,不会把换⾏符作为字符串的内容。
空⽩符在⼤部分情况下都可以忽略。但是当控制字符串不是以格式控制符 %d、%c、%f 等开头时,空⽩符就不能忽略了,它会参与匹配过程,如果匹配失败,就意味着 scanf() 读取失败了。(这个结论是实践得出的结论,没有资料可以查询)
三、关于缓冲区的⼀些总结
1、⼀些概念
缓冲区(Buffer)⼜称为缓存(Cache),是内存空间的⼀部分。缓冲区是为了让低速的输⼊输出设备和⾼速的⽤户程序能够协调⼯作,并降低输⼊输出设备的读写次数。
根据不同的标准,缓冲区可以有不同的分类。
根据缓冲区对应的是输⼊设备还是输出设备,可以分为输⼊缓冲区和输出缓冲区。
根据数据刷新(也可以称为清空缓冲区,就是将缓冲区中的数据“倒出”)的时机,可以分为全缓冲、⾏缓冲、不带缓冲。
1)全缓冲
在这种情况下,当缓冲区被填满以后才进⾏真正的输⼊输出操作。缓冲区的⼤⼩都有限制的,⽐如 1KB、4MB 等,数据量达到最⼤值时就清空缓冲区。
在实际开发中,将数据写⼊⽂件后,打开⽂件并不能⽴即看到内容,只有清空缓冲区,或者关闭⽂件,或者关闭程序后,才能在⽂件中看到内容。这种现象,就是缓冲区在作怪。
2)⾏缓冲
在这种情况下,当在输⼊或者输出的过程中遇到换⾏符时,才执⾏真正的输⼊输出操作。⾏缓冲的典型代表就是标准输⼊设备(也即键盘)和标准输出设备(也即显⽰器)。
Linux和macOS系统中printf和scanf函数都具有⾏缓冲区。
3)不带缓冲
不带缓冲区,数据就没有地⽅缓存,必须⽴即进⾏输⼊输出。
getche()、getch() 就不带缓冲区,输⼊⼀个字符后⽴即就执⾏了,根本不⽤按下回车键。
Windows 下的 printf() 也不带缓冲区,不管最后有没有换⾏符\n,都会⽴即输出,所以对于类似的输出代码,Windows 和 Linux、Mac OS 会有不同的表现。
错误信息输出函数 perror() 也没有缓冲区。错误信息必须刻不容缓、⽴即、马上显⽰出来,缓冲区将会增加捕获错误的时间,这是毫⽆理由的。
总结
输⼊:scanf()、getchar()、gets()都具有⾏缓冲,Windows 下特有的 getche() 和 getch(),不带缓冲区;
输出:Windows 平台下,输出设备是不带缓冲区的,Linux 和 Mac OS 平台下,输出设备带有⾏缓冲区。
2、缓冲区的刷新(清空)
所谓刷新缓冲区,就是将缓冲区中的内容送达到⽬的地。缓冲区的刷新遵循以下的规则:
不管是⾏缓冲还是全缓冲,缓冲区满时会⾃动刷新;
⾏缓冲遇到换⾏符\n时会刷新;
关闭⽂件时会刷新缓冲区;
程序关闭时⼀般也会刷新缓冲区,这个是由标准库来保障的;
使⽤特定的函数也可以⼿动刷新缓冲区。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论