我在c ++中编写了一个函数来从字符串中删除括号,但它并不总是因为某些原因而将它们全部捕获,我确信它非常简单。
string sanitize(string word)
{
int i = 0;
while(i < word.size())
{
if(word[i] == '(' || word[i] == ')')
{
word.erase(i,1);
}
i++;
}
return word;
}
示例结果:
输入:((3)8)8)8)8))7
输出:(38888)7
这是为什么?我可以通过调用输出上的函数来解决问题(因此运行字符串两次),但这显然不是“好”的编程。谢谢!
答案 0 :(得分:11)
if(word[i] == '(' || word[i] == ')')
{
word.erase(i,1);
}
i++;
如果删除括号,则下一个字符将移动到先前由括号占据的索引,因此不会检查。使用else
。
if(word[i] == '(' || word[i] == ')')
{
word.erase(i,1);
} else {
i++;
}
答案 1 :(得分:4)
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;
}
}
也可以使用迭代器完成,但任何一个选项都不好。对于字符串中的每个括号,将复制之后的所有元素,这意味着您的函数具有二次复杂度:O(N^2)
。更好的解决方案是使用 erase-remove 成语:
s.erase( std::remove_if(s.begin(), s.end(),
[](char ch){ return ch==`(` || ch ==`)`; })
s.end() );
如果您的编译器不支持lambdas,您可以将检查实现为函数对象(仿函数)。此算法具有线性复杂度O(N)
,因为未删除的元素仅复制一次到最终位置。
答案 2 :(得分:0)
它失败了,因为你在所有情况下递增索引。如果你没有删除这个字符,你应该这样做,因为删除会将超过该点的所有字符移回一个。
换句话说,只要您要删除两个或多个连续字符,就会遇到此问题。它不是同时删除它们,而是将两者“折叠”成一个。
通过你的函数两次运行它会对那个特定的输入字符串起作用,但你仍会遇到类似“((((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;
}
但是,我会更智能地使用该语言的设施。 C ++字符串已经能够搜索一系列字符,这些字符可能比用户循环更优化。所以你可以使用更简单的方法:
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
答案 3 :(得分:-2)
为什么不使用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;
}