字串轉int:處理8,10,16進位制以及處理無效字元
字串轉int函式:
函式名:Myatoi(*str)
功能:將一串字串轉成int整形數字
注意事項:
1.int型最大取值範圍:2147483647,int型佔4位元組,即4*8 = 32位二進位制,整數在二進位制中用原碼錶示即可,第一位為符號位0表示正數,即:01111111 11111111 11111111 11111111,十六進位制(HEX)表示為:0fff ffff,十進位制計算方法為:2^31 – 1;最小值:十六進位制為:0x80000 0000(HEX),二進位制為:10000000 00000000 00000000 00000000(BIN),十進位制計算方法為:-1*2^31。
2.程式設計時,我第二次用了分開計算正數和負數的方法。由於第一次計算正數,得出負數時是把sum × (-1),這樣計算就會有bug。因為正數的最大值為2147483647,所以×(-1)得到的負數最小值為-2147486947,而不是0x8000 0000(HEX)。
3.注意int型別和char型別一樣是,表示的範圍是迴圈的,我們知道char類型範圍是:-128 — 127 ,如果char a = 127,b = a+1;那麼b就為-128;
所以int同理,我們可以用sum>0或者sum<0判斷sum是否超出的正數或者負數的表示表示範圍。例如:我們求sum為整正數,sum = sum*10 +*str – ‘0’,此時sum為2147483647,sum再加一個1 ,就超出了int表示的正數範圍,2147483647 + 1 為 -2147483648 ,這是一個負數了,此時sum<0,所以sum = MAXINT(最大int正數)。
同理sum表示負數時,若sum一直減,減到最小後再減就>0了,此時就可以退出迴圈,sum = MININT就ok了。
4.先寫了10進位制的情況;十六進位制和八進位制的情況,不需要像10進位制一樣考慮 負號和正號。
5.用到的幾個字元函式:
isdigit();//判斷字元是否為數字
isxdigit();//判斷引數字元是否為16進位制字元,即A-F,a-f
toupper();//如果引數字元是小寫字母,則轉化成大寫字母
6.將字元轉化為int整數時候:
如果是數字字元,’a’ – ‘0’ 減字元0即可。
如果是字母,‘B’ – ‘A’ +10;//表示11。16進位制的計算時要用到
7.還有一個問題:十六進位制和八進位制的sum判斷是否超出範圍,在定義sum時將其定義為long long型別,進行加法加法運算時候,if(sum >maxint),就退出迴圈,返回maxInt。再將最後的結果轉化為int型別。
程式用例:
#include<ctype.h>
#include<assert.h>
#include<stdio.h>
#define MAXINT 0x7fffffff //int範圍內的最大正數
#define MININT 0x80000000 //最小的負數
int Str_To_Int_DEC(char *str)//10進位制
{
int sum = 0;
int flag = 1;//判斷正負數 1表示正數 -1 表示負數
bool first_sum = true;//做負數運算時 判斷第一次運算是否執行
while(*str == ' ')
{
str++;
}
if(*str == '-')
{
flag = -1;
str++;
}
else if(*str == '+')
{
str++;
}
while(isdigit(*str))
{
if(flag == 1)
{
sum = sum*10 + *str -'0';
str++;
if(sum < 0)
{
return MAXINT;
}
}
else if(flag == -1)
{
if(first_sum == true)
{
sum = -(*str-'0');//第一個數為負數
str++;
first_sum = false;
}
else if(first_sum == false)
{
sum = sum*10 - (*str - '0');
str++;
}
if(sum > 0)
{
return MININT;
}
}
}
return sum;
}
int Str_To_Int_HEX(char *str)//16進位制
{
long long sum = 0;
while(*str == ' ')
{
str++;
}
while(isxdigit(*str))//int isxdigit();功能:如果引數是十六進位制數字字元(即:A-F, a-f, 0-9),函式返回非零值,否則返回零值。
{
if(isalpha(*str))
{
sum = sum*16 + toupper(*str) -'A'+10;//如果是字母的話
str++;
}
else if(isdigit(*str))
{
sum = sum*16 + *str -'0';
str++;
}
if(sum > MAXINT)
{
sum = MAXINT;
break;
}
}
return (int)sum;
}
int Str_To_Int_OCT(char *str)//8進位制
{
long long sum = 0;
while(*str == ' ')
{
str++;
}
while(*str>= '0' && *str <= '7')
{
sum = sum*8 + *str -'0';
str++;
if(sum > MAXINT)
{
sum = MAXINT;
break;
}
}
return (int)sum;
}
int Myatoi(char *str)
{
assert(str != NULL);
int result;
while(isspace(*str))
{
str++;
}
if(*str == '0')
{
str++;
if(*str == 'x' || *str == 'X')
{
str++;
result = Str_To_Int_HEX(str);
}
else
{
result = Str_To_Int_OCT(str);
}
}
else
{
result = Str_To_Int_DEC(str);
}
return result;
}
int main()
{
char *str1 = "321564";
char *str2 = "2147483647";
char *str3 = "2147483648";
char *str4 = "+326549875646156";
char *str5 = "-321564";
char *str6 = "-2147483648";
char *str7 = "-2147483649";
char *str8 = "0x7fffffff";
char *str9 = "80000000";
char *str10 = "0x654ab";
char *str11 = "0Xbbb";
printf("%d\n", Myatoi(str1));
printf("%d\n", Myatoi(str2));
printf("%d\n", Myatoi(str3));
printf("%d\n", Myatoi(str4));
printf("%d\n", Myatoi(str5));
printf("%d\n", Myatoi(str6));
printf("%d\n", Myatoi(str7));
printf("%d\n", Myatoi(str8));
printf("%d\n", Myatoi(str9));
printf("%d\n", Myatoi(str10));
printf("%d\n", Myatoi(str11));
return 0;
}
下面是十進位制的測試結果: