String to integer implementation

#include <climits>
#include <cctype>
#include <typeinfo>
#include <iostream>
#include <cstdlib>
#include <cstring>

template <typename type>
type stoi(const char* s, int base);

int main() {
	short i;
	char buf[512];
	std::cout << 
		"SHRT_MIN = " << SHRT_MIN << std::endl <<
		"SHRT_MAX = " << SHRT_MAX << std::endl <<
		"Input short: ";
	std::cin >> buf;
	try {
		i = stoi<short>(buf, 0);
	} catch (int x) {
		std::cout << "Error: ";
		switch (x) {
		case 0: std::cout << "Invalid number\n"; break;
		case 1: std::cout << "Overflow\n"; break;
		case -1: std::cout << "Underflow\n"; break;
		}
		return 1;
	}
	std::cout << i << std::endl;
}

/*
* String to Integral type function
* by Jakash3
* Thu Jul 14, 2011
*
* Desc: When calling this function, the
* template type must be a built-in numeric
* type. Valid types are: char, short, int,
* long, long long, and their equivalent
* unsigned types.
* 
* s is the string to convert, base is the
* numeric base to use.
*
* s may have any amount of leading whitespace
* followed by an optional '+' or '-' sign.
* If base is 16 or 8 then the string may also
* have an optional "0x" or "0" prefix (after
* the sign if present). If base is 0 then
* the base will default to 10, 16, or 8 based
* on the base prefix (if present). 
*
* On success the number of the template type
* will be returned. This function will throw
* an exception of type int on failure. If it
* throws 0 then the string contained invalid
* characters, if it throws -1 then there was
* an underflow, if it throws 1 then there
* was an overflow.
*/
template <typename type>
type stoi(const char* s, int base) {
	bool neg = false;		//Negative flag
	type \
		ret = 0,				//Converted return value
		num,					//Temporary
		place = 1;			//Current digit place
		
	//What integer type are we converting to?
	const std::type_info &ti = typeid(type);
	
	//Skip whitespace
	while (isspace(*s)) s++;
	
	//Check for sign
	if (*s == '-') { neg = true; s++; }
	else if (*s == '+') s++;
	
	//Match optional base prefixes
	if (base == 0) {
		if (*s == '0') {
			if (tolower(s[1]) == 'x') { base = 16; s += 2; }
			else { base = 8; s++; }
		} else base = 10;
	} else {
		if (*s == '0') {
			if (tolower(s[1]) == 'x' && base == 16) s += 2;
			else if (base == 8) s++;
			else throw 0;
		}
	}
	
	const char \
		*set = "0123456789abcdefghijklmnopqrstuvwxyz",
		*t = s + strlen(s) - 1,
		*tmp;
	
	//For each digit in string (starting from rightmost)
	for (; t >= s; t--, place *= base) {
	
	//If place is 0 then value of digit place overflowed
		if (!place)
			if (neg) throw -1;
			else throw 1;
	
		//Get digit offset
		tmp = strchr(set, tolower(*t));
		
		//Is this a valid digit?
		if (tmp == NULL) throw 0;
		if (tmp - set >= base) throw 0;
		
		//Convert to digit value
		num = (tmp - set) * place;

		if (neg) {
			//Check for unsigned underflow
			if ((type)(ret - (num ? num : place) > ret)) throw -1;
			ret -= num;
			//Check for signed overflow
			if (ret >= 0 && num != 0) throw -1;
		} else {
			//Check for unsigned overflow
			if ((type)(ret + (num ? num : place) < ret)) throw 1;
			ret += num;
			//Check for signed overflow
			if (ret <= 0 && num != 0) throw 1;
		}
	}
	return ret;
}

int getRandomNumber() {
	return 4;		//chosen by fair dice roll.
						//guaranteed to be random.
}

This sample program uses my string to numeric function. This is more advanced as it supports negative numbers, multiple numeric datatypes (a template function), and supports try … catch for error handling.

/*
* String to Integral type function
* by Jakash3
* Thu Jul 14, 2011
*
* Desc: When calling this function, the
* template type must be a built-in numeric
* type. Valid types are: char, short, int,
* long, long long, and their equivalent
* unsigned types.
* 
* s is the string to convert, base is the
* numeric base to use.
*
* s may have any amount of leading whitespace
* followed by an optional '+' or '-' sign.
* If base is 16 or 8 then the string may also
* have an optional "0x" or "0" prefix (after
* the sign if present). If base is 0 then
* the base will default to 10, 16, or 8 based
* on the base prefix (if present). 
*
* On success the number of the template type
* will be returned. This function will throw
* an exception of type int on failure. If it
* throws 0 then the string contained invalid
* characters, if it throws -1 then there was
* an underflow, if it throws 1 then there
* was an overflow.
*/

One thought on “String to integer implementation

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: