如何有效地从std::string中删除双引号(如果双引号存在)



这个问题可能是重复的,例如在c++中删除字符串的双引号但我看到的答案都没有解决我的问题
我有一个字符串列表,有些是双引号,有些不是,引号总是在开头和结尾

std::vector<std::string> words = boost::assign::list_of("words")( ""some"")( "of which")( ""might"")("be quoted");

我正在寻找最有效的方法来删除引号。这是我的尝试

for(std::vector<std::string>::iterator pos = words.begin(); pos != words.end(); ++pos)
{
  boost::algorithm::replace_first(*pos, """, "");
  boost::algorithm::replace_last(*pos, """, "");
  cout << *pos << endl;
}

我还能做得更好吗?我可能有成千上万的字符串要处理。它们可能来自文件或数据库。示例中的std::vector仅用于说明目的。

如果您知道引号总是出现在第一个和最后一个位置,您可以直接

if ( s.front() == '"' ) {
    s.erase( 0, 1 ); // erase the first character
    s.erase( s.size() - 1 ); // erase the last character
}

复杂度在字符串的大小上仍然是线性的。不能在0(1)时间内从std::string的开头插入或删除。如果可以用空格替换字符,那么就这样做。

检查一下可能会比较快:

for (auto i = words.begin(); i != words.end(); ++i)
    if (*(i->begin()) == '"')
        if (*(i->rbegin()) == '"')
            *i = i->substr(1, i->length() - 2);
        else
            *i = i->substr(1, i->length() - 1);
    else if (*(i->rbegin()) == '"')
        *i = i->substr(0, i->length() - 1);

它可能不是最漂亮的东西,但它是O(n)加上一个小常数。

现代c++最有效的方法是:

  if (str.size() > 1) {
    if (str.front() == '"' && str.back() == '"') {
      if (str.size() == 2) {
        str.erase();
      } else {
        str.erase(str.begin());
        str.erase(str.end() - 1);
      }
    }
  }

原理:

  • erase()函数修改字符串而不是重新分配字符串。
  • 在空字符串上调用front()会触发未定义行为。
  • 这段代码对编译器推断两个erase调用的意图并进一步优化代码的可能性是开放的(一起删除第一个和最后一个字符是一个标准问题)。

我是这样处理这种情况的:

  • Start Simple:从最简单的方法开始,就像potatoswater的答案。
  • 不要存储引号字符串:如果你可以帮助它,不要存储引号字符串。在创建std::vector<std::string>的地方检查并取消对字符串的引用。如果你只是收到一个std::vector<std::string>,你不能做太多,因为删除第一个引号将需要复制字符串的其余部分。
  • Profile/Benchmark:您可能会惊讶于几个100000个字符串的迭代速度有多快,而最终任何微优化都不会给您带来什么。总有一些情况下,你确实需要一点速度,但一定要了解如何实现最大的收益(分析会告诉你)。
  • 最坏情况:如果你必须在取消引号时防止复制整个字符串,那么存储索引/迭代器到第一个"真实"字符。对于"短"字符串,这实际上可能会慢一些,但对于"长"字符串(即mb大小)可能会有效。你也可以创建,或者找到,一个字符串类来处理移动字符串开始而不复制,但这将是我最后的选择。

相关内容

  • 没有找到相关文章

最新更新