C 标准库 atof 函数的实现

/*
 * atof 是一个解析字符串的一个函数
 * 可以将字符串解析为 double 类型
 * 解决如下的问题:
 *   1 空白符
 *   2 正号和负号
 *   3 进制
 *   4 溢出
 *   5 小数 指数 处理
 */
#include <cstdio>

double atof(const char *str) {
    char *p = (char *)str;
    double ret;
    int sign;
    int base;
    int e = 0;
    int decimal = 0;
    int e_sign;

    // 跳过空白符
    while (*p==' ' || *p=='\t') {
        ++p;
    }

    // 判定符号
    if (*p=='-') sign=-1, ++p;
    else if (*p=='+') sign=1, ++p;
    else sign = 1;

    // 判定进制位
    if (*(p+1)=='x' || *(p+1)=='X' && *p=='0') base=16, p+=2;
    else base = 10;

    // 处理整数部分 和 小数部分
    // 如果可以将整数部分和小数部分分开处理, 这样可以保持精度
    ret = 0.0f;
    while (1) {
        if (*p>='0' && *p<='9') {
            ret *= base;
            ret += *p - '0';
        }
        else if (base==16 && ((*p>='a'&&*p<='f') || (*p>='A'&&*p<='F'))) {
            ret *= base;
            switch (*p) {
                case 'a': case 'A': ret += 10; break;
                case 'b': case 'B': ret += 11; break;
                case 'c': case 'C': ret += 12; break;
                case 'd': case 'D': ret += 13; break;
                case 'e': case 'E': ret += 14; break;
                case 'f': case 'F': ret += 15; break;
                default: break;
            }
        }
        else if (*p == '.'){
            ++decimal;
        }
        else {
            break;
        }

        if (decimal) ++decimal;
        ++p;
    }
    if (decimal) decimal-=2;

    // 处理指数部分
    if (*p=='e' || *p=='E') {
        ++p;
        if (*p == '-') e_sign=-1, ++p;
        else if (*p == '+') e_sign=1, ++p;
        else e_sign=1;

        while (*p>='0' && *p<='9') {
            e *= 10;
            e += *p - '0';
            ++p;
        }

        if (e_sign == -1) e = -e;
    }

    e -= decimal;

    while (e>0) {
        ret *= base;
        --e;
    }

    while (e<0) {
        ret /= base;
        ++e;
    }

    if (sign == -1) ret = -ret;

    return ret;
}

int main() {
    printf("%lf\n", atof("3.1415"));
    printf("%lf\n", atof("-3.1415"));
    printf("%lf\n", atof("333333333333333333333333333333333333333333.1415"));
    printf("%.40lf\n", atof("3.141505555555555555555555555555555555555555"));
    printf("%lf\n", atof("0xe"));
    printf("%lf\n", atof("-14e-2"));
    printf("%lf\n", atof("-14e2"));
    printf("%lf\n", atof("3.14e3.122"));
    printf("%lf\n", atof("3.14e-3.122"));
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值