栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > C/C++/C#

输入函数scanf的特殊用法、gets以及gets的替代函数的功能

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

输入函数scanf的特殊用法、gets以及gets的替代函数的功能

使用scanf函数接收字符串时,如果不加以说明,scanf函数是不会接收空格的,一旦读取到空格scanf就停止接受。如果一定要读取到空格,就需要用到扫描字符集%[],[]内可以加入不想要读取到的字符,直到读取到目标字符,scanf才会停下。

目录

scanf函数

扫描字符集

gets函数

fgets函数


scanf函数

如果要用scanf函数读取空格首先要了解扫描字符集的概念。

扫描字符集

明解C语言中这样描述扫描字符集:扫描字符集(scanset)元素的非空序列。实参必须为指向字符型数组第一个字符的指针。该数组的长度须足够容纳所有字符序列以及null字符。该转换会自动添加一个表示字符串末尾的null字符。
转换说明符为左方括号[与右方括号]之间的格式控制字符串中的所有字符序列。当紧跟在左方括号后面的字符不是折音符^时,扫描字符集由左右方括号之间的扫描列表(scanlist) 构成。当紧跟在左方括号后面的字符是^时,扫描集为未出现在^与右方括号之间的扫描列表中的所有字符。当转换说明符以[]或字符开始时,第一个右方括号为扫描列表中的一一个字符元素,而第二个出现的右方括号才是转换说明的结束符。当转换说明符不以[]和[^]开始时, 第一个出现的右方括号就是转换规范的结束符。当扫描列表中含有连字符-,并且既非第一个字符(如果以^开头,则为第二个字符)也非最后一个字符时,其定义因编译器而异。

乍一看这么长一定很难,但如果用代码的形式来表示就简单许多:

  1、[]之间没有^时:

#include
int main()
{
	char str[10] = "";
	//1、无^时:只读取[]内存在的字符,一旦输入的字符不在[]中,停止读取
	scanf("%[abcde]", &str);
	printf("%sn", str);
	return 0;
}

样例如:


2、[ 后紧跟着^时:

#include
int main()
{
	char str[10] = "";
	scanf("%[^b]", &str);
	//2、有^时:读取直到n停止——只要^和]之间的所有字符未出现时,scanf的读取就不会停止
	
	printf("%sn", str);
	return 0;
}

样例:


对于画删除线的部分,其实是有些不妥的,如果是以]开头,其意义同其他字符一样,并不会什么都不读取,如:

 而]不在开头的情况下,结果在VS2019环境下并不符合:

 至于扫描集中含有连字符的情况结果视编译器而定,大家可以自行尝试。


 那么用scanf函数输入空格的方法为:

scanf("%[^n]", &str);

gets函数

顾名思义,gets即get string的缩写,作用即为获取字符串,printf和scanf分别为带格式化字符串的输入输出,而gets和puts则为不带格式化的字符串的输入输出。使用gets可以直接读取到空格以及任何非换行符"n"的字符,输入"n"则中断输入。看起来gets函数非常的方便,但当我们在VS2015以及以后版本的环境下使用gets函数时会报警告:

 而gets的头文件为,并不是因为未包含头文件造成的。而如果在C++官网查询的话我们会发现该函数在C11标准下就被移除了:

 虽然在VS上我们依旧可以使用该函数,不过事实上VS2015起该函数已经不存在了。移除该函数的原因也很简单,该函数不安全。gets没有指定输入的字符串的大小,那么就会造成一个隐患:当遭到恶意大量输入时,很容易发生溢出。 从安全的角度来看,gets函数最好不再使用。

作为替代,像scanf_s一样,也有一个函数gets_s作为替代,不过二者的用法不太一样,gets_s除了输入字符串的内容以外,还需要另指定一个参数来确定字符串的长度,(超出的部分会被截断)。

char *gets( char *str );
char *gets_s( char *str, rsize_t n );

当然使用gets_s也会有更多的限制:


fgets函数

虽然gets_s可以解决gets存在的安全问题,不过并不是在所有的编译器上都可用,它并不是通用函数,而fgets既能解决gets函数的安全问题,也能保证在每个编译器上可用。

char *fgets( char          *str, int count, FILE          *stream );//(C99 前)
char *fgets( char *restrict str, int count, FILE *restrict stream );//(C99 起)

第一个参数为数据存放的数组地址,第二个参数为最大长度,第三个参数为输入源,从键盘上输入则输入源为stdin.如果count<=1并不会报错,但不会读取数据。与gets_s一样,如果输入字符串长度大于最大长度,那么超出部分依然会被截断。实例:

 当然输入的字符串内容也要保证长度小于数组长度:


不管是gets_s还是fgets都可以用来替代gets函数,因此尽可能地避免使用gets函数吧。

转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1038219.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号