大家好,欢迎来到IT知识分享网。
scanf、gets、getchar和getch 使用及其原理。
一、说在最前:回车及换行。
概念
在计算机还没有出现之前,有一种叫做电传打字机。在电传打字机打字时,在每行后面加两个表示结束的字符,分别叫做回车和换行。
回车:是告诉打字机把打印头定位在左边界,不卷动滚筒;符号 \r;十六进制 0x0d
换行:是告诉打字机把纸张向下方移动一行,不改变左右位置;符号 \n;十六进制 0x0a
区别
在Unix系统里,每行结尾只有”<换行>”,即按下Enter后会产生 ‘\n’ ( linux与 unix系统基本一致)
在Win系统里,每行结尾是”<回车><换行>”,即按下Enter后会产生 ‘\r’ 和 ‘\n’
在Mac系统里,每行结尾是”<回车>”,即按下Enter后会产生 ‘\r’
上述系统按下 Enter 后都会进行回车和换行操作,而产生的 ‘\r’ ‘\n’ 则会保留在 输入缓冲区 。
二、缓冲区
三、scanf、gets、getchar和getch 区别及一些原理。
1. scanf
scanf 指定了输入的格式,并按照格式说明符解析输入对应位置的信息并存储于可变参数列表中对应的指针所指位置。
从 scanf() 角度看输入
假设scanf() 根据一个%d转换说明读取一个整数:scanf 函数每次从输入缓冲区中读取一个字符,跳过所有空白字符,直到遇到第一个非空白字符才开始读取。因为要读取整数,所以 scanf 希望发现一个数字字符或者是 ’ + ’ 或 ’ – ’ 。如果找到一个数字或者 ’ + ’ 或 ’ – ’ ,它便保存该字符,并读取下一个字符。scanf 不断地读取和保存,直到遇到非数字字符。如果遇到一个非数字字符,它便认为读到了整数的末尾。然后 scanf 把非数字字符放回到输入缓冲区中。( 这就意味着程序在下次读取时,首先读到的是上一次读取时丢弃的非数字字符 ) 最后 scanf 计算已读数字相应的数值,并将计算后的值放入指定的变量中。
如果使用%s转换说明:scanf 会读取除空白字符以外的所有字符。scanf 跳过空白开始读取第1个非空白字符,并保存直到再次遇到空白字符。这就意味着 scanf 根据%s 转换说明读取一个不包括空白字符的字符串。当scanf 把字符串放进指定数组中时,它会在字符序列末尾加上’\0’,让数组内容成为一个C字符串。
空白符(空白符:指空格符、制表符、回车符)
例子解析
现在假设你的缓冲区里有:abcd\n1234\n (其中\n是回车符) 执行:scanf("%s",name);的时候 由于scanf是读数据直到看见空白符(空白符:指空格符、制表符、回车符)就停止的输入函数所以执行后,把abcd存到了name中。 缓冲区于是变成了 :\n1234 接下来的执行就有问题了,如果遇到了:scanf("%d",&number);怎么办?因为遇到了回车符,它并不是一个数字。 所以scanf还有一个特性,就是忽略先导的空白符。不管是有几百个回车也好,几万个空格也罢, 只要它们连续地出现在缓冲区的开头,就统统忽略他们。然后再读有意义的字符。于是1234被读入number。 回到刚刚,当缓冲区还是:\n1234\n的时候,如果遇到了:scanf("%c",&sex);应该怎么办呢? 你说,那好办呀,不是说了忽略前导空白符吗。 跳过回车读'1'呀!想法是好的,可这只针对你的程序这一种情况。如果我编写的程序就是统计用户输入了多少个回车呢 所以对scanf来讲跳过前导空白符有个例外,当参数是%c的时候,就把缓冲区的第一个字符返回回去,不管是什么。 这样的设计就有个问题,scanf对不同的参数表现出来的特性不一样。得承认,这是个缺陷,但不是说这样不好。 这样的设计至少把发现所有字符的机会交给了用户,设计者这样想:如果程序员使用了scanf("%c",..) 那他就有必要知道这函数能把回车符读出来,至于程序员对回车符感不感兴趣,那就看他了 不感兴趣的话,程序员也一定知道该怎么处理。回到你的程序里。 当执行scanf("%s",name)的时候,要求你从键盘输入,于是你输入了"abc",然后“回车” 缓冲区里自然而然地是:abc\n ,scanf把abc拿走了,留下了\n 缓冲区里现在就剩下\n于是,下一个scanf ("%c",&sex); 想当然地读取了\n
scanf ()
scanf 按格式从输入缓冲区内读取数据 (即从输入缓冲区中取出),读取并丢弃先导的空白符,直到非空字符才开始保存,当读取 到空白符,也就是 空格符、制表符、回车符时,停止读取并将空白符 放回 输入缓冲区 ( 注意:%c例外,不会放弃先导空白符,而是直接读取第一个字符 )。切记:键盘输入最后按下的回车键 会以 ‘\n’ 的形式存放进输入缓冲区,当scanf 以%c读取时会读入上一次键盘输入末尾的 \n 导致读取数据错误,所以用%c时要清空输入缓冲区,以免读取到垃圾数据。
注意:scanf(“%d\n”,&num); \n在scanf格式串中不表示等待换行符,而是读取并放弃 (丢掉,不放回输入缓冲区) 连续的空白字符。(事实上,scanf格式串中的任何空白字符都表示读取并放弃空白字符。而且,诸如%d这样的格式也会扔掉前边的空白,因此你通常根本不需要在scanf格式串中加入显式的空白。)
因此,”%d\n”中的\n会让scanf读到非空白字符为止,而它可能需要读到下一行才能找到这个非空白字符。这种情况下,去掉\n仅仅使用”%d”即可。
2. gets
3. getchar
void clear_in(void) {
int c; while( (c=getchar() ) != '\n' && c != EOF); }
getchar会一直读取字符直到输入缓冲区内没有数据(返回一个EOF = End Of File 文件结束),这样输入缓冲区就清空干净了。
4. getch
注意:getch();并非标准C中的函数,不存在C语言中。所以在使用的时候要注意程序的可移植性。
1.所在头文件是conio.h。而不是stdio.h。
2.在使用之前要调用 initscr(),结束时要调用 endwin()。否则会出现不输入字符这个函数
也会返回的情况。
3.若使头文件 getch.h ,也会出现不输入字符这个函数直接返回的情况,可以使用多个getchar()来清空缓冲区。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/125625.html