您在这里有几个解决方案。我将发布其中的 2 个。由于stod
功能原因,第一个解决方案需要 c++11 标准。您可以将-std=c++11
标志传递给gcc
或clang++
。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
再次使用而不会遇到麻烦。