Title:
/* Revise the loop that printed the first paragraph in text
* to instead change the elements in text that correspond
* to the first paragraph to all uppercase.
*由于目前进度,没有直接从text文本中获取输入,基本实现即使从CLI获取字符串输入(text),然后将第一段非空的字符串大写输出
*/
1)问题描述:
调试过程中发现,当输入多行字符串都为空值时最后在输出时候会出现“段错误”。
修改后源代码如下:
#include <iostream>
#include <string>
#include <vector>
using std::cout;
using std::cin;
using std::endl;
using std::vector;
using std::string;
int main()
{
vector<string> text;
for (string line; getline(cin, line);) text.push_back(line);
auto temp=text.begin();
if((*temp).empty())
{
// while((*temp).empty()&&temp!=text.end()):判断text.end()的条件在后面的话,可能会产生段错误!!!
while(temp!=text.end() && (*temp).empty())
temp++;
}
if(temp==text.end())
{
std::cerr<<"No data in the text?? boni!!"<<endl;
return -1;
}
else
{
for(auto &charater:*temp)
{
charater=toupper(charater);
}
cout<<"Print out the text which you type:"<<endl;
for(auto tmp=text.begin();tmp!=text.end();tmp++)
cout<<*tmp<<endl;
}
return 0;
}
2)处理过程
从上面代码中可以看出,在被注释掉的那行就是引起段错误的根因。
// while((*temp).empty()&&temp!=text.end()):判断text.end()的条件在后面的话,可能会产生段错误!!!
主要原因是:
1.当键入的字符串只有换行符("\n")没有其他内容时,getline的处理方式是“从给定的输入流中读入内容,直到遇到换行符为止(注意换行符也被读进来了),然后把所读的内容存入到那个string对象中去(注意不存换行符)”,意思就是说,在这种场景下,实际上vector对象text实际上是空文本;
2.当while 循环处理到temp=text.end()时,实际上此时的temp是一个尾后迭代器,这个迭代器没什么实际含义,仅是一个标识,同时不能对该迭代器执行解引用,因为是未被定义的行为;
while((*temp).empty()&&temp!=text.end()):
在这种输入场景下,当“(*temp).empty()”的位置在“temp!=text.end()”前面时,while()语句先执行前者,然后在尝试执行后者进行与判断,但是此时temp刚好等于“text.end()",所以这个行为是非法的。
从而在执行的时候产生段错误。
3)小结
附图红色框出部分为调试前后的对比,最后定位为由于对迭代器非法解引用导致“段错误”: