如何逐个删除字符串中的一个字符?

8

我正在尝试找出如何逐个删除字符串中的一个字符,以便获得每次只缺少一个字符的所有版本。这是我想让它工作的方式,但却没有成功。

for(int i = 0 ; i < s.length() ; i++){
    tmp.erase(0, i);
    std::cout << tmp << std::endl;
    s.at(i)++;
}

显然,它对第一个字符串的操作是正确的,但是接下来的字符串都被删除了。 JON 的预期输出应该是 ON JN JO

6个回答

9

最简单的方法是每次复制字符串,并修改副本:

for(std::string::size_type i = 0 ; i < s.size() ; i++){
    auto tmp=copy;
    tmp.erase(i, 1);
    std::cout << tmp << std::endl;
}

为了正确性,索引变量应该是std::string::size_type,这是length()size()返回的内容(使用size_tsize()自然地成对)。

您的代码几乎正确,只是忽略了每次复制字符串,并且s.at(i)++不应该出现在那里。


2
为了保证正确性,索引应该是 std::string::size_type,可能是 size_t 也可能不是。此外,tmp.erase(i) 将删除从指定索引到字符串末尾的所有字符。如果要删除单个字符,需要使用 tmp.erase(i, 1)tmp.erase(tmp.begin()+i) - Remy Lebeau
谢谢。已纠正。 - Sam Varshavchik
@SamVarshavchik 哦,那很有道理!谢谢。哈哈,对s.at(i)++感到无语... - Gman

3
你在每个循环迭代中没有将tmp重置为原始字符串值,因此它会不断从tmp中擦除更多字符,直到为空。
你也在每个循环迭代中删除了错误的字符范围。
你还在每个循环迭代中修改了原始字符串,以增加其各个字符的值。为什么要这样做呢?
试试像这样的操作:
for(std::string::size_type i = 0 ; i < s.length() ; i++){
    std::string tmp = s;
    tmp.erase(i, 1);
    std::cout << tmp << std::endl;
}

2

使用迭代器和临时副本的解决方案:

#include <iostream>
#include <string>
int main()
{
    std::string s("abcdefg");
    for (auto i = s.begin(); i != s.end(); ++i)
    {
        const std::string b = { s.begin(), i }; // temp copy!
        const std::string e = { i + 1, s.end() }; // temp copy!
        std::cout << b << e << '\n';
    }
}

不需要临时副本的解决方案,C++20 std::string_view:

#include <iostream>
#include <string>
#include <string_view>
int main()
{
    std::string s("abcdefg");
    for (auto i = s.begin(); i != s.end(); ++i)
    {
        const std::string_view b = { s.begin(), i };
        const std::string_view e = { i + 1, s.end() };
        std::cout << b << e << '\n';
    }
}

输出:

bcdefg
acdefg
abdefg
abcefg
abcdfg
abcdeg
abcdef

0

试试这个简单而直接的方法:

while (TMP.size()) {
    cout << TMP << '\n';
    TMP.erase(0, 1);
}

0
#include <iostream>
using namespace std;
int main()
{
    string s;
    cin>>s;

    for(int i=0;i<s.length();i++)
    {
        string s1=s;
        s1.erase(i,1);
        cout<<s1;
    }
}

2
尝试添加一些解释,说明这段代码为什么有效或者与其他答案不同。 - Uli Sotschok

0

这太不高效了。

只需复制而不包括最后一个字符,然后逐步迭代地用原始字符替换该副本的结尾即可。

template <class F>
void do_with_one_missing(std::string_view s, F f) {
    auto i = size(s);
    if (i-- > 0) return;
    std::string x = s.remove_suffix(1);
    f(std::as_const(x));
    while (i-- > 0) {
        x[i] = x[i + 1];
        f(std::as_const(x));
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接