Ввод-вывод NaN ASCII с Visual C ++

Я хочу читать и записывать значения NaN из / в текстовые файлы с помощью iostream и Visual C ++. При записи значения NaN я получаю 1. # QNAN . Но, читая его обратно, вы получите 1.0 .

float nan = std::numeric_limits<float>::quiet_NaN ();
std::ofstream os("output.txt");

os << nan ;
os.close();

Результат: 1. # QNAN .

std::ifstream is("output.txt");
is >> nan ;
is.close();

нан равно 1,0 .

Решение

Наконец, как было предложено awoodland, я придумал это решение. Я выбрал nan как строковое представление NaN. Оба оператора << и >> переопределяются.

using namespace ::std;

class NaNStream 
{
public:
  NaNStream(ostream& _out, istream& _in):out(_out), in(_in){}
  template<typename T>
  const NaNStream& operator<<(const T& v) const {out << v;return *this;}
  template<typename T>
  const NaNStream& operator>>(T& v) const {in >> v;return *this;}
protected:
  ostream& out;
  istream& in;
};

// override << operator for float type
template <> const NaNStream& NaNStream::operator<<(const float& v) const 
{
  // test whether v is NaN 
  if( v == v )
    out << v;
  else
    out << "nan";
  return *this;
}

// override >> operator for float type
template <> const NaNStream& NaNStream::operator>>(float& v) const 
{
  if (in >> v)
    return *this;

  in.clear();
  std::string str;
  if (!(in >> str))
    return *this;

  if (str == "nan")
    v = std::numeric_limits<float>::quiet_NaN();
  else
    in.setstate(std::ios::badbit); // Whoops, we've still "stolen" the string

  return *this;
}

Минимальный рабочий пример: конечное число с плавающей запятой и NaN записываются в строковый поток, а затем считываются обратно.

int main(int,char**) 
{
  std::stringstream ss;
  NaNStream nis(ss, ss);
  nis << 1.5f << std::numeric_limits<float>::quiet_NaN ();
  std::cout << ss.str() << std::endl; // OUTPUT : "1.5nan"

  float a, b;
  nis >> a;  nis >> b;
  std::cout << a << b << std::endl;  // OUTPUT : "1.51.#QNAN"
}
17
задан mskfisher 9 May 2012 в 19:09
поделиться