分析:此题虽然类似于atoi函数,但毕竟double为64位, 而且支持小数,因而边界条件更加严格,写代码时需要更加注意。
#include <errno.h>
#include <float.h>
#include <stdio.h>
#include <stdlib.h>
#include "math.h"
enum status {
invaild = 0, vaild
};
int g_status = vaild;
int isspace(const char* str) {
return *str == ' ';
}
int isDigit(char num) {
if (num >= '0' && num <= '9') {
return 1;
} else {
return 0;
}
}
//对atof函数进行扩充,使其可以处理科学计数法形式的字符如 123.45e-6
double strToDouble(const char* nptr) {
double val = 0, power = 1;
int exp = 0;
if (nptr == NULL) {
return 0;
}
g_status = invaild;
//跳过空格
while (*nptr == ' ') {
nptr++;
}
int flag = *nptr == '-' ? -1 : 1;
if (*nptr == '-' || *nptr == '+') {
nptr++;
}
while (isDigit(*nptr)) {
val = val * 10 + *(nptr++) - '0';
}
if (*nptr == '.') {
nptr++;
}
while (isDigit(*nptr)) {
val = val * 10 + *(nptr++) - '0';
power *= 10;
}
val = val / power;
if (*nptr == 'e' || *nptr == 'E') {
nptr++;
int eflag = *nptr == '-' ? -1 : 1;
if (*nptr == '-' || *nptr == '+') {
nptr++;
}
while (isDigit(*nptr)) {
exp = exp * 10 + *(nptr++) - '0';
}
//是否越界
// else
if (eflag == 1) {
if (val > DBL_MAX * pow(10.0, (double) -exp)) {
return DBL_MAX;
}
while (exp-- > 0) {
val *= 10;
}
} else if (eflag == -1) {
if (val < DBL_MIN * pow(10.0, (double) exp)) {
return DBL_MIN;
}
while (exp-- > 0) {
val /= 10;
}
}
}
if (*nptr == '\0') {
g_status = vaild;
}
return flag * val;
}
int main(void) {
// DBL_MIN: 2.2250738585072014e-308
// DBL_MAX: 1.7976931348623157e+308
setvbuf(stdout, NULL, _IONBF, 0);
char str[100] = "1.79e308";
double num;
num = strToDouble(str);
if (g_status) {
printf("%.16e\n", num);
} else {
printf("%s", "invaild input!!!");
}
return EXIT_SUCCESS;
}