Gman
Gman

Reputation: 93

How do I delete one character from a string at a time?

I am trying to figure out how to delete one character at a time from a string, so that I can obtain all versions of the string with only one character missing at a time. This is what I am trying to make work, but to no avail.

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

It obviously works correctly for the first one, but then deletes the rest. JON should have an expected output of ON JN JO

Upvotes: 8

Views: 37417

Answers (6)

Ghanendra Panwar
Ghanendra Panwar

Reputation: 3

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

Upvotes: 0

Deduplicator
Deduplicator

Reputation: 45654

That's all damn inefficient.

Just make a copy without the last character, and then slowly, iteration by iteration, replace the end of that copy with characters from the original.

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

Upvotes: 0

Richard
Richard

Reputation: 8758

Solution with iterators and temp copies:

#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';
    }
}

A solution without temporary copies, 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';
    }
}

Output:

bcdefg
acdefg
abdefg
abcefg
abcdfg
abcdeg
abcdef

Upvotes: 2

HuskyDucky
HuskyDucky

Reputation: 1288

Try this one simple and straight:

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

Upvotes: 0

Sam Varshavchik
Sam Varshavchik

Reputation: 118310

The easiest way is to make a copy of the string each time, and modify the copy:

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

For correctness, the index variable should be a std::string::size_type, what both length() and size() return (with size_t and size() naturally belonging together).

Your code almost got it right, except that it neglected to make the copy of the string each time, and s.at(i)++ didn't belong there.

Upvotes: 9

Remy Lebeau
Remy Lebeau

Reputation: 595837

You are not resetting tmp to the original string value on each loop iteration, so it keeps erasing more and more characters from tmp until it is empty.

You are also removing the wrong range of characters on each loop iteration.

You are also modifying the original string on each loop iteration to increment the value of its individual characters. Why are you doing that at all?

Try something more like this instead:

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

Upvotes: 3

Related Questions