c++中string和int相互转化

  今天逛csdn的时候看到一篇讲atoi的博客,进去看了看,然后就想根据自己以前java中的转化仿造一把。

  1.  int  转  string 

    其实原理很简单(也是照搬JDK上的,稍微改了点).  加入有个整形 m,现需要转成字符串。可能你会想到每次除10取模然后再将余数变成字符。额,是的。但是这里并不想每次都除以10,而是100.这样每次就取出了两位,然后根据事先准备好的对应表直接将十位和个位取出来

  2. string 转  int

    其实atoi的内部实现就一句话   return  (int)atol(...)。 就是先转成long然后再强转到int. 我想最主要的问题还是可能的溢出。假如一个很长的string转成int必然会溢出,如果转成long不溢出,再转成int必然会被截断,我现在想返回最大或最小的整形。

  废话不说,直接上代码

#ifndef __STINRG_2_INT_H
#define __STING_2_INT_H
#include <string>
using  std::string;
class StrIntConveter
{
public:
	static char DigitTens[];
	static char DigitOnes[];
	static int sizeTable[];
	static int StringSize(int);
	static string ToString(int);   //int 转string
	static void GetChars(int i,int index ,char buf[]);  //内部实际使用
	static bool ParseInt(const string&,int& );  //整形转string
	static bool ParseInt(const string& ,int&,int);//内部实际使用
protected:
private:
};
#endif


#include "string2int.h"
#include "character.h"
char StrIntConveter::DigitTens[]={'0', '0', '0', '0', '0', '0', '0', '0',
'0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '2',
'2', '2', '2', '2', '2', '2', '2', '2', '2', '3', '3', '3', '3',
'3', '3', '3', '3', '3', '3', '4', '4', '4', '4', '4', '4', '4',
'4', '4', '4', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
'6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '7', '7', '7',
'7', '7', '7', '7', '7', '7', '7', '8', '8', '8', '8', '8', '8',
'8', '8', '8', '8', '9', '9', '9', '9', '9', '9', '9', '9', '9',
'9', };
char StrIntConveter::DigitOnes[]={'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6',
'7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2',
'3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', };
int StrIntConveter::sizeTable[]= { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, INT_MAX };
int StrIntConveter::StringSize(int x)
{
	for (int i=0;;i++)
	{
		if (x<=sizeTable[i])
			return i+1;
	}
}
string StrIntConveter::ToString(int i)
{
	if (i==INT_MIN)
		return "-2147483648";
	//获得要转换的整数一共有多少位,包含符号位
	int size=(i<0)?StringSize(-i)+1:StringSize(i);
	char* tmp=new char[size+1];
	tmp[size]='\0';  //以为new char时会自动将数据清0.没想到啊。所以这里必须显示的设置一下
	GetChars(i,size,tmp);
	string retValue= string(tmp);
	delete [] tmp;
	return retValue;
}
void StrIntConveter::GetChars(int i,int index ,char buf[])
{
	int q,r;
	int charPos=index;
	char sign=0;  //符号位
	if (i<0)
	{
		sign='-';
		i=-i;
	}
	//为了提高效率,每次产生2位,然后尽量用位运算
	while (i>100)
	{
		q=i/100;
		r=i-((q<<6)+(q<<5)+(q<<2));//取2位的余数
		i=q;
		buf[--charPos]=DigitOnes[r];
		buf[--charPos]=DigitTens[r];
	}
	//JDK处理小于65535的情况不好用c++处理,所以用了自己的办法
	if(q==100){
		buf[--charPos] = '0';
		buf[--charPos] = '0';
		buf[--charPos] = '1';
	}else if(q<10){
		buf[--charPos]=DigitOnes[i];
	}else{
		buf[--charPos]=DigitOnes[q];
		buf[--charPos]=DigitTens[i];
	}
	if(sign!=0){
		buf[--charPos]=sign;
	}
}
bool StrIntConveter::ParseInt(const string&s , int & retValue)
{
	if (ParseInt(s,retValue,10))
		return true;
	return false;
}
bool StrIntConveter::ParseInt(const string &s, int &retValue, int radix)
{
	if (s.empty() || s=="")
	{
		retValue=0;
		return true;
	}
	if (radix<Character::MIN_RADIX || radix>Character::MAX_RADIX)
		return false;
	bool negative=false;  //表示正负
	int result=0;                //转换结果
	int limit;                     //极限范围
	int multmin;                //在 *radix之前的极限
	int i=0,maxl=s.size();
	int tmpDigit;            //每次取出的字符
	if (maxl>0)
	{
		if (s.at(0)=='-')
		{
			negative=true;
			limit=INT_MIN;
			i++;
		}else
		{
			limit=-INT_MAX;  //在这里也将正数先表示为负数,返回结果的时候再判断(所有都为了统一后面的操作)
		}
		multmin=limit/radix;
		if (i<maxl)
		{
			tmpDigit=Character::Digit(s.at(i++),radix);
			if (tmpDigit<0)
			{
				return false;
			}else
				result=-tmpDigit;
		}

		while (i<maxl)
		{
			tmpDigit=Character::Digit(s.at(i++),radix);
			if (tmpDigit<0)
			{
				return false;
			}
			if (result<multmin)  //已经到极限了
			{
				//这里会出现溢出,但是为了程序健壮将直接返回最大值
				result=limit;
				break;
			}
			result*=radix;
			if (result<limit+tmpDigit)
			{
				result=limit;
				break;
			}
			result-=tmpDigit;
		}
	}
	else 
	{
		retValue=0;
		return true;
	}
	if (negative)
	{
		if (i>1)
		{
			retValue=result;
			return true;
		}else  //仅仅只有一个  ‘-’
		{
			return false;
		}
	}else
	{
		retValue=-result;
		return true;
	}

}

  

