paxdiablo
paxdiablo

Reputation: 882426

Why are there two different getline() functions (if indeed there are)?

Every time I do a quick snippet of C++ code line

std::string s;
cin >> s;

I curse myself because I forgot it stops at the whitespace rather than getting an entire line.

Then, on remembering getline, I invariably become confused as to the two varieties:

std::string s;
getline (std::cin, s);

and:

char cs[256];
std::cin.getline (cs, sizeof (cs));

Is there actually a difference between these two other than the data type?

It seems to me the C++ way should be the former. Under what circumstances would I use the latter, given that I probably should be using real strings instead of null-terminated character arrays anyway?

And, since input should really be the purview of the input streams, why isn't the former part of istream?

Upvotes: 33

Views: 21334

Answers (6)

Raja Murugan K
Raja Murugan K

Reputation: 1

Source:https://www.reddit.com/r/learnprogramming/comments/4fx64h/is_there_a_difference_between_cingetline_and/

The member function cin.getline() works with C strings (i.e. arrays of char) whereas the free function std::getline() works with C++ strings (i.e. std::string.) You should not be using C strings at all when learning C++, which means you should not be using cin.getline().

std::getline() reads a string from an input stream up to some delimiter. The delimiter by default is '\n' and there's no reason to specify that third argument if you're just going to pass the newline character. It doesn't know or care what is contained in that string, other than checking for the delimiter. If you want to attempt to parse that string as an integer or a floating point value you can certainly do that after reading from the stream, but that's not std::getline()'s job. It just reads a string.

Upvotes: -1

Tony Delroy
Tony Delroy

Reputation: 106236

It's a common interface-design problem. cin.getline() is a natural way to make the request, but to avoid making the stream code dependent on <string>, no cin.getline(std::string&) function can be offered. The free-standing getline(cin, s) can later be added once strings have been brought into scope. Not a problem for char* as there's nothing to #include - all part of the language anyway.

In some ways, it's nice when languages allow later code to add further functions to existing classes (e.g. Ruby), but in other ways the delocalisation bites and, well, compromises maintainability. Then of course there's the popular argument for minimal member functions and lots of free-standing functions: I personally think it shouldn't be taken so far as to make the interface less intuitive and expressive, but each to their own.

Upvotes: 11

Matthieu M.
Matthieu M.

Reputation: 300259

Bear in mind that the Standard library is composed from 3 (main) parts: IOStream, String and STL, plus some tossed in goodies and the C-headers.

I don't see anything weird in having those parts loosely coupled (though I wish it was not the case).

Other incongruities include: std::string::length vs std::string::size, the latter having been added for interface compatibility with the STL and the former having been retained for compatibility with older code.

Upvotes: 12

AProgrammer
AProgrammer

Reputation: 52324

Yes the modern C++ way is to use the free function and input an std::string.

But IOStream has a far longer history (the standard version is at least the third incarnation of the same design) than std::string and that history explain why things are the way they are.

(The getline member has the advantage that it doesn't imply dynamic allocation; that characteristic can be handy at time but would probably not be enough to justify it in a from scratch design).

Upvotes: 1

Fr&#233;d&#233;ric Hamidi
Fr&#233;d&#233;ric Hamidi

Reputation: 263137

The global getline() function works with C++ std::string objects.

The istream::getline() methods work with "classic" C strings (pointers to char).

Upvotes: 33

Simon Richter
Simon Richter

Reputation: 29618

The getline variant inside the iostreams library does not support strings as targets, so the string library defined a variant that does.

Upvotes: 2

Related Questions