`cin`错误地在Mac上解析`double`输入

时间:2017-06-07 14:15:26

标签: c++ macos clang cin

一点背景 - 我是学习C ++的新手。我正在使用 Accelerated C ++ 并继续学习。在第4章中,我所获得的代码并没有像书中所说的那样完成,我已经仔细检查了所有代码,以确保我没有输入错误的内容从他们的例子(我无论如何都看不到任何错误)。

我有以下结构和两个函数:

struct Student {
  std::string        name;
  double             midtermGrade, finalGrade;
  std::vector<double>homework;
};

std::istream& read(std::istream& is, Student& s) {
  is >> s.name >> s.midtermGrade >> s.finalGrade;

  std::cout << std::endl << "Name: " << s.name << std::endl
            << " - Md: " << s.midtermGrade << std::endl
            << " - Fn: " << s.finalGrade << std::endl;

  read_hw(is, s.homework);

  return is;
}

std::istream& read_hw(std::istream& in, std::vector<double>& hw) {
  if (in) {
    hw.clear();

    double h;

    while (in >> h) {
      std::cout << " - Hw: " << h << std::endl;
      hw.push_back(h);
    }

    in.clear();
  }

  return in;
}

int main()我正在调用这样的代码:

Student record;
while (read(std::cin, record)) {

如果我编译并运行,然后粘贴(或键入)以下输入,我得到以下输出:

// Input
Johnny 70 80 50 Fred 95 90 100 Joe 40 40 50

// Output
Name: Johnny
 - Md: 70
 - Fn: 80
 - Hw: 50

Name: red
 - Md: 95
 - Fn: 90
 - Hw: 100

Name: Joe
 - Md: 40
 - Fn: 40
 - Hw: 50

正如你所看到的,&#34;弗雷德&#34;已成为&#34; red&#34;。我用一大堆名字试过这个;任何以A-F开头的东西都会受到同一问题的影响,这使我怀疑它可能是一个十六进制问题。然而,&#34;尼克&#34;成为&#34; k&#34;和&#34; Xander&#34;简单地变成&#34; r&#34;。

我完全不知所措。你知道发生了什么吗?

根据要求,这是一个MCVE:

#include <iomanip>
#include <iostream>
#include <string>
#include <vector>

struct Student {
  std::string        name;
  double             midtermGrade, finalGrade;
  std::vector<double>homework;
};

std::istream& read_hw(std::istream& in, std::vector<double>& hw) {
  if (in) {
    hw.clear();

    double h;

    while (in >> h) {
      std::cout << " - Hw: " << h << std::endl;
      hw.push_back(h);
    }

    in.clear();
  }

  return in;
}

std::istream& read(std::istream& is, Student& s) {
  is >> s.name >> s.midtermGrade >> s.finalGrade;

  std::cout << std::endl << "Name: " << s.name << std::endl
            << " - Md: " << s.midtermGrade << std::endl
            << " - Fn: " << s.finalGrade << std::endl;

  read_hw(is, s.homework);

  return is;
}

int main()
{
  Student record;

  std::vector<Student> students;

  while (read(std::cin, record)) {}

  return 0;
}

2 个答案:

答案 0 :(得分:3)

进一步研究后,libc++似乎没有按照您的方式从cin读取双打。我不确定它是否只是特别加倍,但我认为可能是。它似乎只影响OSX上的Clang编译器,它的真的令人讨厌:P

对于TL; DR版本,请参阅David已接受的答案。

我目前尚未发现任何良好修复程序,但如果您添加编译器标记-stdlib=libstdc++,则可以强制它使用较旧的,已弃用的stdlib按预期工作。显然它的功能较少(在我的示例中,std::sortstd::domain_error缺失)。其他选项包括不使用double并对输入进行进一步解析(尽管我不熟悉C ++,但我并不喜欢那个我害怕的人)。 / p>

相关阅读:

official bug report于3。5年前开放,但仍未解决。

答案 1 :(得分:2)

如果您对如何决定某事是否为double有特定要求,则必须编写实现这些要求的代码。该标准允许丢弃任何可能属于有效浮点表示的前导字符。字母喜欢&#34; e&#34;,&#34; i&#34;,&#34; n&#34;和&#34; f&#34;可以是有效浮点表示的一部分。

为什么这种编码永远不是一个好主意,请参阅Falsehoods Programmers Believe About Names,特别是15号。