-2

I recently tried a code mentioned somewhere on this site to remove blank spaces in a string. The answer suggested the function remove from the algorithm library (amazingly explained here: https://www.geeksforgeeks.org/stdremove-stdremove_if-c/) but it gives an unexpected output. It replaces all the blank spaces with some random numbers. Here is the code.

#include <iostream>
#include <algorithm>
using namespace std;

int main() 
{
string a;
int b;
getline(cin, a);
remove(a.begin(), a.end(), ' ');
b = stoi(a);
cout << b << endl;
return 0;
}

If I input 14 546 32 for example it outputs 145463232. Oddly enough if I input 1 2 3 4 5 it outputs the correct thing: 12345.

Expected output, input:

I input any number with blank spaces in between some numbers.

It outputs the number without spaces.

I tried compiling it online with this compiler: https://www.onlinegdb.com/. It has the exact same output. Can anybody figure out what is wrong with the code. And also i need to turn the string into an integer to do some mathematical operations with the integer afterwards (that is why I use the stoi function). Thanks.

Phaeton
  • 15
  • 4
  • onlinegdb is a neat tool. Have you used it to step through the program to see where the behaviour deviates from your expectations yet? Exceptionally helpful when looking for bugs. – user4581301 Jan 10 '21 at 20:41
  • @user4581301 Hello, do you mean i should use the debugger. I am new to this stuff so sorry if this what I am asking is dumb. – Phaeton Jan 10 '21 at 20:46
  • Quoting [cppreference](https://en.cppreference.com/w/cpp/algorithm/remove) *Removes all elements satisfying specific criteria from the range [first, last) and returns a past-the-end iterator for the new end of the range.* It removes the stuff you don't want from a range. Not from the string. Typical usage is to call `erase` on the iterator returned by `remove` to actually remove (yup. I know this sounds dumb, the whole `remove` not removing thing) the unwanted characters from the string. – user4581301 Jan 10 '21 at 20:46
  • A good C++ textbook will not only explain what `std::remove` does but will also give several examples of using it correctly, which will make it clear what other additional step the shown code is missing. – Sam Varshavchik Jan 10 '21 at 20:47
  • A debugger, despite the name (WTF is up with this naming?), doesn't find and remove bugs for you. The basic use is inspect the variables in play. Step a line. If the program took the expected path, inspect the variables again to make sure they contain the expected values. It the variables are incorrect or the program took the wrong path, you need to take a closer look at the line. Sometimes you break the line up into multiple steps to see where on the line the code is wrong and sometimes you reread the documentations to see if you misunderstood it the first time. – user4581301 Jan 10 '21 at 21:04
  • If you still can't see the problem, you at least know where the problem is and can research it more closely or ask a very targeted question. – user4581301 Jan 10 '21 at 21:05
  • 1
    @user4581301 I researched the difference between the erase and the remove function and now I know where the problem is. Thanks for the help to everyone who took their time to answer my question or to comment. – Phaeton Jan 10 '21 at 21:09

2 Answers2

0

Interesting thing about std::remove is that it does not actually remove anything. =)

You will need to erase the character by yourself like this:

#include <iostream>
#include <algorithm>
using namespace std;

int main() 
{
    string a;
    int b;
    getline(cin, a);
    a.erase(remove(a.begin(), a.end(), ' '), a.end());
    b = stoi(a);
    cout << b << endl;
    return 0;
}

You can read more about Erase–remove here: https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom

Phaeton
  • 15
  • 4
Arseniy
  • 680
  • 5
  • 10
  • Hello, thank you very much for taking your time to answer, but even that doesn't work. I inputed 78 789 90 and it outputs 78789900. It adds an unnecessary zero in the end. Could you please explain why this happens? Thanks. – Phaeton Jan 10 '21 at 20:53
  • @Phaeton The above code should have worked so I tried it out and got the expected result: https://ideone.com/TiVJhT – user4581301 Jan 10 '21 at 20:58
  • @user4581301 Thank you very much. I must have made a copy paste mistake while writing the code. Your answer works. Thanks. – Phaeton Jan 10 '21 at 21:01
  • Great! You can mark my answer as an answer if you will :) – Arseniy Jan 10 '21 at 21:04
  • 1
    @Arseniy Yep, I will do that now. Thanks for taking your time to answer my question. – Phaeton Jan 10 '21 at 21:06
0

std::remove removes the elements that compare equal to its argument by shifting the remaining elements using move-assignment. It doesn't resize the container after shifting those elements. In your case, since the objects are of type char, they are simply copied to the beginning of the array. So the end of your string stays the same.

When you remove spaces from the first number, and shift everything to left, you get this:

old string: 14 546 32
new string: 145463232

When you do the same in the second case:

old string: 1 2 3 4 5
new string: 12345 4 5

The only reason you get the correct result in the second one is the space in-between. First number in the string (12345) is converted to int and returned.

Note that std::remove also returns an iterator to the new end of the list. You could use that to resize the string.

auto end = remove(a.begin(), a.end(), ' ');
a.resize(end - a.begin());
Cem
  • 1,276
  • 4
  • 17