0

更具体地说,我想确保这种类型是双精度(或 int/float)。我已经远近搜索,发现几乎为零的非严格解决方案。我只想使用我能完全理解的代码,作为一个完整的 C++ 初学者。

在 Java 中,我可以简单地做这样的事情:

ArrayList<Double> data = new ArrayList<Double>();
Scanner in = new Scanner(System.in);
while (in.hasNextDouble()) {
        double x = in.nextDouble();
        data.add(x); 
        n += 1;      
        sum += x;    
}  
double average = sum / n; 

C++ 显然是一个不同的故事。这是我尝试过的:

vector<double> data;
while (looping) 
{
    cin >> x;
    if (typeid(x) != typeid(float) && typeid(x) != typeid(double) &&
        typeid(x) != typeid(int))
            {looping = false; break;}
    data.push_back(x);
    n += 1;
    sum += x;
}
double average = sum / n;

这行不通。随着输入双打,循环继续进行,但是一旦我输入不是双打的东西,代码就会停止并且不会继续前进。我很沮丧。有什么建议么?

4

3 回答 3

3

用户没有“输入变量”。她输入一个字符串。当提供浮点变量时,运算符>>会尝试将此字符串解释为浮点数的文本表示。

它可能成功也可能不成功:在 Java 中,失败会导致nextDouble()抛出异常。在 C++ 中,流操作不会抛出;相反,失败意味着cin.good()将开始返回false

float x;
cin >> x;
while (cin.good()) 
{   
    data.push_back(x);
    n += 1;
    sum += x;
    cin >> x;
}
于 2013-10-29T06:30:11.627 回答
0

您在这里有几个解决方案。我将发布其中的 2 个。由于stod功能原因,第一个解决方案需要 c++11 标准。您可以将-std=c++11标志传递给gccclang++。Microsoft 编译器默认启用 c++11。

解决方案 1。它包括通过cin >> input_string和使用标准 c++11 函数一直读取字符串stod。stod 代表字符串加倍。如果stod无法解析 a double,它将抛出std::invalid_argument异常。

这个解决方案是这样的:

#include <iostream>
#include <vector>
#include <numeric>
#include <string>
#include <stdexcept>

using namespace std;


int main() {
   vector<double> vec;
   string input;
   try {
      while (getline(cin, input)) {
         vec.push_back(stod(input));

      }
   }
   catch (std::invalid_argument &) {
      cout << "Invalid argument caught\n";
      //Failed to parse a double
   }
   //If pressed Ctrl+D (in linux, which sends EOF), failbit and eofbit are set
   //If it is through invalid_argument the way the loop was exit, then,
   //eof and failbit are not set and cin can be used without clearing.
   double average = accumulate(vec.begin(), vec.end(), 0.0)/vec.size();
   cout << "EOF: " << cin.eof() << endl;
   cout << "Fail: " << cin.fail() << endl;

   //Clean eof and failbit to be able to use cin again
   cin.clear();
   cout << "EOF after cleaning: " << cin.eof() << endl;
   cout << "Fail after cleaning: " << cin.fail() << endl;

   cout << average << endl;

}

编辑:我测试过,当你每行输入多个数字时,它只会得到第一个而不会抛出std::invalid_argument. std::invalid_argument只有当你开始一行时,它才会抛出一个非双精度的行。这是因为该stod函数的行为如下:stod reference

请注意,此解决方案仅允许每行读取一个双精度。

解决方案 2。直接阅读使用cin >> input_double。这可能会失败。请注意,iostream在 c++ 中,默认情况下 s 不使用 exceptionios。您可以使用 api 激活它们,但我不建议您这样做,因为您可以在本地管理所有错误处理。

您可以读取由任何空格字符分隔的任意数量的双精度数:

#include <iostream>
#include <vector>
#include <numeric>
#include <limits>

using namespace std;


int main() {
   double x = 0.0;
   vector<double> data;

   //cin will fail to read the first non-double in the input.
   //You can input as many doubles as you wish. Spaces will
   //be ignored. At the first non-double, cin will fail to read
   //and will exit the loop, setting istream::failbit.
   //Alternatively, you can send EOF (Linux is Ctrl+D) and the loop also will finish.
   while (cin >> x) {
      data.push_back(x);

   }
   double average = accumulate(data.begin(), data.end(), 0.0)/data.size();

   //If you wanted to use again cin, you should:
   //1. Clear failbit. You can do like this:
   cin.clear();

   //2. Cleaning the remaining input. Will stop when finding end of line.
   string rubbish;
   geline(cin, rubbish);
   //cin is usable here again if you need it and with the input clean already.


   cout << average << '\n';
}

您可以在一行中在输入中给出类似的内容:

1 2.4 -38.7 5.8 28.9 你好。

会发生什么?循环将消耗到 28.9,在 hello 停止。之后,设置失败位。我们清理 failbit 以便能够继续阅读直到行尾。由于 hello 被认为是“垃圾”,因为我们想读取双打,我们用 a 清理它,getline我们可以cin再次使用而不会遇到麻烦。

于 2013-10-29T06:50:47.573 回答
0

如果 x 被声明为 double,您的 if 条件将失败,因此 while 循环被破坏

于 2013-10-29T06:21:55.553 回答