C++从字符串中删除括号的函数不会全部捕获它们
C++ function to remove parenthesis from string doesn't catch them all
我用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)7
输出:(38888)7
为什么会这样?我可以通过调用输出上的函数来解决这个问题(所以运行字符串两次),但这显然不是"好"的编程。谢谢
if(word[i] == '(' || word[i] == ')')
{
word.erase(i,1);
}
i++;
如果删除圆括号,下一个字符将移动到该圆括号之前占用的索引,因此不会选中它。使用else
。
if(word[i] == '(' || word[i] == ')')
{
word.erase(i,1);
} else {
i++;
}
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)
。一个更好的解决方案是使用擦除删除习语:
s.erase( std::remove_if(s.begin(), s.end(),
[](char ch){ return ch==`(` || ch ==`)`; })
s.end() );
如果编译器不支持lambdas,则可以将检查作为函数对象(functor)来实现。该算法具有线性复杂度O(N)
,因为未被移除的元素仅被复制一次到最终位置。
它失败了,因为在所有情况下都是递增索引。只有在不删除字符的情况下才应该这样做,因为删除会将所有超过该点的字符向后移动一个。
换句话说,只要有两个或多个连续字符要删除,就会出现这个问题。它没有同时删除它们,而是将两者"合并"为一。
在函数中运行两次它将对特定的输入字符串起作用,但您仍然会遇到类似"((((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
为什么不使用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;
}
- "error: no matching function for call to"构造函数错误
- 什么时候调用组成单元对象的析构函数
- 继承函数的重载解析
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- C++模板来检查友元函数的存在
- 递归函数计算序列中的平方和(并输出过程)
- 对RValue对象调用的LValue ref限定成员函数
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么使用 "this" 指针调用派生成员函数?
- 将对象数组的引用传递给函数
- 函数调用中参数的顺序重要吗
- C++ 如何将参数绑定到具有相同返回类型的函数,并将它们全部存储在一个容器中
- C++ 中深度嵌套函数的单个捕获全部语句?
- C++ 类析构函数删除部分但不是全部成员数据
- 即使我的函数全部定义,也会在C 中获得不确定的引用
- G++ 链接器仅对共享库中的某些函数(不是全部)未定义引用
- C++从字符串中删除括号的函数不会全部捕获它们
- 通过 WinSock2 API 的单次调用"recv()"函数调用获取全部接收字节