C中输入函数的理解 -- getchar和scanf
2017-10-24 13:34
381 查看
之前对C中几个输入函数的理解不深,这几次写代码的过程中遇到一些问题,因此又重新学习了一下,在此记录一下。
程序运行界面如下:
假如我们此时不输入1,2,或者q,而是输入abc,我们程序设计的初衷是希望显示输入错误,然后重新输入新值。为了实现这个目的,在while循环开始的时候,我们让ch的值为空格键的值,因此希望即便是输入的字符个数超过1,程序也能在下一次开始循环的时候将ch的值进行重新赋值,冲掉之前的错误输入,进而接收新值。
然后程序的实际运行情况如下:
可以看到,我们输入abc之后,程序4次提示输入错误,这是因为我们输入abc并按回车键之后,这些输入(包括回车键)被送入输入缓冲区,然后getchar函数从中挨个读取,即便while循环一开始ch被赋初值空格键,但是仍然会被缓冲区送进来的字符冲掉,因此加上回车键才会出现4次报错。
解决此问题的方法就是每次输入完之后将输入缓冲区的内容进行清空,清空的方法网上主要有以下几种:
经测试,setbuf函数不太好用,经典式完美实现!
换成
也会出现上面同样的结果。
不过当不用字符的方法而是用字符串的方法实现上面的功能的时候,就不会出现上述问题,需要注意一点的是字符串的比较要用strcmp函数,而不是简单的使用等于号进行判断。(汗……昨晚脑子抽抽就犯了这个低级错误!)
为字符串变量开辟足够空间
使用字符串指针的时候,不能使用字符串常量对指针进行初始化,否则会出现错误。
程序开始我们为str数组设置了5个字符的长度,因此我们在输入的时候输入字符的个数不能超过5,但是有时候我们即便输入超过5个字符的时候,程序也能运行,并成功输出,这是因为scanf对输入的字符串长度不进行检查,能够输入并成功输出是因为第5个字符之后的一些空间是没有被占用的,所以就成功地输入了多余的字符到这个数组中,这是很危险的,因为假如第5个字符之后的空间被占用,那么就会改写某些数据,出现错误。这其实在测试程序中也能看出来。
首先是我们输入的字符串大小小于设定的字符数:
可以看到,程序正确输出我们的输入,并且提示程序运行结束,按任意键可推出。
然后是我们的输入大于设定的字符数:
此时可以看到,虽然程序正确输出了我们的输入值,但是程序没有正常结束,也没有任意键退出的提示,因此程序处于不正常状态。
这两段代码一个是没有进行初始化,另一个是使用字符串常量进行初始化,这都是不正确的,指针未进行初始化就是野指针,不知道指针指向何处,强行写入会发生危险;而不能使用字符串常量进行初始化是因为,字符串常量是常量,值不能修改,str指针指向它之后,就不能往里写入值了。
上面两段代码的运行结果如下:
正确的做法是为字符串开辟一段空间,并使指针指向它:
最后顺便提一下:使用scanf函数和gets()函数输入字符串的时候,scanf函数会保留回车键,而gets函数不会保留回车键。
1. getchar
getchar()函数是从stdin标准输入流也就是键盘中读入一个字符的函数,当输完内容之后,按回车键会将输入放到输入缓冲区中,然后getchar函数会挨个读取,注意回车键也会读取,下面用一段代码进行说明:char inname[50],outname[50]; while(1) { char ch = ' '; printf("**************************************************\n"); printf("**************************************************\n"); printf("Please enter the number you want to use: \n"); printf("\t1 Convert BIN file to TXT\n"); printf("\t2 Convert TXT file to BIN\n"); printf("\tq quit\n"); printf(">>>"); ch = getchar(); printf("before if,c is: %c\n",ch); if( ch == '1' || ch == '2') { printf("Please enter the input file name: \n"); printf(">>>"); scanf("%s",inname); printf("Please enter the output file name: \n"); printf(">>>"); scanf("%s",outname); if (ch == '1') bin2txt(inname,outname); else txt2bin(inname,outname); } else if (ch == 'q') exit(1); else printf("Enter error !! Enter again !!\n"); printf("end while c is: %c\n",ch); }
程序运行界面如下:
假如我们此时不输入1,2,或者q,而是输入abc,我们程序设计的初衷是希望显示输入错误,然后重新输入新值。为了实现这个目的,在while循环开始的时候,我们让ch的值为空格键的值,因此希望即便是输入的字符个数超过1,程序也能在下一次开始循环的时候将ch的值进行重新赋值,冲掉之前的错误输入,进而接收新值。
然后程序的实际运行情况如下:
可以看到,我们输入abc之后,程序4次提示输入错误,这是因为我们输入abc并按回车键之后,这些输入(包括回车键)被送入输入缓冲区,然后getchar函数从中挨个读取,即便while循环一开始ch被赋初值空格键,但是仍然会被缓冲区送进来的字符冲掉,因此加上回车键才会出现4次报错。
解决此问题的方法就是每次输入完之后将输入缓冲区的内容进行清空,清空的方法网上主要有以下几种:
fflush(stdin); //Windows 系统 rewind(stdin); //Windows 系统 setbuf(stdin,NULL); while((ch = getchar()) != '\n' && ch != EOF); //经典式
经测试,setbuf函数不太好用,经典式完美实现!
所以要谨记,getchar是从输入缓冲区挨个读取字符的函数,包括回车键。
2. scanf函数
1. scanf输入字符
scanf函数也是从标准输入流中读取内容的函数,它是一种格式化输入函数,因此将上一个内容中的ch = getchar();
换成
scanf("%c",ch);
也会出现上面同样的结果。
不过当不用字符的方法而是用字符串的方法实现上面的功能的时候,就不会出现上述问题,需要注意一点的是字符串的比较要用strcmp函数,而不是简单的使用等于号进行判断。(汗……昨晚脑子抽抽就犯了这个低级错误!)
2. scanf输入字符串
在这里要强调使用scanf函数输入字符串的时候,要注意以下的问题:为字符串变量开辟足够空间
使用字符串指针的时候,不能使用字符串常量对指针进行初始化,否则会出现错误。
关于开辟足够空间
看以下代码:# include <stdio.h> int main() { char str[5]; scanf("%s",str); printf("str is : %s\n",str); return 0; }
程序开始我们为str数组设置了5个字符的长度,因此我们在输入的时候输入字符的个数不能超过5,但是有时候我们即便输入超过5个字符的时候,程序也能运行,并成功输出,这是因为scanf对输入的字符串长度不进行检查,能够输入并成功输出是因为第5个字符之后的一些空间是没有被占用的,所以就成功地输入了多余的字符到这个数组中,这是很危险的,因为假如第5个字符之后的空间被占用,那么就会改写某些数据,出现错误。这其实在测试程序中也能看出来。
首先是我们输入的字符串大小小于设定的字符数:
可以看到,程序正确输出我们的输入,并且提示程序运行结束,按任意键可推出。
然后是我们的输入大于设定的字符数:
此时可以看到,虽然程序正确输出了我们的输入值,但是程序没有正常结束,也没有任意键退出的提示,因此程序处于不正常状态。
关于指针初始化
使用scanf函数输入字符串,尤其是使用字符串指针的时候,要注意一定进行初始化并且不能使用字符串常量进行初始化。# include <stdio.h> int main() { char *str; scanf("%s",str); printf("str is : %s\n",str); return 0; }
# include <stdio.h> int main() { char *str = "abc"; scanf("%s",str); printf("str is : %s\n",str); return 0; }
这两段代码一个是没有进行初始化,另一个是使用字符串常量进行初始化,这都是不正确的,指针未进行初始化就是野指针,不知道指针指向何处,强行写入会发生危险;而不能使用字符串常量进行初始化是因为,字符串常量是常量,值不能修改,str指针指向它之后,就不能往里写入值了。
上面两段代码的运行结果如下:
正确的做法是为字符串开辟一段空间,并使指针指向它:
# include <stdio.h> # include <stdlib.h> int main() { char *str = (char *)malloc(10*sizeof(char)); scanf("%s",str); printf("str is : %s\n",str); free(str); return 0; }
最后顺便提一下:使用scanf函数和gets()函数输入字符串的时候,scanf函数会保留回车键,而gets函数不会保留回车键。
相关文章推荐
- c语言笔记——对scanf()等输入函数的深入理解
- 深入解析scanf()/getchar()和gets()等函数针对字符串输入的问题
- 输入函数scanf,gets,getchar简单区别测试
- 输入函数gets()、fgets()、scanf()、getchar()
- 输入与输出函数(printf、putchar、puts和scanf、getchar)
- 深入解析scanf()/getchar()和gets()等函数针对字符串输入的问题
- 换个角度理解C语言getchar()、getch()、scanf()函数
- scanf( )函数的格式化输入
- C语言scanf函数输入时键盘缓冲区\n的问题[经典问题]
- c语言:用scanf函数输入数据,举例并分析错误原因
- 深度比较 scanf()/getchar()和gets()等函数
- 第二天-输入(scanf)输出(printf)函数
- 【缓存区问题】深入了解scanf()/getchar()和gets()/cin等函数
- 格式化输入函数scanf()及输入输出函数的*修饰符
- 关于用getchar()代替scanf处理大量输入
- 用scanf()函数输入带空格的字符串
- C语言中scanf格式化输入函数
- 关于scanf()函数的一点理解
- scanf()函数实现输入带有空格的字符串
- 深入了解scanf()/getchar()和gets()/cin等函数