那些年我们一起踩过的坑——读取字符(串)篇

前言

写了这么久C/C++,自以为对各种输入输出都了如指掌,直到再次做题才明白自己仍有很多地方不太了解。尤其是读取字符时经常“炸锅”,最近碰到不少控制台秒关,得不到正确的字符/字符串等现象。如今深知不能再深受其害,予攥此文以记之

输入缓冲区

所谓键盘输入缓冲区,就是我们在输入的时候,程序并不会根据我们每次输入读取相应的内容,而是先将我们输入的内容全部存储到一个缓冲队列中,包括空格回车。但是回车会作为每次输入结束的标志,输入回车后程序根据我们需要得到的数据类型,从前到后向缓冲区获取相应内容,如果获取成功则缓冲区的内容被提取,输入的多余内容仍然会被保留在缓冲队列中,用于下一次读取

当我们读取数字时,空格和回车并不会造成影响,但是当我们读取字符或者是字符串时,必须要注意输入的空格和回车!但是要注意C/C++不同的输入流的处理方式不同

scanf的坑

scanf读入字符

之前我一直这样记忆:scanf读入字符遇到回车就会结束。但是我没注意过我输入的回车也被保留在了输入缓冲区。那么问题来了,如果有多个字符输入且用回车分隔,那么后面的字符去缓冲区提取的时候,回车也就不服了,凭啥你"abcd"和空格啥的都是字符,俺就不是,于是回车就被当做字符被char类型的变量获取。然后我们就一头雾水——怎么没有得到我们需要的字符呢。所以scanf对于char类型的变量,可以从输入缓冲区得到任意字符包括空格回车

解决办法

1.在每次读入回车时加上一个getchar

char c1,c2;
scanf("%c",&c1);
getchar();
scanf("%c",&c2);

/*输入:
a
b
得到:
c1=a,c2=b
*/

2.使用fflush(stdin)清空输入缓存区所有字符

如下所示,我们第一次输入a后,跟了一串空格和其他字符,当我们按回车后程序开始读取c1,然后赋值为’a’接下来的一串字符包括回车仍然存在于输入缓冲区,此时使用该函数,那么接下来的一串字符包括回车都被清除,接着我们再输入b和回车,c2被赋值为b,回车仍存在于输入缓冲区

char c1,c2;
scanf("%c",&c1);
fflush(stdin);
scanf("%c",&c2);

/*
输入:
a空格空格dfss空格
b
得到:
c1=a,c2=b
*/

scanf读入字符串

现在我很少用char数组来存字符串了,都是使用C++的string。但是这里只提一下,就是使用scanf("%s")读入字符串时,空格被当做字符串分割符,也就是遇到空格将该空格以前的字符串赋值给相应字符串,但是回车并不是输入结束的标志,因此回车也会被字符串获取

扫描二维码关注公众号,回复: 9795508 查看本文章

cin的坑

cin>>

1.cin>>后面可以跟任何基本数据类型(包括char*,string等),而且这里有很严格的输入标志,即遇到空格回车都会作为分隔符,cin也使用输入缓冲区,但是即便是输入字符(串),在字符缓冲区获取字符时,也会跳过空格和回车,仅以文件结束符作为结束标志

2.正因为cin的以上特性,因此多样例输入完全可以按照以下方式进行:

T t;

while(cin>>t){
	...
}

getline

getline是cin输入流下读取单行字符串的一个函数,用法为getline(cin,str)。值得注意的是虽然回车作为结束符,但是输入缓冲区的回车却会对字符串产生影响,就是如果之前的输入将回车放入了输入缓冲区,那么接下来用getline就会得到空串。以前我一直以为string没有结束标志符,但是当我去网上查阅资料,发现是这样的:

std::string:标准中未规定需要\0作为字符串结尾。编译器在实现时既可以在结尾加\0,也可以不加。但是,当通过c_str()来把std::string转换为const char *时,会发现最后一个字符是\0。因此C++11,string字符串都是以’\0’结尾

但是我们知道,string是无法访问最后的结束符的,我猜测长度为len的string有效访问内容是0-len-1,结束符也许就在第len位但是无法访问

因此上面的疑惑就可以解释清了:getline在读取字符串时,以回车作为字符串的结束标志符,因此当遇到回车时,将回车转换为结束标志符后读取结束。因此如果在读取前在输入缓冲区检测到回车,那么该字符串直接添加结束标志符导致为空串

解决办法

cin.ignore()是专门用来消除结束输入缓冲区的回车的函数

string s1,s2;
cin>>s1;
cin.ignore();
getline(cin,s2);
cout<<s1<<s2<<endl;

/*
输入:
Ha
ppig
输出:
Happig
发布了128 篇原创文章 · 获赞 7 · 访问量 5268

猜你喜欢

转载自blog.csdn.net/qq_44691917/article/details/104569763