User Input: Strings and Numbers [C++]

John A 11 Tallied Votes 7K Views Share

User input/output is a key component in the programs you write, yet most online tutorials just provide a quick-and-dirty method of grabbing data. In other words, it works right up until the point the user does something unexpected.

In this tutorial you will learn how to avoid the common mistakes by doing it properly.

Take this typical method that tutorials use to teach user input:

int number;
cin >> number;
cout << "You typed the number " << number << ".\n";

Now let's say you want the user to enter a string that contains a space in it. Since using cin >> myString won't work (it will only grab the first word and then exit), you decide you need to find a function that will grab a whole line of input.

After some Googling, you decide that getline() is probably the best way to do it. You add it to your existing code, and this is how your entire program looks:

#include <iostream>
#include <string>
using namespace std;

int main() {
    
    int number;
    string name;
    
    cout << "Please enter a number." << endl;
    cin >> number;
    cout << "Enter your entire name (first and last)." << endl;
    getline(cin, name);
    
    cout << "Your full name is " << name 
         << ", and the number you entered is " << number << endl;
    return 0;
}

Now you run it and the program totally skips the getline() statement!

Please enter a number.
5
Enter your entire name (first and last).
Your full name is , and the number you entered is 5

That's rather odd. Let's try using only getline for our input (which means the number will be put into a string instead):

#include <iostream>
#include <string>
using namespace std;

int main() {
    
    string number;
    string name;
    
    cout << "Please enter a number." << endl;
    getline(cin, number);
    cout << "Enter your entire name (first and last)." << endl;
    getline(cin, name);
    
    cout << "Your full name is " << name
         << ", and the number you entered is " << number << endl;
    return 0;
}

The program's output being:

Please enter a number.
5
Enter your entire name (first and last).
 Joe Programmer
Your full name is Joe Programmer, and the number you entered is 5

The problem went away.

You will probably suspect something is up with cin and are right. What's actually happening in the first example is:

  1. You enter something in.
  2. You hit return.
  3. All of this is put into the input buffer (including the newline that results from hitting return).
  4. cin grabs whatever it needs (in this case the number), but leaves the newline behind!
  5. Since getline() only grabs 1 line, all it gets is the newline left behind by cin .

To fix this the best approach, although not that easy for newbies, is to avoid the use of cin until you know what you're doing, and let getline() handle your user input. It not only solves the newline problem, but it also solves a number of other problems induced by using cin .

