Sign in to follow this  
Verminox

C++ Integer Input

Recommended Posts

What is the best and safest way to get integer input from a user? (For a Console App) Currently, I'm just using cin, but that is giving me a lot of trouble when I try to cin to a (int) variable, and the user inputs a non-integer character. Someone suggested I include <sstream> and use this method:
string mystring;
int myint;
getline (cin,mystring);
stringstream(mystring) >> myint;
Is that good enough or is there something better I can do to assure that the input I receive is taken as an integer?

Share this post


Link to post
Share on other sites
cin should work perfectly fine. The other method will work no better.

You simply need to do error checking after you have received input.

use the isalpha(input) function to check what the user has input. If this returns true, then the input contains characters. If its false, then it is a valid integer, and you can proceed with your program.

You can then hold your user input in a do while function:


char myInput[MAX_LENGTH];
bool validInput = false;

do{

cout << "Enter input: ";
cin >> myInput;

validInput = isInputInt(myInput);
} while (!validInput);



have your function return false if isalpha returns true. Run it through a loop checking each element of the char array for isalpha. After it passes inspection, and its a valid integer, convert it to an integer.

Share this post


Link to post
Share on other sites
The CIN function will return a true or false value as to whether or not it succeeded. If it succeeds, it will fill in the inputted value into the address of the variable.

This example makes sure the input is a valid integer.

#include <iostream>
using namespace std;

void main()
{
int j = 0;
cout << "Enter a number: ";
if(!(cin >> j))
cout << "You must enter a number!" << endl << endl;
else
cout << "You entered " << j << endl << endl;
}

Share this post


Link to post
Share on other sites
Quote:
Original post by F1N1TY
The CIN function will return a true or false value as to whether or not it succeeded. If it succeeds, it will fill in the inputted value into the address of the variable.


To be more precise, cin is not a function, it is an object (a global object, BTW) - an instance of a class which overload operator bool in order for you to be able to compile and run that code.

@Mr Safety
[quote]
char myInput[MAX_LENGTH];
cin >> myInput;
(/quote]
Hum. No. This code is subject to the classical buffer overflow attack. Use std::string instead [smile]

Regards,

Share this post


Link to post
Share on other sites
The code I posted will determine if it can place the inputted value into the variable (i.e, input can't be larger than maximum int range value).


Quote:
Original post by Emmanuel Deloget
To be more precise, cin is not a function, it is an object (a global object, BTW) - an instance of a class which overload operator bool in order for you to be able to compile and run that code.


Yeah, sorry about that...


Share this post


Link to post
Share on other sites
How would I go about using std::string for the itneger input?

Should I just use getline() to get the input into the string and then use type casting to convert it to an integer? What will happen if the input is purely text and it is casted to an integer?

Share this post


Link to post
Share on other sites
Quote:
Original post by Verminox
How would I go about using std::string for the itneger input?

Should I just use getline() to get the input into the string and then use type casting to convert it to an integer? What will happen if the input is purely text and it is casted to an integer?


You can't cast a std::string to an int. You'd have to use a stringstream or a function like std::atoi to convert it.

Using a std::string would just prevent the potential buffer overflow inherient in Mr Safety's example code.

As F1N1TY pointed out, using cin >> an_int; will return false if it can't convert the input so there shouldn't be any need to make it more complex than that.

However, if you cin to a std::string, that will accept any text and you could then use a variant of Mr Safety's approach to ensure the string contains only numbers before using a stringstream to convert it into an int variable.

Share this post


Link to post
Share on other sites
Quote:
Original post by Verminox
That is no good, isalpha() returns false even if I input punctuation marks, which aren't integers.


This is the
Actually, you should use isdigit(), not isalpha(). From the MSDN:
Quote:
isalpha returns a non-zero value if c is within the ranges A – Z or a – z.
.

Regards,

Share this post


Link to post
Share on other sites
Thinking about it, if you are going to cin to a string then use a custom function to check it is a valid number, just checking to see if everything is a digit is not going to work.

For example, "-1,234" would be a valid integer input that I assume atoi or stringstream would cope with, as well as leading or trailing whitespace.

Share this post


Link to post
Share on other sites
Thanks EasilyConfused, atoi works great. Now, I am posed with another problem.

Suppose I have:

string str;
int num = 10;


I want str to be "The number was 10.\n";

How do I do that. I tried using the + operator between const strings, but it didn't work, I tried usign sprintf() but it did not accept std::string as the first argument. Any help?

Share this post


Link to post
Share on other sites
Personally I'd do this:


std::string int_to_string(int i)
{
char b[64]; sprintf(b,"%d",i); return b;
}

void f()
{
int n=100;

std::string s="The number is "+int_to_string(n);
}



but that is a bit of an old-fashioned hack. I believe you could use an ostringstream to convert the number to a string instead and avoid the potential buffer overflow in my code above.

Share this post


Link to post
Share on other sites
I got this to work:

std::string itos(int i){
char buffer[64];
itoa(i,buffer,10);
return buffer;
}


std::itoa() is not ANSI-defined, but supported by most compilers (according to cplusplus.com).

Share this post


Link to post
Share on other sites
Quote:
Original post by Verminox
I got this to work:

std::string itos(int i){
char buffer[64];
itoa(i,buffer,10);
return buffer;
}


std::itoa() is not ANSI-defined, but supported by most compilers (according to cplusplus.com).

Why aren't you using std::stringstream?

Share this post


Link to post
Share on other sites
Do it properly:

template <typename T, typename Y> T lexical_cast(const Y& input)
{
stringstream ss; ss << input;
T t; ss >> t;
return t;
}


of course, you'll need to specialise for strings:


template<> lexical_cast<std::string, int>(const int& input)
{
stringstream ss; ss << input;
return ss.str();
}


And if partial specialisation for functions was allowed, well, things'd be so much simpler. Or just include Boost, of course, which is where I stole the idea. In my signature.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this