c语言变量输入的导包,C语言的输入输出及缓存区

目录

一、格式控制符

整数

小数

地址

二、输出函数

printf()

puts()

putchar()

三、输入函数

scanf()

getchar()、getche()、getch()

四、缓存区

缓冲类型

缓冲区大小

结合缓存区谈输入函数

缓冲区的刷新(清空)

一、格式控制符

整数

读取一个整数时可带前缀也可不带,在格式控制符中加上 # 可输出前缀。

short

int

long

unsigned short

unsigned

unsigned long

八进制

%ho

%o

%lo

十进制

%hd

%d

%ld

%hu

%u

%lu

十六进制

%hx(%hX)

%x(%X)

%lx(%lX)

小数

%g、%lg 既可以读取一个十进制形式的小数,也可以读取一个指数形式的小数

float

double

十进制形式

%f

%lf

指数形式

%e(%E)

%le(lE)

较短形式

%g(%G)

%lg(%lG)

地址

float

带前缀

%#x(%#X)

不带前缀

%p(%P)

二、输出函数

printf()

printf() 可以输出各种类型的数据,是最灵活、最复杂、最常用的输出函数,可以替代其他输出函数。

一般格式:

printf("格式控制字符串", 参数列表);

格式控制字符串:用于控制输入数据格式,必须以引号引导,内容由一个或多个格式控制字符组合而成,也可以含普通字符,普通字符按原样在对应位置输出,也可以含转义字符。

参量列表:需要输出的一系列参数, 其个数和顺序必须与格式化字符串所说明的输出参数个数一样多, 各参数之间用逗号隔开。

输出格式控制符:

%[flag][width][.precision]type

// flag:标志字符

- : 表示左对齐。如果没有,就按照默认的对齐方式,默认一般为右对齐

+ : 用于整数或者小数,表示输出符号(正负号)。如果没有,那么只有负数才会输出符号

空格 : 用于整数或者小数,输出值为正时冠以空格,为负时冠以负号

# : 用于八进制和十六进制整数时,表示在输出时添加前缀; 用于小数时,表示强迫输出小数点

// width:最小输出宽度(至少占用几个字符的位置)

当输出结果的宽度不足 width 时,以空格补齐(如果没有指定对齐方式,默认会在左边补齐空格)

当输出结果的宽度超过 width 时,width 不再起作用,按照数据本身的宽度来输出。

// .precision:输出精度

用于小数时表示小数的位数:

当小数部分的位数大于 precision 时,会按照四舍五入的原则丢掉多余的数字

当小数部分的位数小于 precision 时,会在后面补 0。

用于整数时表示最小输出宽度:

与 width 不同的是,整数的宽度不足时会在左边补 0,而不是补空格。

用于字符串时表示最大输出宽度:

当字符串的长度大于 precision 时,会截掉多余的字符

当字符串的长度小于 precision 时,.precision 就不再起作用。

puts()

只能输出字符串,并且输出结束后会自动换行

putchar()

每次只能输出单个字符,输出多个字符需要调用多次

三、输入函数

scanf()

通用的输入函数,它可以读取多种类型的数据,是最灵活、最复杂、最常用的输入函数,但它不能完全取代其他函数

格式:

scanf("格式控制字符串", 变量地址列表);

格式控制字符串:用于控制输入数据格式,必须以引号引导,内容由一个或多个格式控制字符组合而成,也可以含有非格式控制字符,非格式控制字符称为普通字符,普通字符按原样在对应位置输入。格式控制字符串中一般不使用转义字符,否则要按原样在对应位置从键盘输入,为输入数据带来不必要的麻烦。

变量地址列表:用于指定存放数据的变量地址,scanf 会根据地址把读取到的数据写入内存。如果需要给多个变量输入数据,则各变量地址要用逗号隔开。

输入格式控制符:

%[*][width]type

// * : 输入赋值抑制字符,表示该格式说明要求输入数据,但不赋值,也即在地址列表中没有相应的地址项

// width : 宽度指示符,表示该输入项最多可输入的字符个数。如遇空格或不可转换的字符,读入的字符将减少

使用scanf函数对实型变量进行赋值时,在格式%f中不得控制小数位的精度。

scanf( ) 要求输入数据的格式要和控制字符串的格式保持一致。但对输入数据之间的空格的处理比较宽松,并不要求空格数严格对应,只要有空格就行。

scanf() 也可以读取带空格的字符串:

scanf("%[^\n]", str); // 直到输入'\n'才结束读取

%[]的意义是读入一个字符集合。[]是个集合的标志,因此%[]特指读入此集合所限定的那些字符,比如%[A-Z]是输入大写字母,一旦遇到不在此集合的字符便停止。如果集合的第一个字符是 "^",这说明读取不在 "^" 后面集合的字符,即遇到 "^" 后面集合的字符便停止。

getchar()、getche()、getch()

这三个函数都用于输入单个字符。getche( )、getch( )在缓冲区和回显方面与 scanf() 有着不同的特性,是 scanf() 不能替代的,但不是标准函数,只能用于 Windows,使用时要加上头文件 conio.h

getchar():

getchar()就是scanf("%c", c)的替代品,除了更加简洁,没有其它优势了;或者说,getchar() 就是 scanf() 的一个简化版本。

getche():

getche()没有缓冲区,输入一个字符后会立即读取,不用等待用户按下回车键,这是它和 scanf()、getchar() 的最大区别。

getch():

getch() 和 getche() 相同,也没有缓冲区。

getch() 的特别之处是它没有回显,看不到输入的字符。所谓回显,就是在控制台上显示出用户输入的字符;没有回显,就不会显示用户输入的字符,就好像根本没有输入一样。

