-3

Here is the problem I'm working on:

Given an inputted line of text, print it without any spaces.

This is my attempt at a solution:

#include <iostream>

int main()
{
    using namespace std;
    std::string text;

    cin >> text;

    for(int i=0; i<text.size(); i++) {
        if(text[i]==' ') {
            text.erase(text.begin()+i);
        }
    }

    cout << text <<"\n";
}

This code prints the string and stop at the first space. What have I missed?

chris
  • 60,560
  • 13
  • 143
  • 205
  • 3
    Have you checked the [Standard library reference](http://en.cppreference.com/w/cpp/io/basic_istream/operator_gtgt2) for cin? – MatthiasB Jul 04 '14 at 14:37
  • 2
    Did you mean `std::getline(cin,text);` instead of `cin >> text;`? – πάντα ῥεῖ Jul 04 '14 at 14:38
  • Note that you don't need to modify the string to print it. Just print non-spaces. This can be done with `std::copy_if` and a light wrapper lambda around `std::isspace` as well. – chris Jul 04 '14 at 14:38
  • related: http://stackoverflow.com/questions/2765462/how-to-cin-space-in-c?rq=1 –  Jul 04 '14 at 14:46
  • @chris And input and output iterators. I don't know why, but I don't think he's quite at that level yet:-). – James Kanze Jul 04 '14 at 14:55
  • @JamesKanze, The first sentence was more for the OP and second for someone more familiar with C++ looking at how to do it, but that really wasn't clear at all. – chris Jul 04 '14 at 14:57

2 Answers2

1

The question is actually a bit vague: by "without any spaces", do you mean "without any white space" or "without any space characters"; the expression is widely used with both meanings. (The space character is white space, but so it a tab, or even a new line.)

At any rate, std::cin >> text will never put any white space into text; that's how it is defined. If you want to read a complete line, you need std::getline. And while you're on the right track with your loop, you don't test the character immediately after the one you erased. This is a classic problem when removing elements; when you remove an element, you don't want to increment.

For the rest, of course: I'm assuming you're doing this as an exercise: a professional would probably write:

text.erase( std::remove( text.begin(), text.end(), ' ' ), text.end() );

(or use std::remove_if and a functional object if the goal was to remove all white space).

And finally, if you switch to using std::isspace: you cannot call it directly with a char without risking undefined behavior. You must convert your char to unsigned char first.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • Good points, mate, but, frankly - that's exactly why I only use pure C for structurals and Java for OOP. C++ got lost in multi-paradigm universe IMO. In C I'd just do it by iterating through the char* and putc'ing anything != ' '... one simple loop, the very same effect. –  Jul 04 '14 at 15:00
  • 1
    I am a professional and my preferred way of writing it would be `boost::algorithm::erase_all(test, " ")` :) Of course, if I didn't have Boost, I'd certainly take your `erase` call and wrap it in a function named similarly to the Boost one. – Christian Hackl Jul 04 '14 at 15:00
  • /agree @ChristianHackl - all this erase/remove/isspace stuff is code smell IMO - if I just want to remove spaces, why should I call **five** functions to be able to do it? –  Jul 04 '14 at 15:01
  • @vaxquis: I would not go as far as calling it "code smell". It's just a bit too low-level for my taste. Now of course, if you were to implement a library like Boost String Algorithms... – Christian Hackl Jul 04 '14 at 15:03
  • @vaxquis If you have to do it often, then you'd certainly have an algorithm for it; I have a number of algorithms which I often use (all from pre-boost---and all updated to work with UTF-8), but I've never needed one to remove a specific character or sequence of characters from a string. So I'd use the version I posted; if I haven't needed it in the past 20 years, I probably won't need it again, so it's not worth making a special function for it. – James Kanze Jul 04 '14 at 15:37
  • yup, that's exactly why I'd write `for( int i = 0; i < text.length(); i++ ) if( text[i] != ' ' ) putchar( text[i] ); // because it's not worth making a special idiom for it.` –  Jul 04 '14 at 15:54
  • As a side note, I'm not an opponent of functional programming etc, I just think that you don't need a MegaTurboUltraHammerinator2020 to simply drive a nail through a wooden plank... –  Jul 04 '14 at 15:58
0

From cin >> reference: http://en.cppreference.com/w/cpp/io/basic_istream/operator_gtgt2

The extraction stops if one of the following conditions are met: a whitespace character (as determined by the ctype<CharT> facet) is found. The whitespace character is not extracted. (...)

tl;dr - using cin >> text; will stop extraction at first whitespace. You should use e.g. getline(), as already mentioned.

BTW, as a mental excercise: why would your code be equal to the one below?

#include <iostream>
int main() {
  std::string text;
  std::cin >> text;
  std::cout << text << '\n';
}
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055