更具体地说,我想确保这个类型是double(或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;
这不起作用。循环在输入双精度时继续运行,但是一旦我输入的东西不是双精度,代码就会停止并且不会继续前进。我很沮丧。有什么建议吗?
答案 0 :(得分:3)
用户不“输入变量”。她输了一个字符串。当提供float变量时,运算符>>
尝试将此字符串解释为浮点数的文本表示。
它可能成功也可能不成功:在Java中,失败会导致nextDouble()
抛出异常。在C ++中,流操作不会抛出;相反,失败意味着cin.good()
将开始返回false
。
float x;
cin >> x;
while (cin.good())
{
data.push_back(x);
n += 1;
sum += x;
cin >> x;
}
答案 1 :(得分:0)
如果x被声明为double,则if条件将失败,因此while循环被破坏
答案 2 :(得分:0)
这里有几个解决方案。我会发布其中2个。由于stod
函数,第一个解决方案需要c ++ 11标准。您可以将-std=c++11
标记传递给gcc
或clang++
。 Microsoft编译器默认启用c ++ 11。
解决方案1 。它包括通过cin >> input_string
和使用标准c ++ 11函数stod
一直读取字符串。 stod代表字符串加倍。如果stod
无法解析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 ++中默认不使用exceptios。您可以使用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,停在你好。之后,设置failbit。我们清理failbit以便能够继续阅读直到行结束。因为hello被认为是“垃圾”,因为我们想读取双打,我们用getline
清理它,我们可以再次使用cin
而不会有麻烦。