Thread: Input check problem with numbers

  1. #16
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Salem View Post
    I'd just like to reiterate my comment that attempting input AND conversion at the same time is just a mess waiting to happen, as already noted by several others.

    By having a consistent approach which always works, you cut down on all the surprises later on in the code.

    As for your concerns over efficiency, then consider this:
    "It is easier to make a working program efficient than it is to make an efficient program work".
    In other words, make it right first, then worry about trying to make it smaller / faster.
    I completely agree. Although the latter brings memories of someone who tried to us 127KB of "data" space on an embedded system. Our group had a limit of 128KB of memory on that system - obviously, there was a valid cause for "be a bit more efficient with the memory allocation" very early on in that particular case - as the code would absolutely not run on the target system, since the remaining 1KB was not enough to share between the other 30 or so modules that also had to go in the same memory!

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  2. #17
    Registered User
    Join Date
    Aug 2007
    Posts
    66
    You said: "I'd just like to reiterate my comment that attempting input AND conversion at the same time is just a mess waiting to happen, as already noted by several others."

    Salem, I do NOT use string and conversion in my last example. I use cin.ignore method. So, am I right ? or no ...... ?


    could you rewrite (if you have free time) my program last source code (which asks name, lastname job, phone etc) in your way?

    I want to see what I am doing wrong. Thanks guys!
    Last edited by BlackSlash12; 11-26-2007 at 04:26 PM.

  3. #18
    Registered User
    Join Date
    Aug 2007
    Posts
    66
    Quote Originally Posted by Elysia View Post
    Don't use flush unless necessary. Output is buffered for a reason.
    Your code is also very error prone. If a user enters a string instead of an integer, the rest of the cins will fail.
    No! I've tested and all cins work great!

    How do I know when I suppose to flush the buffer output ?

  4. #19
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Simple: you don't. Really. In most programs, you never need to flush the output buffer explicitly.

    Whenever you request input, the output is automatically flushed. Whenever the output buffer is full, it is flushed. When your program exits, the output buffer is flushed.

    The only situation where you actually do have to flush the buffer is when you display progress messages during a lengthy computation. If you don't flush then, the message won't show up until after the computation, which somewhat defeats the point.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  5. #20
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > I use cin.ignore method. So, am I right ? or no ...... ?
    Which wasn't the question you asked.

    Each example works in it's own way (which wasn't the issue).

    What I thought you were after was some opinion on what might be the "most suitable" way of dealing with the problem. To me, this meant the code which had the highest probability of working first time, with the minimum risk of such things as buffer and numeric overflow.

    But since you seem to be wedded to using ignore() at every opportunity, then go for it.
    At least it is now a more informed choice.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #21
    Registered User
    Join Date
    Aug 2007
    Posts
    66
    The question is simple:
    Suppose that you have to develop a program in C++. This program asks for user to insert some numeric values. Such as:
    cout << "Give me your age";
    cin >> age;
    cout <<"Give me your phone number";
    cin >> phone;
    cout <<"What is the result of 1+1 ?";
    cin >> result;
    cout <<"How many friends do you have";
    cin >> friends;
    etc etc etc

    If I understood, you say that the official,C++ method to check the input stream is by conversion (e.g using atoi() function). But, if you choose this way you have some disadvantages, such as:
    1)As you said before, you're code is vulnerable to numeric overflow exploits.
    2)More variables --> more RAM (unimportant for new desktops)
    3)Slow speed, because it need to convert, then restore and then check the conversion.
    4)You should repeat the same commands when you want to check the input stream of each numeric variable(I cannot find a way to do it by creating by own function).

    What are the advantages ? I cannot find them...


    I am not wedded to using ignore(), I just want to know which is the best to use in my programs from now on.

    Sorry for the misunderstandings, Salem. My English are not so well.

    Thank you for answering!!!!

  7. #22
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by BlackSlash12 View Post
    The question is simple:
    Suppose that you have to develop a program in C++. This program asks for user to insert some numeric values. Such as:
    cout << "Give me your age";
    cin >> age;
    cout <<"Give me your phone number";
    cin >> phone;
    cout <<"What is the result of 1+1 ?";
    cin >> result;
    cout <<"How many friends do you have";
    cin >> friends;
    etc etc etc

    If I understood, you say that the official,C++ method to check the input stream is by conversion (e.g using atoi() function). But, if you choose this way you have some disadvantages, such as:
    1)As you said before, you're code is vulnerable to numeric overflow exploits.
    You need to be aware of what the input is, what range it should be [e.g someone saying they are 1000 years old is probably not right!], so you still need to sanity check your inputs.
    2)More variables --> more RAM (unimportant for new desktops)
    As you say, not important.
    3)Slow speed, because it need to convert, then restore and then check the conversion.
    If you get a noticable difference in speed because of this, you are doing something wrong - the user will take seconds to input things, and even a complicated conversion is in the region of a few hundred microseconds. 10000 times difference between those values...
    4)You should repeat the same commands when you want to check the input stream of each numeric variable(I cannot find a way to do it by creating by own function).
    Createing a function (or class) that supports dealing with input of numbers in a safe way is an excellent solution.

    What are the advantages ? I cannot find them...
    Reliable code, well working applications isn't valuable to you, I guess?

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #23
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > 3)Slow speed, because it need to convert, then restore and then check the conversion.
    Performing input and conversion at the same time ( as in cin >> myIntVar ) is not going to be that different from input (to a string) then convert (from string to int). It's the same amount of work either way.

    > 2)More variables --> more RAM (unimportant for new desktops)
    They're all temporary variables anyway, so any space they used is reclaimed at the end of the input reading function. The large data resources are going to be as a result of the file being read, not the temporary variables used to do the reading (one line at a time).
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  9. #24
    Registered User
    Join Date
    Aug 2007
    Posts
    66
    I care about reliable code and well working applications!!!

    So, matsp, can you write me function that checks the numeric input (without any other limitation such as you said 1000 years old) using the the conversion ? I want to see a general example of using conversion.

    Thanks both of you guys!
    Last edited by BlackSlash12; 11-27-2007 at 11:12 AM.

  10. #25
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Several years back (about 15 or so), I wrote a whole set of functions to do user-input with all sorts of qualification, size and variations - integers, floats, prices [integer in "pence/cents" displayed as x/100 '.' x &#37;100] strings, dates, times, telephone numbers [including checking that the area code is valid and number of digits is the right for that area code], and a few other things like that.

    Variant 1, using C instead of C++ conversion:
    Code:
    bool inputInt(std::string prompt, int &val)
    {
    	char *ptr;
    	std::string input;
    	for(;;) 
    	{
    		std::cout << prompt;
    		if (!std::getline(std::cin, input))   
    			return false;  // Failed to read input. 
    		val = strtol(input.c_str(), &ptr, 0);
    		if (*ptr != '\0' || ((val == LONG_MAX || val == LONG_MIN) && errno == ERANGE)) {
    			std::cout << "Error, not a valid number" << std::endl;
    			errno = 0;
    		}
    		else
    		{
    			return true;
    		}
    	}
    }
    
    int main() {
    	for(;;) 
    	{
    		int x;
    		if (!inputInt("Enter a number (-999 to exit):", x))
    		{	
    			std::cerr << "Irrecoverable error, EOF or similar." << std::endl;
    			exit(1);
    		}
    		std::cout << "You entered " << x << std::endl;
    		if (x == -999) 
    			break;
    	}
    	return 0;
    }

    Variant 2: using C++ conversion with stringstream [plugs into the above test framework]::
    Code:
    bool inputInt(std::string prompt, int &val)
    {
    	std::string input;
    	std::stringstream sstr;
    	for(;;) 
    	{
    		std::cout << prompt;
    		if (!std::getline(std::cin, input))   
    			return false;  // Failed to read input. 
    		sstr << input;
    		if (sstr >> val) {
    			return true;
    		}
    		else
    		{
    			sstr.clear();
    			sstr.ignore(1000);
    			sstr.clear();
    			std::cout << "Error, not a valid number" << std::endl;
    		}
    	}
    }
    Edit: variant 3 - moved the scope of the stringstream variable, so that I don't need to mess about with clearing it:
    Code:
    bool inputInt(std::string prompt, int &val)
    {
    	std::string input;
    	for(;;) 
    	{
    		std::stringstream sstr;
    		std::cout << prompt;
    		if (!std::getline(std::cin, input))   
    			return false;  // Failed to read input. 
    		sstr << input;
    		if (sstr >> val) {
    			return true;
    		}
    		else
    		{
    			std::cout << "Error, not a valid number" << std::endl;
    		}
    	}
    }
    --
    Mats
    Last edited by matsp; 11-27-2007 at 02:49 PM.
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #26
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    As to performance, I re-wrote the inputInt function to take a iStream as a parameter, and stuffed 4000 strings [mostly duplicates of 3-5 digits] into a stringstream, and processed that through the inputInt function. It took 93 milliseconds... ;-)

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  12. #27
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    I don't think anybody should have to apologize for their language or nationality. If you speak Greek, I see no reason not to write comments in Greek. A browser with poor Unicode support might show garbage. But that is hardly a reason to force people to use a non-preferred language. It is, after all, only a technical issue.

    Our Anglo-centrism runs so deep sometimes we don't even see it.

    I love Greek, by the way, but never really got past "Kalimera" and "Kalispera"

  13. #28
    Registered User
    Join Date
    Aug 2007
    Posts
    66
    First of all I need to say a BIG thank you to matsp for his great work and the time that he devoted to post here these great piece of code.

    Code:
    #include <iostream>
    #include <sstream>
    #include <string>
    using namespace std;
    
    
    bool inputInt(std::string prompt, int &val)
    {
    	using namespace std;
    	string input;
    	for(;;) 
    	{
    		stringstream sstr;
    		cout << prompt;
    		if (!(cin>>input))   
    			return false;  // Failed to read input. 
    		sstr << input;
    		if (sstr >> val) {
    			return true;
    		}
    		else
    		{
    			cout << "Error, not a valid number" << std::endl;
    		}
    	}
    }
    
    int main()
    {
    	using namespace std;
    
    	string age2,phone2,firstName, lastName, city, job;
    	int age, phone;
    
    	cout << "What's your first name? " << flush;
    	cin >> firstName;
    
    	cout << "What's your last name? " << flush;
    	cin >> lastName;
    
    	cout << "What is your job? " << flush;
    	cin >> job;
    
    	cout << "Where do you live? (city)  " << flush;
    	cin >> city;
    
    	cout << "What year were you born? " << flush;
    	inputInt(age2,age);
    
    	cout << "What is your phone number? " << flush;
    	inputInt(phone2,phone);
    
    	cout <<"OTE Telephone Company"
    		 <<"\nOk.Registered.... ===>"
    		 <<"First Name ==========================> " << firstName << endl
    		 <<"Last  Name ==========================> " << lastName << endl
    		 <<" Location  ==========================> " << city << endl
    		 <<" Work as   ==========================> " << job << endl
    		 <<"   Age     ==========================> " << (2007-age) << endl
    		 <<"  phone    ==========================> " << phone << endl;
    	return 0;
    }




    I have one question:
    bool inputInt(std::string prompt, int &val)

    Why are you using the &val ? Why do you use the address of operator (&) ?
    Last edited by BlackSlash12; 11-27-2007 at 03:46 PM.

  14. #29
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654

  15. #30
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    The first parameter to inputInt is supposed to be "a question", e.g. "What year were you born?" or "Enter your phone-number:". That way, if someone hangs on the enter key for half an hour, he/she still knows what the question was. If you pass an empty string, then there will be nothing but an empty screen in the same circumstance.


    by the way, storing phone numbers as integers is bound to fail in many countries, as the number 0 is necessary at the start of the number - since that's the area code - where I live for example, the phone number is 01483 and then 6 more digits. Since 0 at the beginning of a number is usually removed when printing, it won't output the same as the input - use strings for phone numbers - which also works better for really long telephone numbers [full international numbers may be more than the 11 that you can fit in a long integer].

    I choose to use references rather than a pointer because it's "more C++" [or to put it another way, "because we can"].

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. entering numbers to array in a row whithout length input
    By transgalactic2 in forum C Programming
    Replies: 55
    Last Post: 01-02-2009, 04:02 AM
  2. About aes
    By gumit in forum C Programming
    Replies: 13
    Last Post: 10-24-2006, 03:42 PM
  3. Problem getting the input from a temp variable into the Array
    By hello_moto in forum C++ Programming
    Replies: 3
    Last Post: 03-16-2006, 01:50 AM
  4. String input problem, gets
    By willc0de4food in forum C Programming
    Replies: 13
    Last Post: 03-05-2005, 02:05 PM
  5. Problem with Printing message
    By robert_sun in forum C Programming
    Replies: 2
    Last Post: 05-16-2004, 02:09 PM