C++ 从c+中的字符串中删除字符+;
我正在实现一种方法,从字符串txt中删除某些字符,in-place。下面是我的代码。预期结果为“bdeg”。但是结果是“bdegfg”,似乎没有设置空终止符。奇怪的是,当我使用gdb进行调试时,在设置null终止符之后C++ 从c+中的字符串中删除字符+;,c++,string,C++,String,我正在实现一种方法,从字符串txt中删除某些字符,in-place。下面是我的代码。预期结果为“bdeg”。但是结果是“bdegfg”,似乎没有设置空终止符。奇怪的是,当我使用gdb进行调试时,在设置null终止符之后 (gdb) p txt $5 = (std::string &) @0xbffff248: {static npos = <optimized out>, _M_dataplus = {<std::allocator<char>>
(gdb) p txt
$5 = (std::string &) @0xbffff248: {static npos = <optimized out>,
_M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x804b014 "bdeg"}}
(gdb)p txt
$5=(std::string&@0xbfff248:{static npos=,
_M_dataplus={={},},_M_p=0x804b014“bdeg”}
在我看来这是对的。那么这里的问题是什么
#include <iostream>
#include <string>
using namespace std;
void censorString(string &txt, string rem)
{
// create look-up table
bool lut[256]={false};
for (int i=0; i<rem.size(); i++)
{
lut[rem[i]] = true;
}
int i=0;
int j=0;
// iterate txt to remove chars
for (i=0, j=0; i<txt.size(); i++)
{
if (!lut[txt[i]]){
txt[j]=txt[i];
j++;
}
}
// set null-terminator
txt[j]='\0';
}
int main(){
string txt="abcdefg";
censorString(txt, "acf");
// expect: "bdeg"
std::cout << txt <<endl;
}
#包括
#包括
使用名称空间std;
无效审查字符串(字符串&txt,字符串rem)
{
//创建查找表
bool-lut[256]={false};
对于(int i=0;i问题是不能像C样式字符串那样处理C++字符串是问题。也就是说,不能只插入0个在C.中的方法来说服您自己,将此添加到代码中。“CUT问题是,不能像C风格字符串那样处理C++字符串。问题是,你不能只插入一个类似于C.的0来说服你自己,把这个添加到你的代码中:cOUT
STD::String不是空的,因为你想,所以你必须使用其他方式来做这个< /P>
将函数修改为:
void censorString(string &txt, string rem)
{
// create look-up table
bool lut[256]={false};
for (int i=0; i<rem.size(); i++)
{
lut[rem[i]] = true;
}
// iterate txt to remove chars
for (std::string::iterator it=txt.begin();it!=txt.end();)
{
if(lut[*it]){
it=txt.erase(it);//erase the character pointed by it and returns the iterator to next character
continue;
}
//increment iterator here to avoid increment after erasing the character
it++;
}
}
现在这个函数的复杂度为O(n),因为函数std::unordered_set::find
和std::string::push_back
的复杂度为O(1)。
若您使用复杂度为O(logn)的普通std::set find,那个么整个函数的复杂度将变为O(n logn)。std::string并不像您认为的那个样以null结尾,所以您必须使用其他方法来完成此操作
将函数修改为:
void censorString(string &txt, string rem)
{
// create look-up table
bool lut[256]={false};
for (int i=0; i<rem.size(); i++)
{
lut[rem[i]] = true;
}
// iterate txt to remove chars
for (std::string::iterator it=txt.begin();it!=txt.end();)
{
if(lut[*it]){
it=txt.erase(it);//erase the character pointed by it and returns the iterator to next character
continue;
}
//increment iterator here to avoid increment after erasing the character
it++;
}
}
现在这个函数的复杂度为O(n),因为函数std::unordered_set::find
和std::string::push_back
的复杂度为O(1)。
若使用复杂度为O(logn)的普通std::set find,则整个函数的复杂度将变为O(n logn)。文本是字符串而不是字符数组。
此代码
// set null-terminator
txt[j]='\0';
不会截断第j个位置的字符串。文本是字符串而不是字符数组。
此代码
// set null-terminator
txt[j]='\0';
不会截断第j个位置的字符串。您没有告诉字符串您已更改其大小。如果从字符串中删除任何字符,则需要使用调整大小
方法更新大小。您没有告诉字符串您已更改其大小。您需要使用调整大小
方法如果从字符串中删除任何字符,则使用d更新大小。在std::string
中嵌入空终止符是完全有效的,并且不会更改字符串的长度。但是,如果尝试使用流提取输出,则会产生意外的结果
您试图达到的目标可以更容易实现:
#包括
#包括
#包括
#包括
int main()
{
std::string txt=“abcdefg”;
std::string filter=“acf”;
txt.erase(std::remove_if(txt.begin(),txt.end(),[&](字符c)
{
返回std::find(filter.begin(),filter.end(),c)!=filter.end();
}),txt.end());
//期待:“bdeg”
std::cout在std::string
中嵌入空终止符是完全有效的,并且不会更改字符串的长度。但是,如果您尝试使用流提取输出它,则会得到意外的结果
您试图达到的目标可以更容易实现:
#包括
#包括
#包括
#包括
int main()
{
std::string txt=“abcdefg”;
std::string filter=“acf”;
txt.erase(std::remove_if(txt.begin(),txt.end(),[&](字符c)
{
返回std::find(filter.begin(),filter.end(),c)!=filter.end();
}),txt.end());
//期待:“bdeg”
std::cout你打算这个“bool lut[256]={false};”做什么?它不会将数组初始化为所有的假值。@Jay:事实上,它是这样的。这个:bool lut[256]={};
--当您为数组提供初始值设定项时,任何未指定的元素都会进行值初始化。对于bool
,值初始化意味着false
。但我认为这只是偶然的。”另一方面,全局数组和静态数组的元素会自动初始化为它们的默认值,这对于所有基本类型来说都意味着它们被零填充“除了将第一个元素初始化为false之外,什么也不做。所有剩余的都是默认值,我猜是false。如果(…)可以使代码更简单,您可以使用C++11吗?std::remove_.@Jay:={false}”;
将第一个元素初始化为false
,然后,由于存在初始化器,所有元素都将初始化为false
。如果他编写了={true};
,则会将第一个元素初始化为true
,其余元素初始化为false
(同样,因为他提供了一个初始值设定项)。但是,如果他只是编写了bool lut[256];
——没有初始值设定项,元素将处于未初始化状态,处于不确定状态。这只是语言的一条规则。这个“bool lut[256]={false}”是什么意思该怎么办?它不会将数组初始化为所有的假值。@Jay:事实上,它是这样做的。这也会:bool lut[256]={};
——当您为数组提供初始值设定项时,任何未指定的元素都会进行值初始化。对于bool
,值初始化意味着false
。不过我认为这只是偶然的。“另一方面,全局数组和静态数组的元素会自动初始化为其默认值,对于所有基本类型,这意味着它们都用零填充。”即“={false}”“除了将第一个元素初始化为false之外,什么也不做。所有剩余的都是默认值,我猜是false。如果(…)可以使代码简单得多,您可以使用C++11吗?std::remove_.@Jay:={false};#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
int main()
{
std::string txt="abcdefg";
std::string filter = "acf";
txt.erase(std::remove_if(txt.begin(), txt.end(), [&](char c)
{
return std::find(filter.begin(), filter.end(), c) != filter.end();
}), txt.end());
// expect: "bdeg"
std::cout << txt << std::endl;
}
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <unordered_set>
int main()
{
std::string txt="abcdefg";
std::string filter = "acf";
std::unordered_set<char> filter_set(filter.begin(), filter.end());
std::string output;
std::copy_if(txt.begin(), txt.end(), std::back_inserter(output), [&](char c)
{
return filter_set.find(c) == filter_set.end();
});
// expect: "bdeg"
std::cout << output << std::endl;
}