everyone, here is a function I wrote to read a user input which is a vector of double of unknown size, the input must terminate when 'enter' is pressed:
vector<double> read_array()
{
vector<double> array_in;
double el;
while (!cin.get())
{
cin >> el;
array_in.push_back(el);
}
return array_in;
}
To illustrate it consider the following code:
void init() // the function that calls the read_array function
{
cout << "Enter array X: " << endl;
vector<double> X = read_array();
int l = X.size();
cout << l << endl;
}
A typical input when promted is: 1(space)2(space)3(space)4(enter)
When enter is pressed, the input terminates, and the variable 'l' is initialised but is equal to 0 However, when the enter key is pressed, the array size is 0. Debugging it makes it look like it never makes it into the loop like that.
The same routine works well if the input value is not an array.
Thanks to everyone in advance!
I don't know what you hope std::cin.get()
does but based on your comment it seems you hope that it somehow deals with end of lines: it doesn't. It simply reads the next character which is unlikely to do you much good. In particular, if the character is anything but '\0'
negating it will result in the boolean value false
. That said, the loop should in principle work unless you only input a single digit numeric value followed (possibly after space) by a non-digit or the end of the input.
The easiest approach to deal with line-based input is to read the line into a std::string
using std::getline()
and then to parse the line using std::istringstream
:
std::vector<double> read_array() {
std::vector<double> result;
if (std::string line; std::getline(std::cin, line)) {
std::istringstream lin(line);
for (double tmp; std::cin >> tmp; ) {
result.push_back(tmp);
}
}
return result;
}
As std::cin
is only involved while reading lines, std::cin.fail()
won't be set when parsing double
s fails. That is, you can read multiple lines with arrays of double
s, each of which can also be empty.
If you don't want to read an auxiliary line, you'll need to understand a bit more about how formatted input in C++ works: it starts off skipping whitespace. As newlines are whitespace you need to rather read the whitespace yourself and stop if it happens to be a newline or non-whitespace. I'd use a function doing this skipping which returns false
if it reached a newline (which is still extracted):
bool skip_non_nl_ws(std::istream& in) {
for (int c; std::isspace(c = in.peek()); std::cin.ignore()) {
if (c == '\n') {
return false;
}
}
return true;
}
std::vector<double> read_array() {
std::vector<double> result;
for (double tmp; skip_non_nl_ws(std::cin) && std::cin >> result); ) {
result.push_back(tmp);
}
return result;
}
This approach has a similar property that std::ios_base::failbit
won't be set. However, if any of the characters on a line can't be parsed as double
the bit will set. That way you can detect input errors. The approach using std::getline()
will just go on to the next line.