This is relatively easy for people to do until they get to numbers (which usually can't be read into strings because they need to be manipulated). For this, you can use a stringstream to convert the string back into a number:

#include <iostream>
#include <string>
#include <sstream> // need this for stringstreams!
using namespace std;

int main() {
    
    int number;
    string line;
    stringstream stream;
    
    cout << "Please enter a number." << endl;
    getline(cin, line);
    
    stream << line;
    stream >> number;
    cout << "The number entered was " << number << ".\n";
    
    return 0;
}

This outputs:

Please enter a number.
4
The number entered was 4.

You can now see how the operation is nearly identical, except that you are taking an extra step by first putting the input a string, and then putting it into a separate stream before popping it back out in the number.

Finally, you actually can mix cin with getline() , if you know what you are doing. The easiest method is to use cin.ignore([I]<some large number>[/I], '\n') to clear the input buffer. You could simply hard code a large number, although it's usually better to use a built-in constant. The Standard Template Library provides such a constant, which is found in the <limits> header: numeric_limits<streamsize>::max() If you were to implement this in your first example, it would work like this:

#include <iostream>
#include <string>
#include <limits>
using namespace std;

int main() {
    
    int number;
    string name;
    
    cout << "Please enter a number." << endl;
    cin >> number;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    cout << "Enter your entire name (first and last)." << endl;
    getline(cin, name);
    
    cout << "Your full name is " << name
         << ", and the number you entered is " << number << endl;
    return 0;
}

And the output would be:

Please enter a number.
3
Enter your entire name (first and last).
Joe Programmer
Your full name is Joe Programmer, and the number you entered is 3

However, this should only be used when absolutely necessary, as this is just a band-aid for the function. It doesn't really fix some of the other problems that come with using it. So perhaps it is best to stick with getline() . Don't do the quick-and-dirty method that online tutorials teach you, because it will eventually come back and bite you in the back of the neck. Flushing the input buffer like mentioned previously is only a last resort for using cin ; it's not a good alternative to using getline() to handle your input. A little bit of trouble now using getline() will save you a lot of pain later!

Update: Narue has written a nice tutorial showing how to clear the input buffer and all the problems associated with doing so: How do I flush the input stream?

Dani 4,329 The Queen of DaniWeb Administrator Featured Poster Premium Member

Can you explain what cin.ignore actually does, and why we need to specify some randomly large number? Is there no command to just clear the input buffer of the newline character?

John A 1,896 Vampirical Lurker Team Colleague

>Can you explain what cin.ignore actually does
cin.ignore basically ignores (another way of saying 'trashes') characters from the input buffer.

>why we need to specify some randomly large number?
That number is the maximum number of characters that cin.ignore trashes before it encounters a newline character. Theroretically, you would only need 1 to trash a newline, but you never know what else is sitting in the buffer, and this is a pretty safe way of emptying it.

>Is there no command to just clear the input buffer of the newline character?
You could simply use cin.get() to manually remove character-by-character from the input buffer, like this:

int ch;  // notice that this is int, not char, so it can hold larger values
         // (in case we get some crazy values from the input buffer)
while ((ch = cin.get()) != '\n' && ch != EOF);

This method isn't as reliable for clearing the input buffer though, so it's better to stick with cin.ignore().

Additionally, it's a good idea to call cin.clear() before clearing the input buffer, because what cin.clear does is erase any bad bits (errors) that have occured. If there are errors that haven't been cleared, you can't do read (or clear) the input buffer.

~s.o.s~ 2,560 Failure as a human Team Colleague Featured Poster

Coding the tutorial with the magic number given to ignore function would not be such a good idea.

Either declare the constant at the start of the program, in a header file or better yet use inbuilt constants like max value provided in the limits header file.

Another robust method for accepting a integer worth incorporating in your tutorial is:

int main()
{
    int x;
    char ch;
    std::string myString;
    while (getline ( cin, myString ))
    {
        std::istringstream strin(myString);
        strin >> x;
        if (!strin)
            cout << "Bad input" << endl;
        else if ( strin >> ch )
            cout << "Bad input" << endl;
        else
            cout << "You entered: " << x << endl;
    }
    getchar ();
    return 0;
}

Hope, it made sense, bye.

John A 1,896 Vampirical Lurker Team Colleague

>Coding the tutorial with the magic number given to ignore function would not be such a good idea.

Well, I know that it's far better to use something like this,

std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

but I didn't want to scare newbies with a long chunk of code, when I was simply trying to demonstrate clearing the input buffer. But if you think it should be changed, I can get Davey to edit it...

>Another robust method for accepting a integer worth incorporating in your tutorial is:
I wanted to keep the tutorial relatively simple, so I didn't really cover input validation. I'm considering writing some code snippets that would accomodate this (and perhaps link to it at the end of the tutorial, much like Dave Sinkula did in his excellent C input tutorial).

~s.o.s~, thank you very much for your suggestions...

~s.o.s~ 2,560 Failure as a human Team Colleague Featured Poster

Considering that you have already declared using namespace std at the top of your code, the complicated statement becomes cin.ignore(numeric_limits<streamsize>::max(), '\n') ;

Not so complicated, is it ? ;) But even so please make the changes since we want publication quality tutorials and we don't need the magic numbers to mar that.

> I wanted to keep the tutorial relatively simple, so I didn't really cover input validation.
No problem as such, include the code which I pasted whenever you think its appropriate. Just wanted to let you know.

And last but not the least, really good tutorial. I am waiting for the next one in the series... ;)

John A 1,896 Vampirical Lurker Team Colleague

>Not so complicated, is it ?
Well, I was kind of trying to exaggerate the effect of using that statement by adding the std:: prefix to make my point... ;)

>But even so please make the changes since we want publication quality tutorials and we don't need the magic numbers to mar that.
Alrighty then, I'll make some modifications, and then send them to Davey for approval.

>And last but not the least, really good tutorial.
Thank you!

>I am waiting for the next one in the series...
When I have some more time I'll get around to it...

WXuan 0 Newbie Poster

Read the content, I realized that the convinence of the function getline().
I have been using the following method to process input containing number and string.

#include<iostream>
#include<string>
using namespace std;
int main()
{
int number;
string str,remainder;
cout<<"Please enter a number:"<<endl;
cin>>number;
getline(cin,remainder);
getline(cin,str);
cout<<"The string you entered is "<<str<<", and the number you entered is "<<number<<endl;
return 0;
}

grisha83 26 Junior Poster in Training

It would be nice if you talked about the possible manipulations that we could do with strings.
Thank you

abhijitm 0 Newbie Poster

Hi ,

Not sure if you guys are not considering "fflush" on purpose , but you can even use to fflush the console buffer before getting the line to fflush the "Enter" which is present in the buffer after entering the number.
I am modifying the original piece of code and presenting it below

