面試高頻題:實現 float StrToFloat(const char* str),將字串轉為浮點數,不得呼叫任何庫函式(atof、strtod 等),迴圈極少,考慮完整邊界情況。
"12.34.56"、"34a")。".34")、純整數("1234")、負數("-56.34")。// StringToFloat.h
#ifndef __STRINGTOFLOAT_H__
#define __STRINGTOFLOAT_H__
float StrToFloatW(const wchar_t* pstrfloat);
float StrToFloatA(const char* pstrfloat);
#if defined(UNICODE) || defined(_UNICODE)
#define StrToFloat StrToFloatW
#else
#define StrToFloat StrToFloatA
#endif
#endif
// StringToFloat.c
#include "StringToFloat.h"
#pragma warning(disable:4244)
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, fDecPow = 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') * fDecPow;
fDecPow *= 0.1f;
} else break; // 非數字結束
} else { // 整數部分
if (ch >= '0' && ch <= '9') {
fInt = fInt * 10.0f + (ch - '0');
} else if (ch == '.') {
bDec = true; // 進入小數模式
} else break; // 非數字/非點結束
}
++p;
}
return bNegative ? -(fInt + fDec) : (fInt + fDec);
}
float StrToFloatW(const wchar_t* pstrfloat) {
if (!pstrfloat) return 0.0f;
bool bNegative = false, bDec = false;
const wchar_t* p = pstrfloat;
float fInt = 0.0f, fDec = 0.0f, fDecPow = 0.1f;
if (*p == L'-') { bNegative = true; ++p; }
else if (*p == L'+') { ++p; }
while (*p != L'\0') {
wchar_t ch = *p;
if (bDec) {
if (ch >= L'0' && ch <= L'9') {
fDec += (ch - L'0') * fDecPow;
fDecPow *= 0.1f;
} else break;
} else {
if (ch >= L'0' && ch <= L'9') {
fInt = fInt * 10.0f + (ch - L'0');
} else if (ch == L'.') {
bDec = true;
} else break;
}
++p;
}
return bNegative ? -(fInt + fDec) : (fInt + fDec);
}
int _tmain(int argc, _TCHAR* argv[]) {
float v;
v = StrToFloat(L"12.34"); // 12.34
v = StrToFloat(L"a23"); // 0 (首字元非數)
v = StrToFloat(L"1234"); // 1234
v = StrToFloat(L"12.34.56"); // 12.34 (第二個點結束)
v = StrToFloat(L".34"); // 0.34
v = StrToFloat(L"34a"); // 34
v = StrToFloat(L"34a.456"); // 34
v = StrToFloat(L"-34"); // -34
v = StrToFloat(L"-56.34"); // -56.34
v = StrToFloat(L"-3.45.67"); // -3.45
v = StrToFloat(L"-.45.6a"); // -0.45
v = StrToFloat(L"-."); // -0
v = StrToFloat(L"-0"); // -0
return 0;
}
while 迴圈搞定整數/小數/結束。bDec 標記是否進入小數態,邏輯清晰。break,符合「掃描至無法解析為止」語意。StrToFloatW + TCHAR 巨集切換。1.23e-4):需增加指數部分解析、pow10 計算。double 提高精度。FLT_MAX)。作者:magictong。歡迎繼續挖掘潛在 Bug(如極長字串精度、Denormal 數處理)。