分析:此题虽然类似于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; }