cin.get() and cin.getline() problem

Started by
11 comments, last by Aardvajk 15 years, 7 months ago
Hi. I need some help to understand what's going on with these codes. I have a problem with cin.get() and cin.getline(). First Code I used cin.getline() and on the Second Code I used cin.get(). First Code:

#include <iostream>
int main()
{
using namespace std;
const int ArSize = 20;
char name[ArSize];
char dessert[ArSize];
cout << "Enter your name:\n";
cin.getline(name, ArSize); // reads through newline
cout << "Enter your favorite dessert:\n";
cin.getline(dessert, ArSize);
cout << "I have some delicious " << dessert;
cout << " for you, " << name << ".\n";
system("PAUSE");
return 0;
}



Result: Enter your name: Levi Enter your favorite dessert: Leche Flan I have some delicious Leche Flan for you, Levi. Press any key to continue... Second Code:

#include <iostream>
int main()
{
using namespace std;
const int ArSize = 20;
char name[ArSize];
char dessert[ArSize];
cout << "Enter your name:\n";
cin.get(name, ArSize); // reads through newline
cout << "Enter your favorite dessert:\n";
cin.get(dessert, ArSize);
cout << "I have some delicious " << dessert;
cout << " for you, " << name << ".\n";
system("PAUSE");
return 0;
}



Result: Enter your name: Levi I have some delicious for you, Levi. Press any key to continue... My Question is what happened in the 2nd code? Why didn't it ask me for my favorite dessert? In the book I'm reading it says I should add an extra cin.get() for it to work. But what I want to know is what really happened not just how to fix it. Thank you.
Advertisement
Quote:Source
istream& get (char* s, streamsize n );
Extracts characters from the stream and stores them as a c-string into the array beginning at s. Characters are extracted until either (n - 1) characters have been extracted or the delimiting character '\n' is found. The extraction also stops if the end of file is reached in the input sequence or if an error occurs during the input operation.

If the delimiting character is found, it is not extracted from the input sequence and remains as the next character to be extracted. Use getline if you want this character to be extracted (and discarded).

The ending null character that signals the end of a c-string is automatically appended at the end of the content stored in s.


Emphasis mine.
cin.get() doesn't do exactly what you think it does. It retrieves the specified number of characters from the input stream and if that happens to be empty, the user is prompted to enter something. What basically happens here is that there's still some characters left in the input stream (cin) after you've read the users name. These can be discarded with the ignore() function (cin.ignore()), which would solve your problem.

However, since you're programming in C++, consider using std::string's instead of char arrays and stream operators instead of get functions:

#include <iostream>#include <string>using namespace std;int main(){   string name;   string dessert;   cout << "Enter your name:\n";   cin >> name;   cout << "Enter your favorite dessert:\n";   cin >> dessert;   cout << "I have some delicious " << dessert;   cout << " for you, " << name << ".\n";   system("PAUSE");   return 0;}
Create-ivity - a game development blog Mouseover for more information.
Ok I have tried something to see what really is going on. Here's the code.

#include <iostream>using namespace std;int main(){   const int size = 5;   char name[size];   char name2[size];   cout << "What is your name?" << endl;   cin.get( name, size );   cout << name << endl;   cin.get( name2, size );   cout << name2 << endl;   system("PAUSE");   return 0;}


Result:
What is your name?
Levistus
Levi
stus
Press any key to continue...

I used cin.get() and the first name can only take 5 right? So the leftovers went to name2. Then in my first post, what happened in my code 2 in the dessert part? I had a 20 limit. What got sent to dessert automatically? If theres something left behind when using cin.get() then why not just always use cin.getline()?

Thanks for answering. I just want everything clear.
Going with std:.string would really help you here, it would simplify a lot.

I believe what was left is the stream was '\0', since cin.get() doesn't extract/discard this character (see rip-off's post). So on the next call of cin.get(), it reads from 0 to the next '\0'. Seeing there is still a '\0' left from the last call, cin extracts absolutely nothing.


Use std::string, it makes things easier. Also, instead of using cin.get(), I recommend using getline( std::stream&, std::string& ).


#include <iostream>#include <string>int main(){using namespace std;string name;string dessert;cout << "Enter your name:\n";getline(cin, name); // reads one line from cin and discards itcout << "Enter your favorite dessert:\n";getline(cin, dessert);cout << "I have some delicious " << dessert;cout << " for you, " << name << ".\n";system("PAUSE");return 0;}
Quote:Original post by c4c0d3m0n
Going with std:.string would really help you here, it would simplify a lot.

