fork(4) download
  1. #include <stdio.h>
  2. #include <math.h>
  3. #include <stdlib.h>
  4.  
  5. // SVG specs for numbers :
  6. //
  7. // number ::= integer ([Ee] integer)?
  8. // | [+-]? [0-9]* "." [0-9]+ ([Ee] integer)?
  9.  
  10. #define TRY(S) printf("%10s => %f (error is %g)\n", #S, my_atof(#S, NULL), my_atof(#S, NULL) - atof(#S));
  11. #define TRY_BAD(S) printf("%10s %f fails at:", #S, my_atof(#S, &end)); printf("%s\n", end);
  12.  
  13. float my_atof(const char *str, char ** last)
  14. {
  15. char * end = (char*)str;
  16.  
  17. float res = (float)strtoll(str, &end, 10);
  18. int badConv = end == str;
  19. float sign = res < 0 || (*end == '-' && ++end) ? -1 : (end == str && *end == '+' && ++end) || 1; // Trim sign
  20.  
  21. if (badConv && *end != '.') // Invalid input
  22. {
  23. if (last != NULL) *last = (char*)str;
  24. return 0;
  25. }
  26.  
  27.  
  28. if (*end == '.')
  29. {
  30. char* beg = ++end, *tmp = 0; // So end is correct when returning below
  31. long long frac = strtoll(beg, &tmp, 10);
  32. if (*beg < '0' || *beg > '9')
  33. {
  34. if (last != NULL) *last = badConv ? str : end;
  35. return res;
  36. }
  37. end = tmp;
  38. res += sign * frac/pow(10, end-beg);
  39. }
  40.  
  41. if (*end == 'e' || *end == 'E')
  42. {
  43. char * tmp = 0;
  44. res *= pow(10, strtol(end+1, &tmp, 10));
  45. if (tmp != end + 1) end = tmp; // Reject 34e as 34 followed by e
  46. }
  47.  
  48. if (last != NULL) *last = end;
  49. return res;
  50. }
  51.  
  52. int main(void) {
  53. TRY(-5);
  54. TRY(+5);
  55. TRY(-5.1);
  56. TRY(.5);
  57. TRY(.5e2);
  58. TRY(.5541e-2);
  59. TRY(.5e+2);
  60. TRY(+.57e-2);
  61. TRY(+.001e+1);
  62. char * end = 0;
  63. TRY_BAD(34f4);
  64. TRY_BAD(34.+44);
  65. TRY_BAD(34.-44);
  66. TRY_BAD(+.f)
  67. TRY_BAD(+e10)
  68. TRY_BAD(+.e10)
  69. TRY_BAD(34e)
  70. TRY_BAD(+33+4)
  71. return 0;
  72. }
  73.  
Success #stdin #stdout 0s 9432KB
stdin
Standard input is empty
stdout
        -5 => -5.000000 (error is 0)
        +5 => 5.000000 (error is 0)
      -5.1 => -5.100000 (error is 9.53674e-08)
        .5 => 0.500000 (error is 0)
      .5e2 => 50.000000 (error is 0)
  .5541e-2 => 0.005541 (error is -4.161e-10)
     .5e+2 => 50.000000 (error is 0)
   +.57e-2 => 0.005700 (error is 9.61125e-11)
  +.001e+1 => 0.010000 (error is 7.07805e-10)
      34f4 34.000000 fails at:f4
    34.+44 34.000000 fails at:+44
    34.-44 34.000000 fails at:-44
       +.f 0.000000 fails at:+.f
      +e10 0.000000 fails at:+e10
     +.e10 0.000000 fails at:+.e10
       34e 34.000000 fails at:e
     +33+4 33.000000 fails at:+4