Possible to have multiple while (cin>>input) - c++

I would like to know if it's possible to have multiple while (cin>>(variable)) as in the following code:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v1, v2;
int input;
while (cin>>input)
v1.push_back(input);
while (cin>>input)
v2.push_back(input);
return 0;
}
The logic of my program is to let user define the number of elements and value of each element in two sets of int vectors.
However, I realized that after entering the first set of numbers for the first vector (ending with an EOF), I'm unable to enter the second set of numbers for the second vector and the program terminates promptly. I suspect that EOF meant for the first cin for the first vector was processed by the second cin for the second vector as well.
Is there any way for the program above to run correctly i.e. having more than one while (cin)?

When you do while (cin>>input) you are effectively asking the input stream cin to produce integers until the stream has gone bad (i.e. an EOF was encountered, the steam was unable to convert the user's input to an integer, or maybe there was another problem).
After the loop terminates the state of the stream will still be in whatever state caused it to stop the loop. In order to continue reading from cin until another EOF token is encountered you will need to first clear the eof fail bit, this can be done (as πάντα ῥεῖ points out) by using cin.clear(). However, you should check the state of cin first, in case the input failed for another reason (perhaps the user entered a word instead of a number).
Two options might be: check that only the eof bit was set, or you can only unset the eof bit:
if (cin.eof())
{
std::cout << "Yay, reached an EOF" << std::endl;
}
cin.clear(std::ios_base::eofbit);

You need to call cin.clear(); after it was ended with EOF (i.e. CTRL-D or CTRL-Z), to reuse it again.

This while loop reads until the end of the file has been reached.
There is nothing more after the end, so any further read will fail.
You have to design another way so your program knows (i.e., has a condition) when the first set of numbers has finished.
There are usually two options:
read the number of values first
int count;
std::cin >> count;
for (int i = 0; i < count; i++) {
std::cin >> input;
v1.push_back(input);
}
// read into v2 …
or have a delimiting value, i.e. a special value that is not valid. In this case, I will take negative numbers as invalid.
std::vector<int> *v_input = &v1; // first read to v1
while (std::cin << input) {
if (input >= 0)
v_input->push_back(input);
else {
// invalid value, thus push numbers to the next vector
if (v_input == &v1)
v_input = &v2;
else
// invalid value while reading values for v2 - do not read any more lines
break;
}
}
However, you could also first read whole lines as a string and test, e.g., if the string is empty. If yes, input values to v2 instead of v1. Of the input is not empty, convert to int and push to the current vector.

Related

How can I make it so user inputs are stored in seperate variables without knowing how many inputs the user wants? (Beginner)

My code is below. I want the user to be able to input any number of operands and then the code asks them to input an operand that number of times. I have that part figured out. How do I store each one of their operands without knowing how many they want in the first place?
for (int i = 0; i < numoperands; i++){
cout << "Input Operand: ";
cin >> ;
Do you need to have a seperate variable for each different input?
If not you can try defining an array outside the for loop then inside the for loop append to the array for every input the user have.
When you want to access the operands, just run another for loop for the length of the array and index it.
You need a bit more "building" blocks for your program to work :
loops, allow your code to run the same code multiple times (while and for loop)
stop condition, when will you stop with accepting input
conversion, from string to integer
strings, to hold input
Before you continue though I would recommend you learn a bit more C++ first. If you don't have any books this might be a good place to start: https://www.learncpp.com/
Example with explanation :
#include <iostream>
#include <string> // include standard library type for a string.
#include <vector> // a vector can hold values (or objects) and can grow at runtime
// DO NOT use : using namespace std;
// It is good to unlearn that right away https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice
int main()
{
std::string input; // a string to receive input in.
std::vector<int> values; // C++ does know about arrays, but they are fixed length,
// vector vector is allowed to grow
const std::string end_input{ "x" }; // const means you will only read from this variable
// the "x" is used to end the input
// start a do/while loop. Allows you to run the same code multiple times
do
{
// prompt the user what to do :
std::cout << "Enter a number ('"<< end_input << "' to end input) and press return : ";
// read input to the string so we can check its content
std::cin >> input;
// check input end condition
if (input != end_input)
{
int value = std::stoi(input); // stoi is a function that converts a string to an integer
values.push_back(value); // push back adds value at the end of the vector
}
} while (input != end_input); // if condition is not met, then program continues at do (and thus loops)
// the next lines output the content of the vector to show the input
std::cout << "\n"; // output a new line (avoid std::endl)
std::cout << "Your input was : \n";
bool print_comma = false;
for (int value : values) // loops over all values in the vector
{
if (print_comma) std::cout << ", ";
std::cout << value;
print_comma = true;
}
return 0;
}

populating a vector list using a for loop [duplicate]

I would like to know if it's possible to have multiple while (cin>>(variable)) as in the following code:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v1, v2;
int input;
while (cin>>input)
v1.push_back(input);
while (cin>>input)
v2.push_back(input);
return 0;
}
The logic of my program is to let user define the number of elements and value of each element in two sets of int vectors.
However, I realized that after entering the first set of numbers for the first vector (ending with an EOF), I'm unable to enter the second set of numbers for the second vector and the program terminates promptly. I suspect that EOF meant for the first cin for the first vector was processed by the second cin for the second vector as well.
Is there any way for the program above to run correctly i.e. having more than one while (cin)?
When you do while (cin>>input) you are effectively asking the input stream cin to produce integers until the stream has gone bad (i.e. an EOF was encountered, the steam was unable to convert the user's input to an integer, or maybe there was another problem).
After the loop terminates the state of the stream will still be in whatever state caused it to stop the loop. In order to continue reading from cin until another EOF token is encountered you will need to first clear the eof fail bit, this can be done (as πάντα ῥεῖ points out) by using cin.clear(). However, you should check the state of cin first, in case the input failed for another reason (perhaps the user entered a word instead of a number).
Two options might be: check that only the eof bit was set, or you can only unset the eof bit:
if (cin.eof())
{
std::cout << "Yay, reached an EOF" << std::endl;
}
cin.clear(std::ios_base::eofbit);
You need to call cin.clear(); after it was ended with EOF (i.e. CTRL-D or CTRL-Z), to reuse it again.
This while loop reads until the end of the file has been reached.
There is nothing more after the end, so any further read will fail.
You have to design another way so your program knows (i.e., has a condition) when the first set of numbers has finished.
There are usually two options:
read the number of values first
int count;
std::cin >> count;
for (int i = 0; i < count; i++) {
std::cin >> input;
v1.push_back(input);
}
// read into v2 …
or have a delimiting value, i.e. a special value that is not valid. In this case, I will take negative numbers as invalid.
std::vector<int> *v_input = &v1; // first read to v1
while (std::cin << input) {
if (input >= 0)
v_input->push_back(input);
else {
// invalid value, thus push numbers to the next vector
if (v_input == &v1)
v_input = &v2;
else
// invalid value while reading values for v2 - do not read any more lines
break;
}
}
However, you could also first read whole lines as a string and test, e.g., if the string is empty. If yes, input values to v2 instead of v1. Of the input is not empty, convert to int and push to the current vector.

How to read unknown number of inputs?

I am learning C++ using the book C++ Primer.
In Section 1.4.3, the following example code about reading the unknown number of inputs is given.
#include <iostream>
int main()
{
int sum = 0, value = 0;
// read until end-of-file, calculating a running total of all values read
while (std::cin >> value)
sum += value; // equivalent to sum = sum + value
std::cout << "Sum is: " << sum << std::endl;
return 0;
}
According to the book, if we give an input of 3 4 5 6, the output will be Sum is: 18
But when I try this on my computer(Windows 10 with MinGW), The code does not end. It just keeps on asking for input even if I enter a newline. It works only when I enter a non-int input like f.
Is this expected? If yes, is there any code that stops after inputting a newline?
I am quite new to c++ and I have already learned python, so getting stuck so early on is quite frustrating.
Thanks and regards.
You need to terminate your input by an End-Of-File-character (i.e. CTRL-Z on Windows, CTRL-D on Mac/Unix), not just by an End-Of-Line (i.e. Enter).
A simple Enter is interpreted as white space, which will be simply ignored by operator>> when reading into an integral data type.
CTRL-Z / End-Of-File, in contrast, makes any operator>> fail with an error.
See also this SO answer.
Note: Entering f will also terminate your loop, since f is not considered a valid integral number; Hence, std::cin >> value with value being of type int and an input like f will fail as well. To be more accurate: operator>> actually returns a reference to the input stream, but if reading in a value fails, failbit is set on the stream, and then interpreting the stream object in a boolean expression (implicitly calling basic_istream::operator bool()) returns false; So maybe the author of the book did not want to explain these details at the respective section in the book :-)
Is this expected?
Yes, as operator>> ignores leading whitespace by default, which includes line breaks.
If yes, is there any code that stops after inputting a newline?
Use std::cin.getline() or std::getline() instead of operator>>. You can then use operator>> with a std::istringstream to parse values from each line, eg:
#include <iostream>
#include <string>
#include <sstream>
int main()
{
std::string line;
int sum, value;
do
{
std::cout << "Enter a set of numbers, or a blank line to exit: ";
if (!std::getline(std::cin, line) || line.empty())
break;
// read until end-of-line, calculating a running total of all values read
std::istringstream iss(line);
sum = 0;
while (iss >> value)
sum += value; // equivalent to sum = sum + value
std::cout << "Sum is: " << sum << std::endl;
}
while (true);
return 0;
}
Live Demo
Is this expected?
Yes, Thats what while (std::cin >> value) does. See this answer for more explanations: How is "std::cin>>value" evaluated in a while loop?
is there any code that stops after inputting a newline?
No, as >> simply ignore a white space(also #StephanLechner mentioned it)
What you can do instead is:
Just give a condition; if it satisfies just break the loop. you
can also provide a console out to make it more understandable to the
user. For example:
std::cout << "Enter value to sum or press -1 to exit" << std::endl;
while (std::cin >> value && value != -1) // if value == -1, loop stops.
{
sum += value;
}
You can simply terminate by the end of character:
CTRL-Z on Windows
CTRL-D on Mac/Unix

Read a sequence of ints from cin and store them in a vector

This is what I have done to read integers with std::cin and store them in a vector:
int number;
vector<int>ivec;
while (cin>>number)
{
ivec.push_back(number);
}
for (auto v: ivec){
cout << v;
}
Then, I am stuck with the problem that how to stop entering integers and move to the next process of printing the vector out. Any pointer will be appreciated.
It depends on the terminal in use and the precise mechanism varies quite a lot but, conventionally, typing Ctrl+D (Linux) or Ctrl+Z (Windows) will result in an end-of-file "signal" being transmitted along the pipe, causing the EOF bit to be set on cin, and thus the next cin >> number attempt to fail.
That will break the loop.
Conveniently, the same will happen if you ran your executable with redirected input from a file. Which is kind of the point.
The code you posted reads numbers from cin as long as it succeeds. There are two ways to have it stop succeeding: If you enter something that is not a number, reading data still succeeds, but converting it to number fails. This puts cin into the bad state. It can be recovered from using the clear methode. The other way is making the reading of characters from cin fail (for example the end of a file that gets used as input). This puts cin into the failed state. Usually, recovering from a failed state is impossible.
To produce the you can no longer read state at end of file when entering data at the keyboard, operating system specific methods have to be used (likely Control-D or Control-Z). This is final for the invocation of your program.
If you need a way for the user to signal: "Please go on, but let me enter other stuff later", the most clean way is likely reading cin line-by-line and parse the input using strtol or a stringstream, and comparing for a magic stop-token (e.g. empty line, "end") to exit the loop.
You can do it the following way
#include <vector>
#include <iterator>
//...
vector<int> ivec( std::istream_iterator<int>( std::cin ),
std::istream_iterator<int>() );
for ( auto v: ivec ) std::cout << v << ' ';
std::cout << std::endl;
In Windows you have to press key combination Ctrl + z and in UNIX system Ctrl + d
Or you can introduce a sentinel. In this case the loop can look like
int number;
const int sentinel = SOME_VALUE;
for ( std::cin >> number && number != sentinel ) vec.push_back( number );
Please find a simple solution to your problem, let me know if you see any issue with this solution.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> va;
int x;
while ( cin >> x ) {
va.push_back(x);
if ( cin.get() == '\n' ) break;
}
//Vector output
for ( int i = 0; i < va.size(); i++ ) {
cout << va[i] <<" ";
}
return 0;
}

Why does a program become broken when a character is input when prompted to input an integer value?

Example:
int i=0;
do {
cin >> i;
if(!isdigit(i)) cout << "Error. Must be an integer\n\n";
}
while(cin.fail());
If a character rather than an integer was input by the user, the program would break and go into some infinite loop for some reason. Why is this? Is there no way to prevent it from happening? the isdigit() function doesn't seem to work well with int variables, only with char variables.
You seem to be confused about how input works. When you write
std::cin >> i;
and i is an int, the input stream will extract the text for
an integral value: it will skip whitespace, then extract
a possible sign, then one or more digits. It will then convert
this text into an int, and store it where requested. If it
doesn't find text in the appropriate format, it will set an
error status (failbit), which will remain set until you clear
it. And it will not modify i; you must always check that
input has succeeded before using the variable input.
isdigit, on the other hand, has undefined behavior unless
the integer it is passed is in the range [0,UCHAR_MAX]. (Note
that range. It means that you cannot simply pass it a char.)
It's not clear what you're trying to do here. If it's just
enter an int:
int i;
while ( !(std::cin >> i) ) {
std::cout << "Error: integer wanted" << std::endl;
std::cin.clear(); // Clear error...
std::cin.ignore( INT_MAX, '\n' ); // And ignore characters which caused it
// (up until next '\n')
}
If you want a single digit:
int i = std::cin.get();
while ( i != EOF && !isdigit( i ) ) {
std::cout << "Error, single digit wanted" << std::endl;
i = std::cin.get();
}
char ch = i; // NOW (and only now) can you convert into int.
std::cin.get() returns an int, in order to handle the out of
band value EOF. The int in guaranteed to be in the range
[0...UCHAR_MAX], or to be EOF, so you can pass it directly
to isdigit. Only once you've finished these tests should you
convert it into a char (since a digit is a character).
You always need to check after reading that your input was successful, e.g.
if (std::cin >> i) {
// process input
}
If the input fails std::ios_failbit is set. While this flag is set the stream won't accept any input and convert to false. To clear the error flags you use
std::cin.clear();
Clearing the error flags won't remove the offending character. You'll need to get rid of them, e.g., using
std:: ignore();
The above code certainly doesn't create an infinite loop. But the loop happens usually when a digit is expected and a non-digit is given, so the characters in the buffer will stay there and the stream is in an bad state. This will happen until the stream is appropriately cleared, so that the stdio can continue to read according to the format specification. Of course the loop has to be done iny our program, as stdio is not looping on it's own.
To clear the input and ingore what is left there you can use this:
std::cin.clear();
std::cin.ignore();