如何删除 std::string 上以“//”开头的每一行?

问题描述 投票:0回答:4
c++ stdstring
4个回答
0
投票

最简单的方法是使用正则表达式库:

#include <iostream>
#include <regex>

int main()
{
    std::string myString = R"svg(
    <svg height={size} width={size}>
        <rect {...rectProps} x={x0h} y={y0h} />
        // <rect {...rectProps} x={x1h} y={y0h} />
        <rect {...rectProps} x={x0h} y={y1h} />
        // <rect {...rectProps} x={x1h} y={y1h} />
    </svg>
    )svg";
    
    std::cout << myString << std::endl; //before
    std::string new_string = std::regex_replace(myString, std::regex("\n *//.*\n"), "\n");
    std::cout << new_string << std::endl; //after
}

我们捕获所有以新行

\n
开头、具有零个或多个空格
 *
、两个斜杠
//
以及零个或多个以另一新行结尾的任何字符
.*
的模式。我们仅用一个新行替换出现的事件(以补偿其中一个)。

输出:

<svg height={size} width={size}>
    <rect {...rectProps} x={x0h} y={y0h} />
    // <rect {...rectProps} x={x1h} y={y0h} />
    <rect {...rectProps} x={x0h} y={y1h} />
    // <rect {...rectProps} x={x1h} y={y1h} />
</svg>


<svg height={size} width={size}>
    <rect {...rectProps} x={x0h} y={y0h} />
    <rect {...rectProps} x={x0h} y={y1h} />
</svg>

0
投票

基于 std::basic_string::find_first_not_of 找到的

'/'
的数量使用 std::basic_string::erase 的简单性很难被击败,例如

    std::string s { "//Some comment" };
    
    if (s.at(0) == '/')
        s.erase (0, s.find_first_not_of ("/"));

您还可以通过将

"//"
添加到拒绝字符来删除
" \t"
之前的任何前导空格:

    std::string s { "  //Some comment" };
    
    if (s.at(s.find_first_not_of (" \t/") - 1) == '/')
        s.erase (0, s.find_first_not_of (" \t/"));

注意:

- 1
at()
是必需的,因为它需要从零开始的索引,而
erase()
需要删除字符数)

然后要处理

"//"
周围的前导和尾随空白,您可以
#include <cctype>
并使用
isspace(c)
,如下所示:

    std::string s { "  //  Some comment" };
    char c = s.at(s.find_first_not_of (" \t/") - 1);
    
    if (c == '/' || isspace (c))
        s.erase (0, s.find_first_not_of (" \t/"));

在所有情况下,结果都是

"Some comment"


0
投票

没有按我的预期工作

除了它之外,它绝对不会按照你的方式工作。 您使用的

erase
的过载看起来像

string& erase( size_type index = 0, size_type count = npos);

来自 cppreference 的重载描述:

删除从索引开始的 min(count, size() - index) 个字符。

所以你真正做的

svg.erase(0, svg.find("//") + 1)
是删除从索引[0]到[你找到的最后一个
'/'
的索引]

的所有字符

相反,您应该执行以下操作:

  1. 在字符串中搜索
    "//"
    ,将此位置命名为 A。
  2. 在字符串中搜索
    '\n'
    ,将此位置命名为 B。
  3. 擦除间隔[A; B] 来自字符串或 [A; svg.length()] 如果你没有找到 B
  4. 重复直到没有位置A

P.s.我建议从末尾而不是从头开始搜索,因为如果它更接近末尾而不是开头,则擦除片段形式的字符串会更容易

P.p.s.如果您想精确删除间隔,请务必使用迭代器,因为删除间隔的

erase
的唯一重载是

iterator erase( const_iterator first, const_iterator last );

-1
投票

最后这就是我找到的解决方案

std::string trim(const std::string &str) {
  size_t first = str.find_first_not_of(' ');
  if (std::string::npos == first) {
    return str;
  }
  size_t last = str.find_last_not_of(' ');
  return str.substr(first, (last - first + 1));
}

bool startsWith(const std::string &input, const std::string &start) {
  return input.find(start) != std::string::npos;
}

std::string myString = R"svg(
  <svg height={size} width={size}>
    <rect {...rectProps} x={x0h} y={y0h} />
    // <rect {...rectProps} x={x1h} y={y0h} />
    <rect {...rectProps} x={x0h} y={y1h} />
    // <rect {...rectProps} x={x1h} y={y1h} />
  </svg>
)svg";

std::istringstream stream(myString);
std::string line;
std::string myFinalString;
while (std::getline(stream, trim(line))) {
  if (!startsWith(line, "//")) {
    myFinalString += line + "\n";
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.