字串轉數字atoi的重新編寫及注意事項

littleway發表於2014-05-14

字串轉數字看似很簡單,其實很多細節需要把握,這裡涉及到程式碼完整性:功能測試、邊界檢測和負面測試。如果要把所有的細節都考慮到是不太容易的。

本部落格啟發於劍指offer的最後一章的第一個面試案例。

我想大家都知道用n=n*10+c-‘0’的方式來進行轉換,這裡就直接進行分析了。

功能測試:

出現+-號,能否正確識別並計算出正確結果。

邊界檢測:

如果發生溢位情況怎麼辦,字串超出了int範圍?

負面檢測:

1、字串為空“”

2、輸入指標為NULL

3、含有非數字字元

4、開頭的+、-號之後接著'\0'

5、小數點(新新增,程式碼未實現)


由於可能出現的負面輸入以及溢位情況,我們需要對結果進行判斷,這裡介紹一下三種錯誤處理方式:返回值、全域性變數、異常。

返回值:和系統API一致; 但是不能方便的使用返回結果,並且會有二義性。

全域性變數:用全域性變數表示錯誤狀態,能方便使用結果; 但是程式設計師可能會忘記檢查全域性變數。

異常:可以為不同的出錯原因定義不同該異常型別,邏輯清晰明瞭; 有些語言不支援,同時對效能有一定程度上的負面影響。


這裡附上全域性變數和異常處理的兩種程式碼供參考:

全域性變數:

enum Status{Valid = 0, Invalid, OutOfRange};
int g_status = Invalid;
int atoi(char* str)
{
	if(str != NULL && *str != '\0') 
	{
		g_status = Invalid;
		//這裡用long long是為了判斷它的越界;
		long long num = 0;

		char *tmp = str;
		int flag = 1;
		//判斷開頭的符號;
		if(*tmp == '-')
		{
			flag = -1;
			++tmp;
		}
		else if(*tmp == '+')
			++tmp;
		//以免只有符號沒有數字;
		if(*tmp != '\0')
		{
			while(*tmp != '\0')
			{
				if(*tmp >= '0' && *tmp <= '9')
				{
					//如果num不是long long,這裡就需要多計算一次;
					num = num*10 + flag * (*tmp - '0');
					if(flag && num > 0x7FFFFFFF)
					{
						g_status = OutOfRange;
						return 0;
					}
					if(flag == 0 && num < 0x80000000)
					{
						g_status = OutOfRange;
						return 0;
					}
				}
				else
				{
					return 0;
				}

			}
		}
		g_status = Valid;
		return num;
	}	
}

異常:

int atoi(char* str)
{
	if(str != NULL && *str != '\0') 
	{
		//這裡用long long是為了判斷它的越界;
		long long num = 0;

		char *tmp = str;
		int flag = 1;
		//判斷開頭的符號;
		if(*tmp == '-')
		{
			flag = -1;
			++tmp;
		}
		else if(*tmp == '+')
			++tmp;
		//以免只有符號沒有數字;
		if(*tmp != '\0')
		{
			while(*tmp != '\0')
			{
				if(*tmp >= '0' && *tmp <= '9')
				{
					//如果num不是long long,這裡就需要多計算一次;
					num = num*10 + flag * (*tmp - '0');
					if(flag && num > 0x7FFFFFFF)
						throw range_error("Error: out of range!");					
					if(flag == 0 && num < 0x80000000)
						throw range_error("Error: out of range!");					
				}
				else
				{
					throw invalid_argument("Error: invalid input!");
				}

			}
		}
		else 
			throw invalid_argument("Error: invalid input!");

		return num;
	}
	else
		throw invalid_argument("Error: invalid input!");
}


相關文章