std::string擦除最后一个字符失败
std::string erase last character fails?
我正在尝试将通配符形式("*word*")
的用户输入更改为正则表达式格式。为此,我使用下面的代码去掉输入开头和结尾的'*'
,这样我就可以在两端添加正则表达式字符:
string::iterator iter_begin = expressionBuilder.begin();
string::iterator iter_end = expressionBuilder.end();
iter_end--;
if ((char)*iter_begin == '*' && (char)*iter_end == '*')
{
expressionBuilder.erase(iter_begin);
expressionBuilder.erase(iter_end);
expressionBuilder = "\b\w*" + expressionBuilder + "\w*\b";
}
然而,对"expressionBuilder.erase(iter_end)"
的调用并没有从输入字符串中擦除尾随的'*'
,所以我最终得到了一个不正确的正则表达式。我在这里做错了什么?如果要运行if语句中的代码,"(char)*iter_end == '*'"
必须为true(它确实这样做了),那么为什么同一个迭代器在传递给erase()时不起作用呢?
除了您发布的关于的明显问题外,您的原始代码和迄今为止提出的解决方案还有几个问题:
- 修改字符串后使用无效迭代器
- 甚至在修改字符串之前就取消引用可能无效的迭代器(例如,如果字符串为空)
- 如果expressionBuilder字符串仅包含单个"*"字符,则会出现错误
现在,如果使用代码段/例程的代码已经在验证字符串是否至少有2个字符,那么最后两项可能不会成为问题,但如果不是这样,我相信以下内容在expressionBuilder的任意值面前会更健壮:
// using the reverse iterator rbegin() is a nice easy way
// to get the last character of a string
if ( (expressionBuilder.size() >= 2) &&
(*expressionBuilder.begin() == '*') &&
(*expressionBuilder.rbegin() == '*') ) {
expressionBuilder.erase(expressionBuilder.begin());
// can't nicely use rbegin() here because erase() wont take a reverse
// iterator, and converting reverse iterators to regular iterators
// results in rather ugly, non-intuitive code
expressionBuilder.erase(expressionBuilder.end() - 1); // note - not invalid since we're getting it anew
expressionBuilder = "\b\w*" + expressionBuilder + "\w*\b";
}
请注意,当expressionBuilder
是""
、"*"
或"**"
时,此代码将起作用,因为它不执行任何未定义的操作。然而,在这些情况下,它可能不会产生你想要的结果(这是因为我不知道你在这些情况中到底想要什么)。修改以满足您的需求。
尝试按相反的顺序擦除它们:
expressionBuilder.erase(iter_end);
expressionBuilder.erase(iter_begin);
在擦除第一个*之后,iter_end引用示例中字符串末尾之后的一个字符。STL文档表明迭代器被erase()
无效,所以从技术上讲,我的例子也是错误的,但我相信它在实践中会起作用。
(已修订,因为我错过了iter_end--
行)。
您可能想要一个if语句,它只检查是否为*iter_begin == '*'
,然后调用find()
来获取另一个'*'
。或者,您可以使用rbegin()
来获得"反向序列的起始迭代器",将其提前一步,然后调用base()
将其转换为常规迭代器。这将使您获得序列中的最后一个字符。
更好的是,std::string
具有rfind()
和find_last_of()
方法。他们会给你最后一个'*'
。您也可以简单地调用replace()
,而不是剥离'*'
,然后将新的东西添加回。
减去错误处理,您可能只需要这样做:
#include <iostream>
#include <string>
using namespace std;
string stripStar(const string& s) {
return string(s.begin() + 1, s.end() - 1);
}
int main() {
cout << stripStar("*word*") << "n";
}
- 如果没有malloc,链表实现将失败
- C++字符*缓冲区的大小
- 模板参数替换失败,并且未完成隐式转换
- HEX值到wchar_t字符(UTF-8)的转换
- 在 Windows 上,stat 和 GetFileAttributes 对于包含奇怪字符的路径失败
- GetFileAttributeW对于非ASCII字符失败
- 查找下一个文件失败,出现空格字符
- 从UTF-8到ANSI wcstomb的转换在一个特定字符处失败
- 失败的输入帮助,国际和字符,C++
- 在添加额外的字符时,字符串流的putback失败
- 为什么当我删除此字符 * 时,调试断言失败block_type_is_valid
- 字符数组复制失败
- 当我传递从字符串流构建的字符指针时,流打开(..)失败
- 由于隐藏/控制字符,在C++中读取文本文件的行失败
- 当QFILE用于mediaSource时,QT声子播放失败,当字符串通过时,QT声波播放正常
- 对于非静态字符串,字符串到字符* 转换失败
- 字符编码-当读取超过127个ASCII值时,C++cin失败
- 为什么fscanf在读取字符时失败
- 调试断言失败错误,字符数组终止为null
- std::string擦除最后一个字符失败