/*
* 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;
}
C 标准库 atof 函数的实现
最新推荐文章于 2023-08-24 19:11:01 发布