Page 1 of 1

Input validation of Integer and Floating point number using strtol() a Rate Topic: -----

#1 Tapas Bose  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 23
  • View blog
  • Posts: 472
  • Joined: 09-December 09

Posted 19 March 2010 - 01:57 AM

Input validation is an important and necessary part of secure programming. Invalid input can cause abnormal termination of program. There are different methods of input validation. In this tutorial we are going to see input validation of integer and floating point number using two very known functions of C and C++, that is strtol() and strtod().

Before we get any source code let us see the synopsis and descriptions of strtol() and strtod() functions.

strtol()

Header required : stdlib.h in C or cstdlib in C++.

Synopsis : long int strtol(const char *nptr, char **endptr, int base);

Description : The strtol() function converts the initial part of the string in nptr to a long integer value according to the given base, which must be between 2 and 36 inclusive.
The string may begin with an arbitrary amount of white space followed by a single optional '+' or '-' sign. If base is zero or 16, the string may then include a '0x' prefix, and the number will be read in base 16; otherwise, a zero base is taken as 10 (decimal) unless the next character is '0', in which case it is taken as 8 (octal).
The remainder of the string is converted to a long int value in the obvious manner, stopping at the first character which is not a valid digit in the given base. (In bases above 10, the letter 'A' in either upper or lower case represents 10, 'B' represents 11, and so forth, with 'Z' representing 35.)
If endptr is not NULL, strtol() stores the address of the first invalid character in *endptr. If there were no digits at all, strtol() stores the original value of nptr in *endptr (and returns 0). In particular, if *nptr is not '\0' but **endptr is '\0' on return, the entire string is valid.

Return Value : The strtol() function returns the result of the conversion, unless the value would underflow or overflow. If an underflow occurs, strtol() returns LONG_MIN. If an overflow occurs, strtol() returns LONG_MAX. In both cases, errno is set to ERANGE.

strtod()

Header required : stdlib.h in C and cstdlib in C++

Synopsis : double strtod(const char *nptr, char **endptr);

Description : The strtod() functions convert the initial portion of the string pointed to by nptr to double.
The string may begin with an arbitrary amount of white space followed by a single optional '+' or '-' sign and then either (i) a decimal number, or (ii) a hexadecimal number, or (iii) an infinity, or (iv) a NAN (not-a-number).
A decimal number consists of a nonempty sequence of decimal digits possibly containing a radix character (decimal point, locale dependent, usually ''.''), optionally followed by a decimal exponent.
A decimal exponent consists of an ''E'' or ''e'', followed by an optional plus or minus sign, followed by a non-empty sequence of decimal digits, and indicates multiplication by a power of 10.
A hexadecimal number consists of a ''0x'' or ''0X'' followed by a nonempty sequence of hexadecimal digits possibly containing a radix character, optionally followed by a binary exponent. A binary exponent consists of a ''P'' or ''p'', followed by an optional plus or minus sign, followed by a non-empty sequence of decimal digits, and indicates multiplication by a power of 2. At least one of radix character and binary exponent must be present.
An infinity is either ''INF'' or ''INFINITY'', disregarding case.
A NAN is ''NAN'' (disregarding case) optionally followed by '(', a sequence of characters, followed by ')'. The character string specifies in an implementation-dependent way the type of NAN.

Return Value : These functions return the converted value, if any. If endptr is not NULL, a pointer to the character after the last character used in the conversion is stored in the location referenced by endptr. If no conversion is performed, zero is returned and the value of nptr is stored in the location referenced by endptr. If the correct value would cause overflow, plus or minus HUGE_VAL (HUGE_VALF, HUGE_VALL) is returned (according to the sign of the value), and ERANGE is stored in errno. If the correct value would cause underflow, zero is returned and ERANGE is stored in errno.

Now it is time to get the code.
Integer validation :
#include <iostream>
#include <cstdlib>
#include <climits>
#include <cerrno>
#include <string>

using namespace std;

