Member Avatar for nicolap

Hi,

I'm working on a C++ project and in a menu I want the user to choose 1, 2, 3 etc... integer number.

If they input a float i.e. 1.2
I want the code to tell them they've entered something invalid, rather than just rounding it down to 1.

how do I do this?

Actually you should check the input on being a valid integer or not :)

To check whether the input is an integer or not, you could do something like this (you'll have to pass the input as a string):

bool checkInt(const string &s)
{
	int len = s.length();
	for(int i=0; i<len; i++)
		if(!isdigit(s[i])) return false;
	return true;
}

TIP: Read your input (the number/integer) as a string, pass it to this function, if this function returns true , convert the number to an integer (you could use stringstreams ) :)

/// fast int test (except possible overflow)
bool isInt(const std::string& s)
{
    static const size_t npos = std::string::npos;
    static const std::string digits("0123456789");
    size_t pos = s.find_first_not_of(" \t");
    bool res = pos != npos;
    if (res) {
        if (s[pos] == '+' || s[pos] == '-')
            pos++;
        res = (pos < s.size()
            && s.find_first_not_of(digits,pos) == npos);
    }
    return res;
}
commented: Lol, I forgot to handle the signs also :) Good job ArkM !! +3

here is another solution

double input;
int test;
cout << "Please enter an integer: ";
cin >> input;
test = input;
if (test != input)
{
       cout << you did not enter an integer.";
}

basicaly what you are doing is let the number come in as a double then store it into the int test. if the number is a float then test will be rounded and the resualting if statement will be true and then you will know. hope this helps

commented: Very nice :) !!! +3
commented: Never compare two floats -1
commented: this is not a solution, and should not be green. +8

Dear NathanOliver, your code is working perfectly after changing cout << you did not enter an integer."; to cout << [B][I]"[/I][/B]you did not enter an integer."; :)

Edit:: Some additional information on if (test != input) as 'input' is a double and 'test' is an integer, 'test' will be implicitly converted to a double to do comparison :)

>>Dear NathanOliver, your code is working perfectly after changing..............
It may be working on your implementation but the code is in a state of undefined behavior.

>>Edit:: Some additional information on if (test != input) as 'input' is a double
>>and 'test' is an integer, 'test' will be implicitly converted to a double to do
>>comparison
This can't get worst. When you know he is doing a float comparison, there is a lot more need to warn him than smiling.
To OP and everyone : Never use float comparison in your programs. It will lead to undefined behavior.
You may want to like to read: http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.17

commented: Very interesting :) !!! +3

thank you tux4life for your input i i realized the typo after i submitted the reply and as for the conversion to a double in the if() statement i knew that would happen but so far it was a quick and dirty way to test. i guess the best way for testing that i have found is placing the input into a string then converting. or you could use cin.getline(ch,20,"."); to test and see if there is a decimalpoint in the response.

>>Dear NathanOliver, your code is working perfectly after changing..............
It may be working on your implementation but the code is in a state of undefined behavior.

How so?

>>Edit:: Some additional information on if (test != input) as 'input' is a double
>>and 'test' is an integer, 'test' will be implicitly converted to a double to do
>>comparison
This can't get worst. When you know he is doing a float comparison, there is a lot more need to warn him than smiling.
To OP and everyone : Never use float comparison in your programs. It will lead to undefined behavior.
You may want to like to read: http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.17

Unfortunately, you do not understand the term "undefined behavior". It has a specific definition. Do a search to learn that definition. What we have here is a "logic error". You will also note that the term "undefined behavior" does not appear in the link you posted at all.

Undefined Behaviour as per Scot Mayers;

For a variety of reasons, the behavior of some constructs in C++ is literally not defined: you can't reliably predict what will happen at runtime. To emphasize that the results of undefined behavior are not predictable and may be very unpleasant, experienced C++ programmers often say that programs with undefined behavior can erase your hard drive. It's true: a program with undefined behavior could erase your hard drive. But it's not probable. More likely is that the program will behave erratically, sometimes running normally, other times crashing, still other times producing incorrect results.

This tells me that the snippet posted on post #4 is in state of undefined behavior by using float comparison.


>>How so?
Good point. You may be right. As I may be over cautioning the programmer about float comparison. But consider this:
Lets say the user inputs 5.00000001. Hence input=5.00000001 Then test=5.0 Now it is perfectly undefined that test==float

It's a rather strange thought that the C++ language defines built-in bool operator==(double,double) which inevitably leads to undefined behaviour. Yes, the language standard does not define an exact correspondence between floating-point values and mathematical abstraction of real numbers (it's impossible, of course). It's an implementation-defined issue. So the program (try this)

double x = 0.0, d = 0.1;
    for (size_t i = 0; i < 10; ++i)
        x += d;
    if (x == 1.0)
        cout << "OK: 10*0.1 = 1.0\n";
    else
        cout << "Oops! 1.0-0.1*10 == " << 1.0-x << endl;