#ifndef __CHARACTER_H
#define __CHARACTER_H
class Character
{
public:
	static int MIN_RADIX;   //最小进制
	static int MAX_RADIX; //最大进制
	static char MIN_CHAR;
	static char MAX_CHAR;
	static int Digit(char ch,int radix);
protected:
private:
};
#endif


#include "character.h"
#include <ctype.h>
int Character::MIN_RADIX=2;
int Character::MAX_RADIX=36;
char Character::MIN_CHAR='\0';
char Character::MAX_CHAR=0xff;
//将一个radix进制的数转换成对应的十进制
//其中负数表示失败
int Character::Digit(char ch, int radix)
{
	if (radix<MIN_RADIX || radix>MAX_RADIX)
	{
		return -1;
	}
	if (radix<=10)
	{
		if (ch>='0' && ch<='9')
		{
			return ch-'0';
		}
		return -1;
	}
	int upperChar=toupper(ch);
	int limit='A'+radix-11;
	if (upperChar>limit)
		return -1;
	return 10+upperChar-'A';
}

  这是些测试用的

#include <iostream>
#include <string>
#include "string2int.h"
using std::cout;
using std::cin;
using std::string;
int main()
{
	/*int i=0;
	cout<<"请输入要转成string的 整数\n";
	cin>>i;
	while (i!=1)
	{
		cout<<StrIntConveter::ToString(i)<<"\n";
		cin>>i;
	}*/
	int result=0;
	string tmp;
	cout<<"请输入要转成int 的string\n";
	cin>>tmp;
	while (tmp!="quit")
	{
		if (StrIntConveter::ParseInt(tmp,result))
		{
			cout<<"转换的结果是"<<result<<"\n";
			cin>>tmp;
		}else{
			cout<<"转换失败\n";
			break;
		}
		
	}
	system("pause");
	return 0;
}

  

posted on 2013-06-05 12:59  SandyNie  阅读(377)  评论(0编辑  收藏  举报

导航