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;
}
浙公网安备 33010602011771号