3

Straight to the problem:

This code,

#include <iostream>
using namespace std;

int main() {
    std::string string = "9 9";
    std::cout << string;
    return 0;
}

returns 9 9 as output.

Yet, when inputting 9 9 to this code,

#include <iostream>
using namespace std;

int main() {
    std::string string;
    std::cin >> string;
    std::cout << string;
    return 0;
}

it outputs 9. Why does this happen?

I guess it has to do with the space, but is there any way to avoid this? I must say space is the only valid separation between numbers.

Felix Glas
  • 15,065
  • 7
  • 53
  • 82
Nautilus1
  • 57
  • 3

5 Answers5

7

std::cin takes one word at a time. To take the whole line you would need to use getline() function.

Usage: std::getline (std::cin,name);

Your case: This should work when you include <string>:

#include <iostream>
#include <string>

int main() {
    std::string MyString;
    std::getline (std::cin, MyString);
    std::cout << MyString;
    return 0;
}

Advice: Don't you ever use using namespace std; anymore. Also, use proper variable names.

Khalil Khalaf
  • 9,259
  • 11
  • 62
  • 104
  • 5
    `operator>>(std::istream&, std::string&)` reads one word at a time. What `std::cin` reads depends upon what function you pass it to. – Benjamin Lindley Apr 29 '16 at 01:11
  • 2
    @ben very useful comment – Khalil Khalaf Apr 29 '16 at 01:16
  • In simpler terms: `std::cin` does _not_ read "one word at a time". It is just a stream object representing the standard input stream. You could very well read all characters available from `std::cin`, including spaces, until, _e.g._, an eof is detected. – Felix Glas Apr 29 '16 at 01:52
  • @FirstStep why should you not use "using namespace std" if that is the only name space you are using, why is it bad? That's kinda a big claim for me, I could see that being an issue in a template since you don't know how it will be used. But in main that is a problem? – Caperneoignis Apr 30 '16 at 20:52
  • @cam it is completely fine to use here and/or for simple programs and many programmers are using it in big programs but it is just a good practice to know how, why and when to use it. here is a reference: http://stackoverflow.com/questions/1452721/why-is-using-namespace-std-in-c-considered-bad-practice – Khalil Khalaf Apr 30 '16 at 23:26
3

The standard library overload of the input operator >> taking an std::istream and a std::string as parameters, is designed to read characters from the stream into the std::string object until a delimiter i found, and then return the altered stream (for further reads).

All whitespace characters are by default recognized as delimiters, e.g. in most implementations, , \t, and \n (the true meaning of whitespace is defined by the locale's ctype facet).

The purpose of this design is for the usage of the input operator as a tokenizer of input data, e.g.:

std::istringstream input_stream{"apple banana pear"};

std::string token;
while (input_stream >> token) {
    // Token per iteration is: "apple", "banana", and "pear".
}

Here input_stream >> token is equivalent to the call std::operator>>(input_stream, token) which will read characters up until a delimiter into token, and then return the stream object input_stream. The returned stream object is finally checked as a bool in the while clause, which basically returns !input_stream.fail() (see std::basic_ios::operator bool).

If what you need is to read characters until a linebreak or end-of-file is detected then use std::getline.

If you want to read N characters from the stream then use, e.g., std::basic_istream::read.


Reference:

http://en.cppreference.com/w/cpp/string/basic_string/operator_ltltgtgt

Felix Glas
  • 15,065
  • 7
  • 53
  • 82
  • It reads until whitespace (ignoring EOF and `width`), where "whitespace" is defined by the locale's ctype facet. – T.C. Apr 29 '16 at 01:50
1

std::cin is an extraction stream object whose extraction behavior is dependent on the >> operator overload used. (Thanks Ben)

For C-style strings, std::string and its variants; it's operator overload only extracts one "word" (non-delimited sequence of characters) at a time.

To get an entire line of characters, you would use std::getline

Note: The default delimiters is dependent on your default locale, for en_us.utf8 it includes but not limited to, any whitespace(" "), tab("\t"), and newline("\n") encountered

WhiZTiM
  • 21,207
  • 4
  • 43
  • 68
0

Why does this happen? I guess it has to do with the space, but is there any way to avoid this? I must say space is the only valid separation between numbers.

The input operators ignore whitespace by default ( blank, tab, newline, formfeed and carriage return)!

You can use std::getline to read until newline (by default):

std::getline(std::cin, string);
Andreas DM
  • 10,685
  • 6
  • 35
  • 62
0

after writing using name space std : don't use std::cin somrthing like this.