bool intInputValdation(string Str)
{
	char *endPtr;

	if (Str.empty()) 
	{ 
		// If the string does not contain any thing
		return false; 
	}
	
	errno = 0;	// errno is Last error number. It is set to zero at program startup, and certain 
			// functions of the standard C/c++ library modify its value to some value different 
			// from zero to signal some types of error.
	
	long Value = strtol(Str.c_str(), &endPtr, 10);		// strtol() function convert string to long
	
	// check if there is any overflow or underflow
	
	if ((errno == ERANGE && (Value == LONG_MAX || Value == LONG_MIN)) || (errno != 0 && Value == 0)) 
	{
		// ERANGE is range error
	
		// The strtol() function returns the result of the conversion, unless the value 
		// would underflow or overflow. If an underflow occurs, strtol() returns LONG_MIN.
		// If an overflow occurs, strtol() returns LONG_MAX. In both cases, errno is set to
		// ERANGE.
		 
		return false; 
	}
	
	// check whether input string contain any character
	
	else if (endPtr == Str || *endPtr != '\0') 
	{
		// If endptr is not NULL, strtol() stores the address of the first invalid character 
		// in *endptr. If there were no digits at all, strtol() stores the original value of
		// Str in *endptr  (and returns 0). In particular, if *Str is not '\0' but **endptr
		// is '\0' on return, the entire string is valid.	 
		
		return false; 
	}

	return true;		// otherwise correct input	
}

int main()
{
	string inputString;
	long inputLong;
	char *endPtr;
	
	cout << "  Enter an integer : ";
	getline(cin, inputString, '\n');
	
	cout << endl;
	
	if (intInputValdation(inputString))
	{
		inputLong = strtol(inputString.c_str(), &endPtr, 10);
		cout << "  You have entered : " << inputLong;
	}
	else
	{
		cout << "  Invalid input.";
	}
	
	cout << endl;
	cin.get();
	
	return 0;
}


Floating point number validation :
#include <cstdlib>
#include <cmath>
#include <cerrno>
#include <iostream>

using namespace std;

double getFloatNumber()
{
	double Value;
	bool correctInput = false;

	while(!correctInput)
	{
		char *endPtr;
		string Str;
		Value = 0;

		cout << "\n";
		cin.sync();
		cout << "  Enter a Number : ";
		getline(cin, Str, '\n');
		cout << "\n";

		if (Str.empty())
		{
			correctInput = false;
			cerr << "  Input is empty." << endl;
		}
		else
		{
	    		errno = 0;
	    		Value = strtod(Str.c_str(), &endPtr);		// strtod() function convert string to double
    		
	    		// check if there is any overflow or underflow
	    		
	    		if ((errno == ERANGE && (Value == HUGE_VALF || Value == HUGE_VALL)) || (errno != 0 && Value == 0))
	   		{
	        		cerr << "  Numerical result out of range." << endl;
	        		correctInput = false;
	    		}
	    		
	    		// check whether input string containg any character
	    		
	   		else if (endPtr == Str || *endPtr != '\0')
	   		{
	        		cerr << "  Invalid input." << endl;
	        		correctInput = false;
	    		}
	    		
	    		// otherwise correct input
	    		
			else
			{
				correctInput = true;
			}
		}
	}

	return Value;
}

int main()
{
	cout << "  You have entered : " << getFloatNumber() << endl << endl;
	return 0;
}



Note :
  • In the first code the base is set to 10, so this code will validate decimal number only.
  • In the second code an infinite loop is used to operate the validation function and this way the loop will not terminate until it get a proper input. It can be written as the first code without while(1).
  • The second code is not commented since there will be the same comments as the first one.
  • LONG_MAX and LONG_MIN are from the header climits, errno and ERANGE are from header cerrno and HUGE_VALF and HUGE_VALL are from header cmath.
  • There two codes after little modification can be used as C codes.

Hope these will help to validate input.

Is This A Good Question/Topic? 0
  • +

Page 1 of 1