#include <iostream>
#include <conio.h>
using namespace std;

int main() {
    
    int number;
    string name;
    
    cout << "Please enter a number." << endl;
    cin >> number;
    cout << "Enter your entire name (first and last)." << endl;
    fflush(stdin);
    getline(cin, name);
    
    cout << "Your full name is " << name 
         << ", and the number you entered is " << number << endl;
         
    getch() ; // to hold the output screen
    return 0;
}

The output is
Please enter a number.
4
Enter your entire name (first and last).
Abhijit Mehta
Your full name is Abhijit Mehta, and the number you entered is 4

John A 1,896 Vampirical Lurker Team Colleague

>Not sure if you guys are not considering "fflush" on purpose
Actually, yes... http://www.gidnetwork.com/b-57.html

V.V.Raman -7 Newbie Poster

My question is regarding he use of numeric_limits<streamsize>::max().
I found that this compiled in the command line using the C++ command in Bloodshed Dev-C++. However, when I tried to compile this code in a console project in Visual C++ 6.0, I was successful only after including headers for <stream> and <limits>. Why this difference?
Raman

John A 1,896 Vampirical Lurker Team Colleague

>Why this difference?
Well, first of all, Visual C++ 6.0 is a fairly old compiler and doesn't really conform to proper C++ standards. You should really get a newer compiler (Try the Express edition of Visual Studio 2008).

Second, some compilers' headers include other headers, some don't. In this case, because I was using the STL objects string, stringstream, cout, numeric_limits<T>, it means I should have also included the following headers in the code:

#include <string>
#include <limits>

Those headers are included by default from iostream in gcc. But you are correct, I should update the tutorial.

V.V.Raman -7 Newbie Poster

>Why this difference?
Well, first of all, Visual C++ 6.0 is a fairly old compiler and doesn't really conform to proper C++ standards. You should really get a newer compiler (Try the Express edition of Visual Studio 2008).

Second, some compilers' headers include other headers, some don't. In this case, because I was using the STL objects string, stringstream, cout, numeric_limits<T>, it means I should have also included the following headers in the code:

#include <string>
#include <limits>

Those headers are included by default from iostream in gcc. But you are correct, I should update the tutorial.

Thank you for the explanation, John.
Raman

bemboysms 0 Newbie Poster

are the codes used in the c++ programming same with the dev-c++ programming, coz im using the latter, and will you give me the list of header files and their use and algorithms, i am a fully first time programmer, thanks

hiyas 0 Newbie Poster

God Bless

wyujack 0 Newbie Poster

User input/output is a key component in the programs you write, yet most online tutorials just provide a quick-and-dirty method of grabbing data. In other words, it works right up until the point the user does something unexpected.

In this tutorial you will learn how to avoid the common mistakes by doing it properly.

Take this typical method that tutorials use to teach user input:

int number;
cin >> number;
cout << "You typed the number " << number << ".\n";

Now let's say you want the user to enter a string that contains a space in it. Since using cin >> myString won't work (it will only grab the first word and then exit), you decide you need to find a function that will grab a whole line of input.

After some Googling, you decide that getline() is probably the best way to do it. You add it to your existing code, and this is how your entire program looks:

#include <iostream>
#include <string>
using namespace std;

int main() {
    
    int number;
    string name;
    
    cout << "Please enter a number." << endl;
    cin >> number;
    cout << "Enter your entire name (first and last)." << endl;
    getline(cin, name);
    
    cout << "Your full name is " << name 
         << ", and the number you entered is " << number << endl;
    return 0;
}

Now you run it and the program totally skips the getline() statement!

Please enter a number.
5
Enter your entire name (first and last).
Your full name is , and the number you entered is 5

That's rather odd. Let's try using only getline for our input (which means the number will be put into a string instead):

#include <iostream>
#include <string>
using namespace std;

int main() {
    
    string number;
    string name;
    
    cout << "Please enter a number." << endl;
    getline(cin, number);
    cout << "Enter your entire name (first and last)." << endl;
    getline(cin, name);
    
    cout << "Your full name is " << name
         << ", and the number you entered is " << number << endl;
    return 0;
}

The program's output being:

Please enter a number.
5
Enter your entire name (first and last).
 Joe Programmer
Your full name is Joe Programmer, and the number you entered is 5

The problem went away.

You will probably suspect something is up with cin and are right. What's actually happening in the first example is:

  1. You enter something in.
  2. You hit return.
  3. All of this is put into the input buffer (including the newline that results from hitting return).
  4. cin grabs whatever it needs (in this case the number), but leaves the newline behind!
  5. Since getline() only grabs 1 line, all it gets is the newline left behind by cin .

