這兩天做的一個項目需要將十進制字符串(只含'0'--'9' )轉換成相應的數字。比如將“123456789”轉換成數字123456789。要求只轉換指定長度而不是轉換到字符串的結束‘\0’。在網上搜到了比如StrToInt()等都是處理字符串到字符串結束而且不知道那些函數能不能判斷溢出,比如對於32位機來說4294967295是無符號整型能表示的最大數,如果所給的字符串超出了上述範圍函數能不能判斷出來。一個很簡單的方法是用 sscanf 函數或者atoi函數,如下:
char a[] = "4294967295";
unsigned int i;
sscanf(a, "%d", &i);// 或者 i = atoi(a);
printf("i = %u\n", i);
缺點就是如果要轉換的字符串表示的數超出了範圍sscanf函數會自動截斷。也就是說如果字符串是“4294967296”,轉換後i=0。而且轉換前還需要把要轉換的字符串賦給一個字符數組。優點是它可以轉換小數等其他功能。當然可以改進,可以判斷溢出,但判斷不出非法字符:
// 將前面的'0'去掉
char p[] = "4294967295";
char *a = p;
while (*a == '0')
{
++a;
}
unsigned int maxUINT = 0xFFFFFFFF;
char b[11];
unsigned int result;
sprintf(b, "%u", maxUINT);
if (strcmp(a, b) > 0)
{
printf("溢出!\n");
}
else
{
sscanf(a, "%u", &result);
printf("result = %u\n", result);
}
一般情況下用sscanf足夠了。爲了玩,我另寫了一個函數。雖然效率差了許多但還勉強過得去。我沒有用sscanf和sprintf,下面是代碼。參數len是要轉換的字符個數。
unsigned int StrToDec(const char *str, int len)
{
while (*str == '0')
{
str++;
len--;
}
unsigned int maxUINT = 0xFFFFFFFF;
// 32位機integer最大能表示十位
if (len > 10)
{
printf("溢出!\n");
return 0;
}
unsigned int tmpResult = 0;
if (len < 10)
{
while (len-- > 0)
{
tmpResult *= 10;
if (*str >= '0' && *str <= '9')
{
tmpResult += (*str) - '0';
}
else
{
printf("字符串出現非法字符!\n");
return 0;
}
str++;
}
return tmpResult;
}
else
{
unsigned int tmpQuotient = 0;// 商
unsigned int tmpRemainder = 0;// 餘數
if (*str >= '0' && *str <= '9')
{
tmpResult += (*str) - '0';
}
str++;
while (len-- > 1)
{
if (*str >= '0' && *str <= '9')
{
tmpQuotient = maxUINT / (unsigned int)pow(10, len);
tmpRemainder = maxUINT % (unsigned int)pow(10, len);
if ((tmpResult < tmpQuotient)
|| ((tmpResult == tmpQuotient)
&& (*str - '0' <= tmpRemainder / pow(10, len - 1))))
{
tmpResult *= 10;
tmpResult += (*str) - '0';
str++;
}
else
{
printf("溢出!\n");
return 0;
}
}
else
{
printf("字符串出現非法字符!\n");
return 0;
}
}
return tmpResult;
}
}
十進制字符串(只含'0'--'9' )的溢出判斷有點複雜,十六進制字符串(含'0' -- '9'以及'a' -- 'f'或'A'--'F')的溢出判斷就相對簡單了:
unsigned int HexStrToDec(const char *str, int len)
{
// 32位機
if (len > 8)
{
return 0;
}
unsigned int tmpResult = 0;
while (len-- > 0)
{
tmpResult <<= 4;
if (*str >= '0' && *str <= '9')
{
tmpResult |= *str - '0';
}
else if(*str >= 'A' && *str <= 'F')
{
tmpResult |= *str - 'A' + 10;
}
else if(*str >= 'a' && *str <= 'f')
{
tmpResult |= *str - 'a' + 10;
}
str++;
}
return tmpResult;
}
//下面是我在網上找的一位大牛用C++實現的,方法很簡便,缺點是處理大量數據轉換速度較慢。用C++的stringstream:
#include <sstream>
#Include <string>
string num2str(double i)
{
stringstream ss;
ss << i;
return ss.str();
}
int str2num(string s)
{
int num;
stringstream ss(s);
ss >> num;
return num;
}
The End.
<pre name="code" class="cpp">