strtod.c 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. #include <math.h>
  2. #include <errno.h>
  3. /*
  4. * bug: should detect overflow, set errno = ERANGE, and return +/- HUGE_VAL
  5. */
  6. double
  7. strtod(const char *cp, char **endptr)
  8. {
  9. double num, dem;
  10. extern double pow10(int);
  11. int neg, eneg, dig, predig, exp, c;
  12. const char *p;
  13. p = cp;
  14. num = 0;
  15. neg = 0;
  16. dig = 0;
  17. predig = 0;
  18. exp = 0;
  19. eneg = 0;
  20. c = *p++;
  21. while(c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\v' || c == '\r')
  22. c = *p++;
  23. if(c == '-' || c == '+'){
  24. if(c == '-')
  25. neg = 1;
  26. c = *p++;
  27. }
  28. while(c >= '0' && c <= '9'){
  29. num = num*10 + c-'0';
  30. predig++;
  31. c = *p++;
  32. }
  33. if(c == '.')
  34. c = *p++;
  35. while(c >= '0' && c <= '9'){
  36. num = num*10 + c-'0';
  37. dig++;
  38. c = *p++;
  39. }
  40. if(dig+predig == 0){
  41. if(endptr)
  42. *endptr = (char *)cp;
  43. return 0.0;
  44. }
  45. if(c == 'e' || c == 'E'){
  46. c = *p++;
  47. if(c == '-' || c == '+'){
  48. if(c == '-'){
  49. dig = -dig;
  50. eneg = 1;
  51. }
  52. c = *p++;
  53. }
  54. while(c >= '0' && c <= '9'){
  55. exp = exp*10 + c-'0';
  56. c = *p++;
  57. }
  58. }
  59. exp -= dig;
  60. if(exp < 0){
  61. exp = -exp;
  62. eneg = !eneg;
  63. }
  64. dem = pow10(exp);
  65. if(dem==HUGE_VAL)
  66. num = eneg? 0.0 : HUGE_VAL;
  67. else if(dem==0)
  68. num = eneg? HUGE_VAL : 0.0;
  69. else if(eneg)
  70. num /= dem;
  71. else
  72. num *= dem;
  73. if(neg)
  74. num = -num;
  75. if(endptr){
  76. *endptr = (char *)--p;
  77. /*
  78. * Fix cases like 2.3e+
  79. */
  80. while(p > cp){
  81. c = *--p;
  82. if(c!='-' && c!='+' && c!='e' && c!='E')
  83. break;
  84. (*endptr)--;
  85. }
  86. }
  87. return num;
  88. }