1

I was wondering if there was any possible method of copying/assigning a whole getline(cin, str) input to a separate string? This is what I have so far:

string str;
// possibly another string strOriginal?
getline(cin, str);

for (i = 0; i < str.size(); ++i) {
    if (isspace(str.at(i))) {
        str.replace(i, 1, "");
    }
}
cout << str;
// cout << strOriginal;

I need to get rid of all spaces inside a string and then work with that new string while also being able to access the original string input later on.
Ex. If I were to input a string such as "Hello everyone" the code would output "Helloeveryone" which is what I need, however, I also need to be able to access the original string.
If anyone could help and inform me if this is possible and how to do so, that would be greatly appreciated, thanks!

General Grievance
  • 4,555
  • 31
  • 31
  • 45
  • The shown whitespace removal algorithm is fatally flawed: it will fail if the string contains two or more spaces in a row. – Sam Varshavchik Jul 04 '23 at 00:27
  • Oh wow, yes that is definitely correct... would there be a simple way to fix this? Or would I need to forgo this method and approach it some other way? –  Jul 04 '23 at 00:32
  • More generically: don't attempt to modify a collection of anything while iterating over it. – Chris Jul 04 '23 at 01:08
  • @Chris: there are exceptions, e.g. it's fine to erase from a `std::set` or `std::map` while iterating over it - just need to keep accessing/iterating from the iterator returned by the `erase` operation. And anyway, "iterating" using an index and repeated random access like OP has done is safe as long as the index logic tracks the modifications. – Tony Delroy Jul 04 '23 at 01:11
  • Just keep reading your C++ textbook. Eventually you'll reach the chapter that explains iterators, and algorithms, and shows how to do something like this, removing whitespace, with a single line of code in C++, using an algorithm call and a `std::string` method call. – Sam Varshavchik Jul 04 '23 at 01:30

3 Answers3

3

There is a short solution.

#include <algorithm>
#include <iterator>

std::string origin, nospace;
std::getline(cin, origin);
std::remove_copy_if(origin.begin(), origin.end(), std::back_inserter(nospace), ' ');

Or another one if you need to use std::isspace() from #include <ccype>

std::remove_copy_if(origin.begin(), origin.end(), std::back_inserter(nospace),
    [](char c) { return std::isspace(static_cast<unsigned char>(c)); });
273K
  • 29,503
  • 10
  • 41
  • 64
  • 1
    It's a PITA, but `[](char c) { return std::isspace(c); }` has undefined behaviour for implementations with signed `char`, when passed a negative value. You should use `[](char c) { return std::isspace(static_cast(c)); }`. (Some compilers - e.g. GCC - support -127..255 values, but it's not portable.) – Tony Delroy Jul 04 '23 at 01:06
  • Regarding the comment by @TonyDelroy, see [this answer to another question](https://stackoverflow.com/a/45007070/12149471) for more information on why the cast is required. The information in that answer regarding `isdigit` also applies to `isspace`. – Andreas Wenzel Jul 04 '23 at 02:41
  • There's a slightly easier way to deal with that: `[](unsigned char c) { return std::isspace(c); }` – Jerry Coffin Jul 04 '23 at 04:58
2
getline(cin, str);
string strOriginal = str;

I hope it's self-explanatory.

anatolyg
  • 26,506
  • 9
  • 60
  • 134
1

There are two possible solutions: The first is simply to copy the original string, and then remove the spaces from the copy, using std::remove_if and the erase-remove idiom:

// First copy the original string
std::string str_no_space = str;

// Then remove all spaces from the copy
auto new_end = std::remove_if(begin(str_no_space), end(str_no_space),
                              [](char c) { return std::isspace(c); });
str_no_space.erase(new_end, end(str_no_space));

Or you can create a new string and copy all non-space characters to it, use std::copy_if:

std::string str_no_spaces;
str_no_space.reserve(str.length());  // Pre-allocate memory, don't set size

// Copy all non-space characters from str into str_no_space
std::copy_if(begin(str), end(str), std::back_inserter(str_no_space),
             [](char c) { return !std::isspace(c); });

// Reallocate to not "waste" memory
str_no_space.shrink_to_fit();

Please note that since I use std::isspace all white-space will be removed, not only the single space character ' '.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621