要考慮的問題
- 前導空白(空格和Tab)
- 溢出
- 異常字符
處理方法
- 首先過濾前導空白,直到遇到非空白符
- 若接下來的字符是正負號或者數字,繼續執行下一步;否則,返回0,結束
- 一直讀取,直至遇到非數字字符(包括’\0’)
- 若這段數字溢出,則相應的返回 INT_MAX 或者 INT_MIN ;否則,返回轉換後的結果,結束
代碼如下
#include "stdio.h"
#define INT_MAX 2147483647
#define INT_MIN (-2147483647-1)
#define MAX_DIGITS 10 // int類型的最大位數
const char* INT_MAX_STR = "2147483647";
const char* INT_MIN_STR = "2147483648";
bool overflow(char* num, int flag)
{
char* INT_BOUND = (flag == 1) ? INT_MAX_STR : INT_MIN_STR;
for(int i = 0; i < MAX_DIGITS; i++)
{
if(num[i] > INT_BOUND [i])
return true;
else if(num[i] < INT_BOUND [i])
return false;
}
return false;
}
bool isDigit(char ch)
{
return (ch >= '0' && ch <= '9');
}
int atoi(char * str)
{
int value = 0;
while(*str == ' ' || *str == '\t')
*str++;
if(*str == '\0')
return 0;
int flag = 1;
if(*str == '+' || *str == '-')
{
if(*str == '-')
flag = -1;
*str++;
}
char num[MAX_DIGITS];
int index = 0;
while(isDigit(*str))
{
if(index >= MAX_DIGITS) // overflow
return (flag == 1) ? INT_MAX : INT_MIN;
num[index++] = *str;
*str++;
}
if(index == MAX_DIGITS && overflow(num, flag)) // overflow
return (flag == 1) ? INT_MAX : INT_MIN;
for(int i = 0; i < index; i++)
value = value * 10 + num[i] - '0';
return value * flag;
}
相關問題
關於INT_MIN的定義,若寫成-2147483648,則當在程序中使用INT_MIN時,編譯器會出現警告信息:
warning C4146:一元負運算符應用於無符號類型,結果仍爲無符號類型;
編譯器把-2147483648看做了對2147483648取負,而2147483648超出了有符號整數的範圍,編譯器就把他當做了無符號數0x80000000=2147483648。
在C語言中,若有符號數與無符號數進行運算,C語言就隱式的將有符號參數強制轉換爲無符號數,
並假設兩個數都是非負的。(深入理解計算機系統 P48)
在有些情況下這會導致一些錯誤,比如下面的表達式:
(0>INT_MIN) ? 1 : -1;
表達式的結果是 -1 就不難理解了。