从字符串中删除括号的C++函数不能捕获它们 我在C++中写了一个函数来从一个字符串中删除括号,但是它并不是总是因为某些原因而完全地捕获它们。 string sanitize(string word) { int i = 0; while(i < word.size()) { if(word[i] == '(' || word[i] == ')') { word.erase(i,1); } i++; } return word; }

从字符串中删除括号的C++函数不能捕获它们 我在C++中写了一个函数来从一个字符串中删除括号,但是它并不是总是因为某些原因而完全地捕获它们。 string sanitize(string word) { int i = 0; while(i < word.size()) { if(word[i] == '(' || word[i] == ')') { word.erase(i,1); } i++; } return word; },c++,C++,样本结果: 输入:388887 产出:388887 为什么会这样?我可以通过调用输出上的函数来绕过这个问题,这样就可以运行两次字符串,但这显然不是一个好的编程。谢谢 为什么不使用strtok和一个临时字符串呢 string sanitize(string word) { int i = 0; string rVal; char * temp; strtok(word.c_str(), "()"); //I make the assumption that your values should

样本结果:

输入:388887

产出:388887


为什么会这样?我可以通过调用输出上的函数来绕过这个问题,这样就可以运行两次字符串,但这显然不是一个好的编程。谢谢

为什么不使用strtok和一个临时字符串呢

string sanitize(string word)
{
int i = 0;
 string rVal;
 char * temp;
strtok(word.c_str(), "()"); //I make the assumption that your values should always start with a (
do
{
   temp = strtok(0, "()");
   if(temp == 0)
   {
       break;
   }
   else { rVal += temp;}
}while(1);

return rVal;
}
如果删除圆括号,则下一个字符将移动到该圆括号先前占用的索引,因此不会选中它。使用另一个


它失败了,因为您在所有情况下都在增加索引。只有在不删除字符的情况下才应该这样做,因为删除操作会将超出该点的所有字符向后移动一个

换句话说,如果要删除两个或多个连续字符,就会出现此问题。它不是同时删除它们,而是将两者合并为一

在函数中运行两次将对特定的输入字符串起作用,但您仍然会遇到类似pax的问题,因为第一次调用将它折叠到pax,第二次调用将为您提供pax

一种解决方案是在删除字符时不提前索引:

std::string sanitize (std::string word) {
    int i = 0;

    while (i < word.size()) {
        if(word[i] == '(' || word[i] == ')') {
            word.erase(i,1);
            continue;
        }
        i++;
    }
    return word;
}
您可以在以下完整程序中看到这一点:

#include <iostream>
#include <string>

std::string sanitize (std::string word) {
    int i = 0;

    while ((i = word.find_first_of ("()", i)) != std::string::npos)
            word.erase (i, 1);
    return word;
}

int main (void) {
    std::string s = "((3)8)8)8)8))7 ((((pax))))";
    s = sanitize (s);
    std::cout << s << '\n';
    return 0;
}

如果编译器不支持lambdas,则可以将检查作为函数对象函子实现。由于未删除的元素只复制一次到最终位置,因此该算法具有线性复杂性。

可行是可行的。就我个人而言,我更喜欢使用char*而不是std::string,大多数人觉得这很奇怪。如果我们想用纯C++方法,我确信有一百万种方法可以去做。另外,关于编程的最好部分:一百万种方法,回到家里。让我们从一个不编译的事实开始。“是的,@ MooingDuck,C++有Strutok,它在CSTRON头上。如果我要把所有的东西都给他,我会亲自给他发代码。如果人们想这样做,一个char*,或者一个dynamic_cast就可以解决问题。或者,如果我能为他解决整个问题,我会想出一个完全不同的解决方案。当然,你是对的。与重新发明轮子相比,我本可以按原样修复他的函数。c_str member函数返回一个const char*。修改字符串,就像这个糟糕的例子一样,是未定义的行为。如果你必须使用strtok,你必须先制作你自己的字符串副本。给任何未来的访问者的提示:word.erasestd::remove_ifstd::beginword,std::endword,[]char c{return c==| c==;},std::endword;应该就这么做了。@chris,这应该是回答,而不是评论。@paxdiablo,我想是的。我想已经有关于OP代码的好答案了,但我想我应该填补这个空白。@paxdiablo,我完全错过了David答案的附件,直到我发布之后。毕竟它就在那里:p我想上次之后,当它还不在那里的时候,我没有太仔细地看。这就成功了,我知道这很简单。谢谢
std::string sanitize (std::string word) {
    int i = 0;

    while (i < word.size()) {
        if(word[i] == '(' || word[i] == ')') {
            word.erase(i,1);
            continue;
        }
        i++;
    }
    return word;
}
std::string sanitize (std::string word) {
    int spos = 0;

    while ((spos = word.find_first_of ("()", spos)) != std::string::npos)
            word.erase (spos, 1);
    return word;
}
#include <iostream>
#include <string>

std::string sanitize (std::string word) {
    int i = 0;

    while ((i = word.find_first_of ("()", i)) != std::string::npos)
            word.erase (i, 1);
    return word;
}

int main (void) {
    std::string s = "((3)8)8)8)8))7 ((((pax))))";
    s = sanitize (s);
    std::cout << s << '\n';
    return 0;
}
388887 pax
while(i < word.size())
{
    if(word[i] == '(' || word[i] == ')')
    {
        word.erase(i,1);
    }
    i++;
}
while (i < word.size()) {
   if (word[i] == '(' || word[i] == ')' ) {
      word.erase(i,1);
   } else {
      ++i;
   }
}
s.erase( std::remove_if(s.begin(), s.end(), 
                        [](char ch){ return ch==`(` || ch ==`)`; })
         s.end() );