C語言 atof()的實現

網上搜了幾個關於atof()實現的博客,實現的都不是很全面,有的未考慮科學計數法,有的未考慮非法輸入,所以打算自己實現atof()。

函數實現要求:

  1. 將字符串表示的浮點數轉化爲double類型;
  2. 可以採用科學計數法,如1.34e3 代表 1340.0;
  3. 忽略前置空格;
  4. 能夠考慮正負數值;
  5. 能夠識別非法輸入;(截斷至非法字符處,如atof(” 12.2c32”)輸出爲12.2)。

函數原型:

double my_atof(const char *str);

爲了提高效率,我們只能遍歷一次字符串,爲此我們需要小數點及e或E的位置。

double my_atof(const char *str){
    const char *p = str;
    int sign = 1;
    while (*p == ' ')++p;//忽略前置空格
    if (*p == '-')//考慮是否有符號位
    {
        sign = -1;
        ++p;
    }
    else if (*p == '+')
        ++p;
    int hasDot = 0,hasE = 0;
    double integerPart = 0.0,decimalPart = 0.0;
    //遇到'e''.'字符則退出循環,設置hasE和hasDot。
    for (; *p; ++p){
        if (isdigit(*p)) //若p指向的字符爲數字則計算當前整數部分的值
            integerPart = 10 * integerPart + *p - '0';
        else if (*p == '.'){
            hasDot = 1;
            p++;
            break;
        }
        else if (*p == 'e' || *p == 'E'){
            hasE = 1;
            p++;
            break;
        }
        else  //如果遇到非法字符,則截取合法字符得到的數值,返回結果。
            return integerPart;
    }

//上一部分循環中斷有三種情況,一是遍歷完成,這種情況下一部分的循環會自動跳過;其次便是是遇到'.''e',兩種hasE和hasDot只可能一個爲真,若hasDot爲真則計算小數部分,若hasE爲真則計算指數部分。
    int decimalDigits = 1;
    int exponential = 0;    
    for (; *p; p++){
        if (hasDot && isdigit(*p))
            decimalPart += (*p - '0') / pow(10, decimalDigits++);
        else if (hasDot && (*p == 'e' || *p == 'E')) {
            integerPart += decimalPart;
            decimalPart = 0.0;
            hasE = 1;
            ++p;
            break;
        }
        else if (hasE && isdigit(*p))
            exponential = 10 * exponential + *p - '0';
        else break;
    }
//上一部分較難理解的就是else if (hasDot && (*p == 'e' || *p == 'E')) 這一特殊情況,對於合法的浮點數,出現'.'字符後,仍然有可能是科學計數法表示,但是出現'e'之後,指數部分不能爲小數(這符合<string.h>對atof()的定義)。這種情況變量IntegerPart和decimalPart都是科學計數法的基數,因此有integerPart += decimalPart(這使得IntergerPart的命名可能欠妥,BasePart可能是一種好的選擇)。
//上一部分循環結束一般情況下就能返回結果了,除非遇到前文所述的特殊情況,對於特殊情況需要繼續計算指數。
    if (hasE && hasDot)
        for (; *p; p++)
            if (isdigit(*p))
                exponential = 10 * exponential + *p - '0';
    return sign * (integerPart * pow(10, exponential) + decimalPart);

    }

以上便是我的atof()實現,註釋附有解釋,若有疑問或批評和建議,敬請指正。

發佈了31 篇原創文章 · 獲贊 26 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章