C++ 从c+中的字符串中删除字符+;

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>>

我正在实现一种方法,从字符串txt中删除某些字符,in-place。下面是我的代码。预期结果为“bdeg”。但是结果是“bdegfg”,似乎没有设置空终止符。奇怪的是,当我使用gdb进行调试时,在设置null终止符之后

(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;
}