1.细谈scanf

1.1scanf的报错

在vs2019中,使用scanf编译器会报错(具体如下)

image-20211115194803667

说的是scanf不安全,让我们使用scanf_s

原因:scanf不检查边界,导致内存访问越界,具体意思是

char a[5];scanf("%s",a);
如果输入12345678,这里5及(注意字符串末尾有'\0')以后的部分会被写到其他变量所在的空间,会导致程序运行异常

而使用scanf_s提供一个缓冲参数规定缓冲区大小,就避免了内存访问越界,具体表达为

char a[5];scanf_s("%s",a,5);scanf_s内第三个参数就是规定缓冲区大小 
int a=0;scanf_s("%d",a);对于整型,实型变量则不需要规定缓冲区大小

1.2宽度,文件内存,缓冲区

我们知道可以通过%5d在格式符前加数字来限制输入输出字符的长度,而上文又提到个缓冲区大小问题,除此之外还要考虑到文件内存大小,一共设计到三个因素,我用一张图来介绍

1590962-20190718172606703-1287717972

之前scanf_s输入超过等于缓冲区大小时,就输出了空,疑惑了我好久,上图就介绍了文件内存大小大于或等于缓冲区大小,就将数组的第一个元素赋值为’\0‘,这里也要提到一点 比如我定义字符串 char a[5];scanf_s("%s",a,5); 这里我们输入时,最多输入四个字符,因为字符串末尾自动添'\0'。

1.3scanf_s与缓冲区的问题

有关scanf缓冲区的知识,简单用几个实例解释

image-20211115220649398

由图可知,在输入a,c后,并没有让我继续输入c,而是直接得到这样的结果,为什么呢?

原因:因为我在输入1 2后,第一次scanf_s读走1给a,读走2给c按下了回车,此时回车就留在缓冲区内,要明白scanf_s是从缓冲区内拿东西,所以第二个scanf_s内的b就会接受回车(\n),结果就成所示这样。

而若要解决此情形,就要进行清空缓冲区

1.4清空缓冲区

1.fflush(stdin)的误区

在CSDN查到清楚缓冲区的知识,很多文章都说到了用fflush(stdin),可我在自己VS2019里面使用,发现并不能起作用。通过查找资料得到c/c++标准没有定义过fflush(stdin),虽然有些编译器会成功,但目前VS2019无法使用,或许有什么设置可以使其实现,但最后不要使用。

2.格式符号前加空格

scanf_s(" %c",&b)or scanf_s("\n%c,&b")
///在格式符前加空白字符
表示对输入的字符,跳过开始处出现的所有空格(包括空格、换行符、制表符等),如果不加,则由于回车、换行也是一个字符,b就会接受空白字符,导致结果不符合。

3.rewind(stdin)

但要注意多个scanf输入时回车是一定要有的,不管getchar还是scanf只要是通过缓冲区输入数据的函数都是等待回车键'\n '出现才进入缓冲区的,而不是由空格等。

Jy75dMfcasOovkp

这里图示也涉及到一个问题,第一个scanf_s是接受整型变量,当输入流中数据类型与格式字符要求不符合时,就会认为结束。此时第一项a232就留在了缓冲区并没有直接给b,此时我们按下回车,b就接受到了a232.

f1CuO7TDy2mi9Ll

而这一例子也表明,只有按了回车scanf_s才会读取缓冲区数据。上图显示我们输入回车前的缓冲区被清空,第二个scanf_s读取是第二次输入的数据。

4.ch=getchar()

相当于定义一个垃圾桶,去装回车空格等

5.while ((ch = getchar()) != EOF && ch != '\n');(万能语句)

这里有点类似直接用ch=getchar(),但这里提到一个EOF(End of File)字面意思是文件结束,这里不做解释,如想了解请自行查找资料。

6.scanf_s("%*[^\n]")scanf_s(“%*c”)

scanf_s("%*[^\n]"):将换行符前面的所有字符清空;scanf_s("%*c"):将最后剩下的换行符清空。

这样就可以实现第一个scanf后通过enter来进行第二个scanf的输入。问题就是写起来很麻烦,也不好记,所以不怎么推荐。

image-20211116160102716

用scanf_s输入字符,字符串是很麻烦的。比如有时候我希望我输入的字符串没有长度限制,可scanf_s总让我设置一个缓冲区限制,这样就会很麻烦,反而被机器给限制了,所以我们要学会用其他方式输入字符。

1.5.其他输入字符的方式

1.5.1gets()、fgets()、gets_s()、s_gets()

这几种输入方式的用法与区别,我推荐这位博主的文章,写的很详细,毕竟我也不怎么会用,讲就是误人子弟。小牛同学

1.5.1getchar()、getche()、getch()

这三种都是用来输入单个字符的,具体区别用法,也为各位推荐一位博主的文章 CurryCoder

肯定还有其他方式,我这里也只是举出来几种,并且也是引用了其他博主的文章,此篇文章也是我第一次写,一方面是听取他人学习经验,多谢博客将自己所学知识规范地写下来,对自己也有好处;另一方是也是scanf_s这玩意确实把我搞懵好几次,也许其他和我一样的C语言初学者有一样的困惑,所以花了几天时间去钻研了一下。作为一名初学者,文章内容或许有错,希望各位能够指出,谢谢各位的阅览与纠正。

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值