fork download
  1. #include <fstream>
  2. #include <iostream>
  3. #include <sstream>
  4. #include <limits>
  5.  
  6. struct double_istream
  7. {
  8. std::istream &in;
  9.  
  10. double_istream (std::istream &i) : in(i) {}
  11.  
  12. double_istream & parse_on_fail (double &x, bool neg)
  13. {
  14. const char *exp[] = {"", "inf", "Inf", "NaN", "nan"};
  15. const char *e = exp[0];
  16. int l = 0;
  17. char parsed[4];
  18. char *c = parsed;
  19. if (neg) *c++ = '-';
  20. in.clear();
  21. if (!(in >> *c).good()) return *this; //If the stream is broken even before trying to read from it, it's pointless to try.
  22.  
  23. switch (*c) //Switch on the first character to parse, if 'i' or 'I', set up for Infinity, else if 'n' or 'N', set up for NaN
  24. {
  25. case 'i': e = exp[l=1]; break;
  26. case 'I': e = exp[l=2]; break;
  27. case 'N': e = exp[l=3]; break;
  28. case 'n': e = exp[l=4]; break;
  29. }
  30.  
  31. while (*c == *e)
  32. {
  33. if ((e-exp[l]) == 2) break;
  34. ++e;
  35. if (!(in >> *++c).good()) break;
  36. }
  37.  
  38. if (in.good() && *c == *e)
  39. {
  40. switch (l)
  41. {
  42. case 1: case 2: x = std::numeric_limits<double>::infinity(); break;
  43. case 3: case 4: x = std::numeric_limits<double>::quiet_NaN(); break;
  44. }
  45. if (neg) x = -x;
  46. return *this;
  47. }
  48. else if (!in.good())
  49. {
  50. if (!in.fail()) return *this;
  51. in.clear(); --c;
  52. }
  53.  
  54. do { in.putback(*c); } while (c-- != parsed);
  55. in.setstate(std::ios_base::failbit);
  56. return *this;
  57. }
  58.  
  59. double_istream & operator >> (double &x) {
  60. bool neg = false;
  61. char c;
  62. if (!in.good()) return *this;
  63. while (isspace(c = in.peek())) in.get();
  64. if (c == '-') { neg = true; }
  65. in >> x;
  66. if (! in.fail()) return *this;
  67. return parse_on_fail(x, neg);
  68. }
  69. };
  70.  
  71. struct double_imanip
  72. {
  73. mutable std::istream *in;
  74.  
  75. const double_imanip & operator >> (double &x) const
  76. {
  77. double_istream(*in) >> x;
  78. return *this;
  79. }
  80.  
  81. std::istream & operator >> (const double_imanip &) const
  82. {
  83. return *in;
  84. }
  85. };
  86.  
  87. const double_imanip & operator >> (std::istream &in, const double_imanip &dm)
  88. {
  89. dm.in = &in;
  90. return dm;
  91. }
  92.  
  93. int main()
  94. {
  95. std::stringstream iss("1.0 -NaN inf Inf nan -inf NaN 1.2 inf");
  96. double u, v, w, x, y, z, a, b, fail_double;
  97. std::string fail_string;
  98. iss >> double_imanip()
  99. >> u >> v >> w >> x >> y >> z >> a >> b
  100. >> double_imanip()
  101. >> fail_double;
  102. std::cout << u << " " << v << " " << w << " "
  103. << x << " " << y << " " << z << " " << a << " " << b << std::endl;
  104. if (iss.fail()) {
  105. iss.clear();
  106. iss >> fail_string;
  107. std::cout << fail_string << std::endl;
  108. } else {
  109. std::cout << "TEST FAILED" << std::endl;
  110. }
  111. }
Success #stdin #stdout 0.01s 2864KB
stdin
Standard input is empty
stdout
1 nan inf inf nan -inf nan 1.2
inf