To fix this the best approach, although not that easy for newbies, is to avoid the use of cin until you know what you're doing, and let getline() handle your user input. It not only solves the newline problem, but it also solves a number of other problems induced by using cin .

This is relatively easy for people to do until they get to numbers (which usually can't be read into strings because they need to be manipulated). For this, you can use a stringstream to convert the string back into a number:

#include <iostream>
#include <string>
#include <sstream> // need this for stringstreams!
using namespace std;

int main() {
    
    int number;
    string line;
    stringstream stream;
    
    cout << "Please enter a number." << endl;
    getline(cin, line);
    
    stream << line;
    stream >> number;
    cout << "The number entered was " << number << ".\n";
    
    return 0;
}

This outputs:

Please enter a number.
4
The number entered was 4.

You can now see how the operation is nearly identical, except that you are taking an extra step by first putting the input a string, and then putting it into a separate stream before popping it back out in the number.

Finally, you actually can mix cin with getline() , if you know what you are doing. The easiest method is to use cin.ignore([I]<some large number>[/I], '\n') to clear the input buffer. You could simply hard code a large number, although it's usually better to use a built-in constant. The Standard Template Library provides such a constant, which is found in the <limits> header: numeric_limits<streamsize>::max() If you were to implement this in your first example, it would work like this:

#include <iostream>
#include <string>
#include <limits>
using namespace std;

int main() {
    
    int number;
    string name;
    
    cout << "Please enter a number." << endl;
    cin >> number;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    cout << "Enter your entire name (first and last)." << endl;
    getline(cin, name);
    
    cout << "Your full name is " << name
         << ", and the number you entered is " << number << endl;
    return 0;
}

And the output would be:

Please enter a number.
3
Enter your entire name (first and last).
Joe Programmer
Your full name is Joe Programmer, and the number you entered is 3

However, this should only be used when absolutely necessary, as this is just a band-aid for the function. It doesn't really fix some of the other problems that come with using it. So perhaps it is best to stick with getline() . Don't do the quick-and-dirty method that online tutorials teach you, because it will eventually come back and bite you in the back of the neck. Flushing the input buffer like mentioned previously is only a last resort for using cin ; it's not a good alternative to using getline() to handle your input. A little bit of trouble now using getline() will save you a lot of pain later!

Update: Narue has written a nice tutorial showing how to clear the input buffer and all the problems associated with doing so: How do I flush the input stream?

It's very usefull to me .thank you !

chaithanya07 0 Newbie Poster

why do we use scope resolution operator?? explain about it please.....

p-man 0 Newbie Poster
#include <iostream>
#include <string>



int main()
{
int number;
string str,remainder;
cout<<"Please enter a number:"<<endl;
cin>>number;
cin>>remainder>>str;

cout<<"The string you entered is "<<str<<",and the number you entered is "<<number<<endl;
int v;
cin>>v;
return 0;
}
ilyas0121 0 Newbie Poster

here is a nice tutorial on this with some more details:
http://augustcouncil.com/~tgibson/tutorial/iotips.html

Jasper_90 0 Newbie Poster

User input/output is a key component in the programs you write, yet most online tutorials just provide a quick-and-dirty method of grabbing data. In other words, it works right up until the point the user does something unexpected.

In this tutorial you will learn how to avoid the common mistakes by doing it properly.

Take this typical method that tutorials use to teach user input:

int number;
cin >> number;
cout << "You typed the number " << number << ".\n";

Now let's say you want the user to enter a string that contains a space in it. Since using cin >> myString won't work (it will only grab the first word and then exit), you decide you need to find a function that will grab a whole line of input.

After some Googling, you decide that getline() is probably the best way to do it. You add it to your existing code, and this is how your entire program looks:

#include <iostream>
#include <string>
using namespace std;

int main() {
    
    int number;
    string name;
    
    cout << "Please enter a number." << endl;
    cin >> number;
    cout << "Enter your entire name (first and last)." << endl;
    getline(cin, name);
    
    cout << "Your full name is " << name 
         << ", and the number you entered is " << number << endl;
    return 0;
}

Now you run it and the program totally skips the getline() statement!

Please enter a number.
5
Enter your entire name (first and last).
Your full name is , and the number you entered is 5

That's rather odd. Let's try using only getline for our input (which means the number will be put into a string instead):

#include <iostream>
#include <string>
using namespace std;

int main() {
    
    string number;
    string name;
    
    cout << "Please enter a number." << endl;
    getline(cin, number);
    cout << "Enter your entire name (first and last)." << endl;
    getline(cin, name);
    
    cout << "Your full name is " << name
         << ", and the number you entered is " << number << endl;
    return 0;
}

The program's output being:

Please enter a number.
5
Enter your entire name (first and last).
 Joe Programmer
Your full name is Joe Programmer, and the number you entered is 5

The problem went away.

You will probably suspect something is up with cin and are right. What's actually happening in the first example is:

  1. You enter something in.
  2. You hit return.
  3. All of this is put into the input buffer (including the newline that results from hitting return).
  4. cin grabs whatever it needs (in this case the number), but leaves the newline behind!
  5. Since getline() only grabs 1 line, all it gets is the newline left behind by cin .

To fix this the best approach, although not that easy for newbies, is to avoid the use of cin until you know what you're doing, and let getline() handle your user input. It not only solves the newline problem, but it also solves a number of other problems induced by using cin .

This is relatively easy for people to do until they get to numbers (which usually can't be read into strings because they need to be manipulated). For this, you can use a stringstream to convert the string back into a number:

#include <iostream>
#include <string>
#include <sstream> // need this for stringstreams!
using namespace std;

int main() {
    
    int number;
    string line;
    stringstream stream;
    
    cout << "Please enter a number." << endl;
    getline(cin, line);
    
    stream << line;
    stream >> number;
    cout << "The number entered was " << number << ".\n";
    
    return 0;
}

This outputs:

Please enter a number.
4
The number entered was 4.

You can now see how the operation is nearly identical, except that you are taking an extra step by first putting the input a string, and then putting it into a separate stream before popping it back out in the number.

Finally, you actually can mix cin with getline() , if you know what you are doing. The easiest method is to use cin.ignore([I]<some large number>[/I], '\n') to clear the input buffer. You could simply hard code a large number, although it's usually better to use a built-in constant. The Standard Template Library provides such a constant, which is found in the <limits> header: numeric_limits<streamsize>::max() If you were to implement this in your first example, it would work like this:

#include <iostream>
#include <string>
#include <limits>
using namespace std;

int main() {
    
    int number;
    string name;
    
    cout << "Please enter a number." << endl;
    cin >> number;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    cout << "Enter your entire name (first and last)." << endl;
    getline(cin, name);
    
    cout << "Your full name is " << name
         << ", and the number you entered is " << number << endl;
    return 0;
}

And the output would be:

Please enter a number.
3
Enter your entire name (first and last).
Joe Programmer
Your full name is Joe Programmer, and the number you entered is 3

However, this should only be used when absolutely necessary, as this is just a band-aid for the function. It doesn't really fix some of the other problems that come with using it. So perhaps it is best to stick with getline() . Don't do the quick-and-dirty method that online tutorials teach you, because it will eventually come back and bite you in the back of the neck. Flushing the input buffer like mentioned previously is only a last resort for using cin ; it's not a good alternative to using getline() to handle your input. A little bit of trouble now using getline() will save you a lot of pain later!

Update: Narue has written a nice tutorial showing how to clear the input buffer and all the problems associated with doing so: How do I flush the input stream?

=>> this is a bit different from the C++ i learn. i use "#include<stdio.h>" wonder if it is the same?? is this the newer version? or is this the older version?? oh well i hope to fine a example for a the programming that use #include<stdio.h>. it's just too much different in what i learn. complicated to comprehand now...:)

WaltP 2,905 Posting Sage w/ dash of thyme Team Colleague

That's because you didn't learn C++. You learned C. And if your instructor was really teaching C++ then you unfortunately received a very bad education. It's like taking a car repair class and all you worked on were motorcycles. After all, they have engines, too, don't they?

Bendez Thyna 0 Light Poster

nice tutorial...

Learner010 99 Posting Whiz in Training

i've declared pointer to char for getting input but i'm unable to get input using getline in this case :

char* str;
cout<<"enter string";
getline(cin,str);

its not working however i solved the issue using the following code(but i want that why the above code is not working)

string str;
cout<<"enter string";
getline(cin,str);

i want to know about this (char*) for getting input.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Your pointer doesn't point anywhere meaningful. Allocate some memory to it first. Also, there's a different getline for C-style strings that's a member function of cin.

Khawaja Ghulam 0 Newbie Poster

The basic difference between character and string can be demonstrated as we use "cin" in case of character and "getline" of "cin.get" in case of strings.The reason of using getline is that we want to input characters from the user that may include spaces,i.e.,"Hello World". "cin" cannot take such input.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.