从字符串中擦除单词(在C++中)

Erase words from a string (in C++)

本文关键字:C++ 单词 字符串 擦除      更新时间:2023-10-16

我想从字符串中删除一些单词,但我的代码不起作用。我没有任何错误或警告,但我认为我的字符串变空了。有人能帮我吗?我尝试将我的初始字符串转换为2个矢量,这样我就可以比更容易地导航

 #include <iostream>
    #include <sstream>
    #include <string>
    #include <vector>
    using namespace std;
    int main()
    {
        string s("Somewhere down the road");
        string t("down");
        istringstream iss(s);
        vector <string> plm;
        vector <string> plm2;

        do
        {
            string sub;
            iss >> sub;
            plm.push_back(sub);
        } while (iss);

    for(unsigned int i=0 ; i<plm.size();i++){
    cout<<plm[i];}

        istringstream ist(t);

        do
        {
            string subb;
            ist >> subb;
            plm2.push_back(subb);
        } while (ist);

    for(int i=0;i<plm.size();i++){
    for(int j=0;j<plm2.size();i++){
    {if (plm[i]==plm2[j])
        plm.erase(plm.begin()+j);}}}

    for(int i=0 ; i<plm.size();i++)
    cout<<plm[i];

    }

警告:这实际上只是一个太长的注释,无法放入注释字段。哦,还有一点咆哮。

我很高兴我们有了这些现代语言,生活比几十年前轻松多了。例如,考虑一下这项工作看起来像一种早已奄奄一息的SNOBOL 4编程语言:

    s = 'somewhere down the road'
del s 'down' =                     :s(del)
    OUTPUT = s

天哪,很高兴我们从那以后取得了如此大的进步,我们不必处理整整3行代码,现在我们只需要52行就可以完成这项工作(哦,除了52行实际上不起作用,但我们暂时忽略这一点)。

我想,公平地说,我们可以在C++中更紧凑地完成这项工作。一个明显的方法是使用std::remove_copy、一些流迭代器和一两个字符串流:

std::istringstream input("somewhere down the road");
std::string del_str("down");
std::istream_iterator<std::string> in(input), end;
std::ostringstream result;
std::remove_copy(in, end, std::ostream_iterator<std::string>(result, " "), del_str);
std::cout << result.str();

转换为向量没有任何好处——字符串本身已经提供了你想要做的事情所需的一切

vector<char> v;
v.assign(s.c_str(), s.c_str() + s.length()); // without... 
v.assign(s.c_str(), s.c_str() + s.length() + ); // including...
    // ... terminating null character

现在它变得很容易:

size_t pos = s.find(t);
if(pos != string::npos)
{
    s.erase(pos, t.length());
}

然而,这并不关心是否留下多个空格,或者t是否不是s中的一个完整单词(例如,t = "down"; s = "I'm going to downtown.";将导致s == "I'm going to town."),但您也没有这样做。。。

第一个问题是,如果只使用起始位置调用std::string::erase,它会擦除所有内容,直到字符串结束。

第二个问题是,代码只会一个接一个地擦除第二个字符串中的所有字母。也就是说,不是整个单词——为此,你需要检查整个单词是否匹配,然后才能擦除(单词的整个长度)。问问自己——如果前两个字母匹配,但单词的其余部分不匹配,代码中会发生什么?

在第二个for循环中,您从未增加j,并且在if (plm[i]==plm2[j])块中,您使用j而不是i作为erase()中的偏移量。

for(int i=0;i<plm.size();i++) 
{
    for(int j=0;j<plm2.size();j++)//here you need to increment j
    {
        if (plm[i]==plm2[j])
            plm.erase(plm.begin()+i);//here the offset should be i
    }
}

另一件事是不要使用do...while循环从stringstream中读取并推回向量。如果读取失败,您将把无效数据推送到矢量上,而不是尝试以下操作:

 string sub;
 while(iss >> sub;)
      plm.push_back(sub);//only if reading is successful
 ...//do the same for the other istringstream too

您不递增j这是我在您的代码中看到的第一件事。把它写对,如果它仍然不起作用,那就去问!