stringstream str(line, ios_base::in);
while(!str.eof()){
string word;
str >> word;
std::transform(word.begin(), word.end(), word.begin(), ::tolower);
char c = *(--word.end());
char b = *word.begin();
if((c == ')' && b == '(') || (c == '\'' && b == '\'')){
word.erase(--word.end());
word.erase(word.begin()); //exception occurs here
}
c = *(--word.end());
if(c == ',' || c == '.' || c == '?' || c == '!')
word.erase(--word.end());
}
此代码在word.erase(word.begin())中抛出std :: length_error(what():basic_string :: _ S_create);但是,如果我将其更改为word.erase(0,1);它完美无缺。
为什么?
我正在使用gcc 4.8.1(MinGW build)
答案 0 :(得分:2)
如果line
由单个字符组成
'
然后
(c == '\'' && b == '\'')
将通过,因此我们将开始删除开头和结尾字符,word.erase(--word.end());
将删除唯一的字符,使字符串为空,word.erase(word.begin());
将崩溃,因为word.begin()
现在不指向字符串中的有效字符。 (我认为这实际上会导致未定义的行为)答案 1 :(得分:2)
您的代码存在多处问题:
std::istream::eof()
终止循环不起作用。您可能希望使用eof()
来决定是否要报告错误。std::tolower()
签名的平台上使用char
和char
会导致未定义的行为,例如,对于大多数编码,当使用我的姓氏时,它将导致未定义的行为word
为空时,会发生各种奇怪的事情。由于您没有检查是否可以成功读取单词,我想这就是发生的情况:erase()
在空字符串上使用它时,begin()
指向的位置将失败。