面試高頻題:「不調用庫函數,實現 float StrToFloat(const char* str)」。看似簡單,實則坑多:符號位、小數點、非法字符截斷、溢出、邊界條件……作者在空閒時間完成雙版本(ANSI/Unicode)實現,並附帶豐富測試用例,堪稱教科書級參考。
while(*pSor) 循環搞定所有字符。bNegative 標記符號,bDec 標記是否進入小數部分。fInteger = fInteger * 10 + digitfDecimal += digit * fDecPower; fDecPower *= 0.1f(避免 pow 開銷)atof 風格。float StrToFloatA(const char* pstrfloat) {
if (!pstrfloat) return 0.0f;
bool bNegative = false, bDec = false;
const char* p = pstrfloat;
float fInt = 0.0f, fDec = 0.0f, fDecPower = 0.1f;
// 符號
if (*p == '-') { bNegative = true; p++; }
else if (*p == '+') { p++; }
while (*p != '\0') {
char ch = *p;
if (bDec) { // 小數部分
if (ch >= '0' && ch <= '9') {
fDec += (ch - '0') * fDecPower;
fDecPower *= 0.1f;
} else break; // 非法字符截斷
} else { // 整數部分
if (ch >= '0' && ch <= '9') {
fInt = fInt * 10.0f + (ch - '0');
} else if (ch == '.') {
bDec = true;
} else break;
}
p++;
}
float result = fInt + fDec;
return bNegative ? -result : result;
}
Unicode 版 StrToFloatW 邏輯完全一致,僅將 char 換為 wchar_t、字面量加 L 前綴,並通過宏 StrToFloat 根據 UNICODE 自動切換。
| 輸入 | 預期行為 |
|---|---|
L"12.34" | 正常轉換 12.34 |
L"a23" | 首字符非法,返回 0 |
L"1234" | 純整數 |
L"12.34.56" | 第二個點截斷,返回 12.34 |
L".34" | 無整數部,返回 0.34 |
L"-56.34" | 負數 |
L"-." | 僅符號+點,返回 -0 |
L"-0" | 負零 |
1.23e-4),需擴展狀態機處理 e/E。double 或 long double 累加,最後再縮窄。inf,可引入 FLT_MAX 邊界判斷。strtod 會跳過前導空白。這份實現展示了「單遍歷 + 狀態機 + 雙累加」的經典模式,代碼清晰、邊界處理完善,極適合面試白板寫代碼或嵌入式無庫環境移植。讀者可在其基礎上按需擴展科學計數法、錯誤碼返回等特性。