0

I am a little new to C++ and would really appreciate any input or suggestions! So with our intro course projects I have been looking for a way to ensure that when the prog. is asking for int values it correctly responds! That is it states its invalid in cases of both a double as well as string being entered! So if cin >> intVariable ... intVariable will not accept cin entry of "abdf" or 20.01.

So to achieve this I wrote the following function...It works but I am looking for your thoughts on how this process can be further improved!

void getIntegerOnly(int& intVariable, string coutStatement)
{
    bool isInteger; // Check if value entered by user is int form or not
    string tmpValue; // Variable to store temp value enetered by user

    cout << coutStatement; // Output the msg for the cin statement 

    do
    {
        cin >> tmpValue; // Ask user to input their value

        try // Use try to catch any exception caused by what user enetered
        {
            /* Ex. if user enters 20.01 then the if statement converts the 
            string to a form of int anf float to compare. that is int value
            will be 20 and float will be 20.01. And if values do not match 
            then user input is not integer else it is. Keep looping untill 
            user enters a proper int value. Exception is 20 = 20.00      */
            if (stoi(tmpValue) != stof(tmpValue))  
            {
                isInteger = false; // Set to false!
                clear_response(); // Clear response to state invalid
            }
            else
            {
                isInteger = true; //Set to true!
                clear_cin(); // Clear cin to ignore all text and space in cin!
            }
        }
        catch (...) // If the exception is trigured!
        {
            isInteger = false; // Set to false!
            clear_response(); // Clear response to state invalid
        }

    } while (!isInteger); //Request user to input untill int clause met

    //Store the int value to the variable passed by reference
    intVariable = stoi(tmpValue); 
}

This is simply an example of getting users age and age is greater than zero when running a Win32 console based application! Thank you for the feedback :)

rakesh219
  • 42
  • 9
  • You could search the string for the '.' character. – mbadawi23 Nov 06 '14 at 00:34
  • Please could you change your C++ tag to C++11 in case you are using so? – ha9u63a7 Nov 06 '14 at 00:37
  • Except for the fact that a user might be 3000+ years old, your code should be fine. – Marco A. Nov 06 '14 at 00:39
  • @hagubear: What indicates that the user may be using C++11? – Evan Carslake Nov 06 '14 at 00:41
  • @rekesh219: You want to stay away from stoi, stof etc... They are not portable or standard. – Evan Carslake Nov 06 '14 at 00:42
  • @rakesh219, do you want the code to work with input such as "20.00"? – bialpio Nov 06 '14 at 00:53
  • [You can use a facet to change the formatting rules of your stream.](http://rextester.com/live/IXHJT77973) Of course, this doesn't beat actually parsing it as a string yourself. For example, the facet can't tell if `.` is a decimal point or a period separating sentences. – David G Nov 06 '14 at 00:57
  • @EvanCarslake They are both [portable and standard](http://en.cppreference.com/w/cpp/string/basic_string/stol), assuming the library has implemented them. – user657267 Nov 06 '14 at 01:03
  • @πάνταῥεῖ I'm not sure the duplicate answers this, a stream will not fail when attempting to read "123.12" into an `int`, it'll just stop at `.`. – user657267 Nov 06 '14 at 01:06
  • Thank you for the updates! I removed the c++ tag as requested. – rakesh219 Nov 06 '14 at 16:24
  • @Evan is there a function that performs the same as stoi()/stof() but is standard? Or should I define my own functions to do that? – rakesh219 Nov 06 '14 at 16:24
  • @bialpio No I think it is fair to assume that 20.00 = 20 and hence should be allowed as valid entry. – rakesh219 Nov 06 '14 at 16:29
  • @mbadawi23 Ahhh i see so replace the stoi(tmpValue) != stof(tmpValue) with the find '.' character syntax and placing the cin line within the try....both of which will fire an exception. but then how would you convert the string to int? – rakesh219 Nov 06 '14 at 16:31
  • @rakesh219, I don't know why you want to throw exceptions, but what I had in mind is that you search for the dot like so `int found = tempValue.find('.');` and `if (found > -1) isInteger = true; else isInteger = false;`. In one statement: `if (tempValue.find('.') > -1) isInteger = true; else isInteger = false;` – mbadawi23 Nov 06 '14 at 23:17

3 Answers3

1

One way would be something like the following:

std::string str;
std::cin >> str;
bool are_digits = std::all_of(
  str.begin(), str.end(), 
  [](char c) { return isdigit(static_cast<unsigned char>(c)); }
);

return are_digits ? std::stoi(str) : throw std::invalid_argument{"Invalid input"};

and catch the exceptions on the calling side (stoi can also throw std::out_of_range).

user657267
  • 20,568
  • 5
  • 58
  • 77
  • Assuming that he is using C++11, this solution will work. std::all_of is a very C++11 thingy. very helpful though :) – ha9u63a7 Nov 06 '14 at 00:37
  • 1
    @hagubear well he is already using `std::stoi`. – user657267 Nov 06 '14 at 00:39
  • It will not work for hex input. – bialpio Nov 06 '14 at 00:39
  • 1
    @bialpio As far as I can tell OP isn't interested in hex input (will not accept cin entry of "abdf"). – user657267 Nov 06 '14 at 00:44
  • @user657267 Thank you! This looks way more compact than what i wrote! And you are right I am not looking for hex input to be valid. Let me understand the code you provided and I will come back to accept your response :) – rakesh219 Nov 06 '14 at 16:39
0

You can leverage the second parameter of stoi().

string tmpValue;
size_t readChars;
stoi(tmpValue, &readChars);
if(readChars == tmpValue.length())
{
   // input was integer
}

EDIT: this will not work for strings containing "." (for example integers passed in scientific notation).

bialpio
  • 1,004
  • 7
  • 17
-2

This is not my work, but the answer to this question is what you want. Pass the string to it as a reference. It will return true is your string is an integer.

How do I check if a C++ string is an int?

Community
  • 1
  • 1
Evan Carslake
  • 2,267
  • 15
  • 38
  • 56