首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

面試必考:浮點數字串轉浮點數完整實作(支援正負、科學計數法擴展)

     編輯:關於C語言

題目背景

面試高頻題:實現 float StrToFloat(const char* str),將字串轉為浮點數,不得呼叫任何庫函式(atof、strtod 等),迴圈極少,考慮完整邊界情況。

核心難點

  • 正負號處理。
  • 小數點分割整數/小數部分。
  • 非數字字元提前結束(如 "12.34.56"、"34a")。
  • 純小數(".34")、純整數("1234")、負數("-56.34")。
  • 多重小數點、尾部垃圾字元的截斷語意。

完整實作(ANSI C 風格,含 Unicode 版)

// 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;
}

設計亮點

  1. 單次遍歷:一個 while 迴圈搞定整數/小數/結束。
  2. 狀態機:bDec 標記是否進入小數態,邏輯清晰。
  3. 提前結束:遇非預期字元即 break,符合「掃描至無法解析為止」語意。
  4. 無庫依賴:純手寫運算,面試環境可直接編譯跑測試。
  5. Unicode 就緒:StrToFloatW + TCHAR 巨集切換。

可擴展方向

  • 支援科學計數法(1.23e-4):需增加指數部分解析、pow10 計算。
  • 回傳 double 提高精度。
  • 錯誤碼輸出參數(區分「0」與「解析失敗」)。
  • 溢位檢查(FLT_MAX)。

作者註記

作者:magictong。歡迎繼續挖掘潛在 Bug(如極長字串精度、Denormal 數處理)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved