C语言 atof()的实现

来源:互联网 发布:地图数据采集gis 编辑:程序博客网 时间:2024/05/18 00:04

网上搜了几个关于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()实现,注释附有解释,若有疑问或批评和建议,敬请指正。

0 0
原创粉丝点击