is well-formed and has absolutely predictable effect in every concrete C++ implementation.

It's the other story that (probably) the only "safe" (better "portable" or "pragmatically useful") usage of operator==(double,double) is

if (dblvar == 0.0) ...

It's computational mathematics, not a language...

>>It's a rather strange thought that the C++ language defines built-in bool
>>operator==(double,double) which inevitably leads to undefined behaviour.
As a side note, I was just wondering if I could somehow overload operator--(double,double) so that it could just throw me an exception-" Error/Warning, you are using floating point comparisoin" LO L :D

>>It's a rather strange thought that the C++ language defines built-in bool
>>operator==(double,double) which inevitably leads to undefined behaviour.
As a side note, I was just wondering if I could somehow overload operator--(double,double) so that it could just throw me an exception-" Error/Warning, you are using floating point comparisoin" LO L :D

I have much more informative message from VC++ in that case:
operator ==' must have at least one formal parameter of class type ;)
Yes, good compilers print warning on eq op of doubles. Why? See my post above ;)

would a better way for testing if the float exsist be have have the input recived by a float the raounding it up or down to make the comparision but the then i guess that even it the user entered 5 you could still get 5.00000001 and then all will be lost and you will truly have undefined behavior going on. so lets just stick to strings and we can realy tell what the user has entered.

>would a better way for testing if the float exsist ...
What do these words stand for? The OP problem solution: see my 1st post in the thread.
Undefined behavior term does not bear a relation to OP question.

1.3.13
undefined behavior
behavior, such as might arise upon use of an erroneous program construct or erroneous data, for which this International Standard imposes no requirements. Undefined behavior may also be expected when this International Standard omits the description of any explicit definition of behavior.
Note: permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed. —end note
1.3.14
unspecified behavior
behavior, for a well-formed program construct and correct data, that depends on the implementation. The implementation is not required to document which behavior occurs.
Note: usually, the range of possible behaviors is delineated by this International Standard. —end note

User input processing is an example of a very "well-defined" in the C++ Standard program behavior... ;)

i just had a thought and i though that i would at least give it one more shoot. if it is truly a no no to test for floats instead of an integer input then so be it. with that out of the way here it is tell me what you think

#include <iostream>
#include <string>
#include <stdlib.h>

using namespace std;

int main()
{
	int number;
	string input;;
	cout << "Please enter an integer: ";
	cin >> input;
	int size  = input.size();
	char * temp = new char[size + 1];	// array to copy the string into for conversion
	for (int i = 0; i < size; i++)
	{
		if ((input[i] == 46) && (i < size - 1))	// makes sure that there is information
		{									// after the decimal point. 46 means "." in ascii
			cout << "you did not enter an integer.\n";  
			return 0;	// you can place anything here but this works for this application
		}
		temp[i] = input[i];	// asigns the string to a char for conversion to an int
	}
	number =  atoi(temp);
	cout << "I got " << number << "\n";
	return 0;
}

>>i just had a thought and i though that i would at least give it one more shoot. if it
>>is truly a no no to test for floats instead of an integer input then so be it. with that
>>out of the way here it is tell me what you think
I think the code you just posted is junk. Seriously, it may work ( I have not tested) but it is Non-standard [ string::size returns size_t ], cruel [you are unnecessarily using cstrings ], untidy and too complicated for a simple process like this.
You may ignore my comments and continue to work as you wish, but this will surly lead you nowhere.

ArkM has posted a decent solution (post#3). Try to learn from it.

As side notes:
1. Line 10 is ended with two semicolons . Syntactically right but ........
2. The standard library for <stdlib.h> is actually <cstdlib>
3. Rather than using 46 use '.' which is more readable.

It's perfectly acceptable to compare floats. You just have to understand the difficulties and know how to deal with them.

Because floating point is not exact, you need to define what precision is acceptable. If you want a .01 variance, simply test for it:

if ((inputValue > targetVal - 0.01) && 
    (inputValue < targetVal + 0.01))
{

Now if you input 5.0 and you get 5.00000001 your comparison works fine.

commented: Very simple and effective solution :) +3

>>It's perfectly acceptable to compare floats. You just have to understand the
>>difficulties and know how to deal with them.
Good. I mean you are right.


>>Now if you input 5.0 and you get 5.00000001 your comparison works fine.
A you see, if now I put inputValue =5.0 and targetVal=5.0, your posted snippet tells me that they are not equal.
What say?
Actually. You are right in saying that we can trade off by getting the result in a desired range. This is the next best thing one can get.

I wouldn't call the problem of comparing floating point values for equality "undefined". There's a pretty clear definition of what happens - the two values are compared returning a boolean value.

I would describe the procedure as "unreliable", in that two values which may be (ought to be) the same might differ in the lowest order digit, owing to the means of storing floating point values.

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.