I believe what was left is the stream was '\0', since cin.get() doesn't extract/discard this character (see rip-off's post). So on the next call of cin.get(), it reads from 0 to the next '\0'. Seeing there is still a '\0' left from the last call, cin extracts absolutely nothing.


Use std::string, it makes things easier. Also, instead of using cin.get(), I recommend using getline( std::stream&, std::string& ).


*** Source Snippet Removed ***


Ok thanks. It's just that I'm following the book maybe I'll get to strings someday and I wanted more than 1 word so I used cin.get(). Thanks guys you can close this now I understand now. God Bless.
Quote:Original post by c4c0d3m0n
Going with std:.string would really help you here, it would simplify a lot.

I believe what was left is the stream was '\0', since cin.get() doesn't extract/discard this character (see rip-off's post). So on the next call of cin.get(), it reads from 0 to the next '\0'. Seeing there is still a '\0' left from the last call, cin extracts absolutely nothing.


'\n' (a return character), not '\0' (a null terminator). std::cin doesn't normally ever contain any \0's because there isn't a decent way to type them.

What happens is, cin.get(name, ArSize) reads 'Levistus' into name, adds a '\0' after those 8 characters, and leaves the '\n' on the stream. Then cin.get(dessert, ArSize) sees the '\n' right at the start of the stream, so it does exactly what it is told - reads '' into dessert, adds a '\0' after those 0 characters, and leaves the '\n' on the stream.

Anyway, "following a book" is usually a bad way to learn a language; working with std::string is easier than all this nonsense, and the fact that your book has you work through any of it (let alone start off with it!) is a sign that it is very much out of date.
Quote:Original post by Zahlman
Quote:Original post by c4c0d3m0n
Going with std:.string would really help you here, it would simplify a lot.

I believe what was left is the stream was '\0', since cin.get() doesn't extract/discard this character (see rip-off's post). So on the next call of cin.get(), it reads from 0 to the next '\0'. Seeing there is still a '\0' left from the last call, cin extracts absolutely nothing.


'\n' (a return character), not '\0' (a null terminator). std::cin doesn't normally ever contain any \0's because there isn't a decent way to type them.

What happens is, cin.get(name, ArSize) reads 'Levistus' into name, adds a '\0' after those 8 characters, and leaves the '\n' on the stream. Then cin.get(dessert, ArSize) sees the '\n' right at the start of the stream, so it does exactly what it is told - reads '' into dessert, adds a '\0' after those 0 characters, and leaves the '\n' on the stream.

Anyway, "following a book" is usually a bad way to learn a language; working with std::string is easier than all this nonsense, and the fact that your book has you work through any of it (let alone start off with it!) is a sign that it is very much out of date.


The book I'm reading is C++ Primer Plus 5th Edition by Stephen Prata, Sams Publishing (2005). The reviews about this book seems really good so I got it. Maybe you can recommend me a more recent book. Thanks.

Quote: The book I'm reading is C++ Primer Plus 5th Edition by Stephen Prata, Sams Publishing (2005). The reviews about this book seems really good so I got it. Maybe you can recommend me a more recent book.
I thought Prata’s book deals with std::string. Maybe it’s a bit later in the book.

If you want a good set of books. Accelerated C++ by Koenig and C++ Primer (not Prata’s Primer Plus), 4th Edition, by Lippman. The first one if you don’t want to get both.
Ok I have researched for an alternative to cin.get/getline that can store words with whitespaces and also to be able to use strings. Here's my new code:

#include <iostream>#include <string>using namespace std;int main(){      string name;   string dessert;   cout << "Enter your name:\n";   getline(cin, name);   cout << "Enter your favorite dessert:\n";   getline(cin, dessert);   cout << "I have some delicious " << dessert;   cout << " for you, " << name << ".\n";   system("PAUSE");   return 0;}


Result:
Enter your name:
Leche Flan Monster
Enter your favorite dessert:
Leche Flan
I have some delicious Leche Flan for you, Leche Flan Monster.

Yea! it worked! Now I ask if there is another better alternative to what im trying to do? Or is getline(not cin.getline) the best? I just want to be able to print on the screen words with spaces. Thanks guys.

This topic is closed to new replies.

Advertisement