回显在大部分情况下是有必要的,它能够与用户及时交互,让用户清楚地看到自己输入的内容。但在某些特殊情况下,我们却不希望有回显,例如输入密码,有回显是非常危险的,容易被偷窥。

四、缓存区

缓冲区(Buffer)又称为缓存(Cache),是内存空间的一部分。也就是说,在内存中预留了一定的存储空间,用来暂时保存输入或输出的数据,这部分预留的空间就叫做缓冲区。缓冲区根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区。

应用缓冲区可大大提高计算机的运行速度。比如从磁盘里取信息,我们先把读出的数据放在缓冲区,计算机再直接从缓冲区中取数据,等缓冲区的数据取完后再去磁盘中读取,这样就可以减少磁盘的读写次数,再加上计算机对缓冲区的操作大大快于对磁盘的操作。

缓冲区就是一块内存区,它用在输入输出设备和CPU之间,用来缓存数据。它使得低速的输入输出设备和高速的CPU能够协调工作,避免低速的输入输出设备占用CPU,解放出CPU,使其能够高效率工作。

缓冲类型

全缓冲:当填满缓冲区后才进行实际I/O操作。全缓冲的典型代表是对磁盘文件的读写。

行缓冲:当在输入和输出中遇到换行符时,执行真正的I/O操作。这时,我们输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O操作。典型代表是标准输入(stdin)和标准输出(stdout)。

不带缓冲:也就是不进行缓冲,标准错误文件 stderr 是典型代表,这使得出错信息可以直接尽快地显示出来。

ANSI C对stdin、stdout和stderr的缓存特征没有强行的规定,以至于不同的系统可能有不同的stdin、stdout和stderr的缓存特征。目前主要的缓存特征是:stdin和stdout是行缓存;而stderr是无缓存的。

缓冲区大小

如果没有自行设置缓冲区的话,系统会默认为标准输入输出设置一个缓冲区,这个缓冲区的大小通常是512个字节的大小。

缓冲区大小由 stdio.h 头文件中的宏 BUFSIZ 定义,如果希望查看它的大小,包含头文件,直接输出它的值即可: printf("%d", BUFSIZ);

缓冲区的大小是可以改变的,也可以将文件关联到自定义的缓冲区,通过使用 setvbuf() 和 setbuf() 函数

结合缓存区谈输入函数

从本质上讲,我们从键盘输入的数据并没有直接交给 scanf(),而是暂时保存到缓冲区中,直到我们按下回车键,scanf() 才从缓冲区中读取数据,赋值给变量。如果缓冲区中的数据符合 scanf() 的要求,那么就读取结束;如果不符合要求,那么就继续等待用户输入,或者干脆读取失败。scanf() 匹配到想要的数据后,会将匹配到的数据从缓冲区中删除,而没有匹配到的数据仍然会留在缓冲区中。

正是由于缓冲区的存在,才使得我们能够多输入一些数据,或者一次性输入所有数据。

scanf( ) 、getchar( ) 是带有缓冲区的。遇到 scanf( ) 和getchar( )函数,程序会先检查输入缓冲区中是否有数据。如果有数据,scanf( ) 会直接读取,不会等待用户输入;如果没有,就等待用户输入。而 getche()、getch() 不带缓冲区,只能立即读取。

缓冲区的刷新(清空)

其实当用户按下回车键时,回车换行符也会被保存到缓冲区,只是大多数情况下 scanf() 会忽略。但是当控制字符串不是以 %xxx 开头时,回车换行符就起作用了,scanf() 会对它进行匹配,只是匹配失败而已。所以有时候要清空缓存区。

下列情况会引发缓冲区的刷新:

缓冲区满时;

行缓冲区遇到回车时;

关闭文件;

使用特定函数刷新缓冲区。

scanf() 的缓冲区有时会引发奇怪的问题,多个 scanf() 之间要注意清空缓冲区。

清空缓冲区主要有两种思路:一是将缓冲区中的数据丢弃,二是将缓冲区中的数据读取出来,但是却不使用。

如果只考虑Windows,建议使用fflush(stdin);,简单明了;如果兼顾移植和效率,建议使用scanf("%*[^\n]%*c"); 。

1. 使用fflush( ) 清空文件缓冲区:

fflush(stdin);

fflush(stdin) 直接将缓冲区中的数据丢弃,它在 Windows 下一般是有效的,但在 Linux GCC 下可能无效,因为C语言标准规定:对于以 stdin 为参数的 fflush() 函数,它的行为是不确定的,fflush() 操作输入流是对标准C语言的扩充。

2. 使用 scanf( ) 循环读取缓冲区中的数据:

scanf("%*[^\n]%*c");

%*[^\n]将逐个读取缓冲区中的 '\n' 字符之前的其它字符,% 后面的 * 表示将读取的这些字符丢弃,遇到 '\n' 字符时便停止读取。此时,缓冲区中尚有一个 '\n' 字符遗留,所以后面的%*c将读取并丢弃这个遗留的换行符,这里的星号和前面的星号作用相同。由于所有从键盘的输入都是以回车结束的,而回车会产生一个 '\n' 字符,所以将 '\n' 连同它之前的字符全部读取并丢弃之后,也就相当于清除了输入缓冲区

3. 使用 getchar( ) 循环读取缓冲区中的数据:

int c;

while((c = getchar()) != '\n' && c != EOF);

该代码不停地使用 getchar() 获取缓冲区中的字符,直到获取的字符是换行符\n或者是文件结尾符EOF为止。这个方法可以完美清空输入缓冲区,并且具备可移植性。但需要额外定义一个 char 类型的变量,略显繁琐,并且 while 循环也会导致效率不高,所以建议使用scanf("%*[^\n]%*c"); 。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值