Why is cin used as a loop condition? - c++

In my c++ book, there is this loop:
vector<double> temps; // temperatures
for (double temp; cin>>temp; ) // read and put into temps
temps.push_back(temp);
This appears to loop forever. I can't stop this loop. What purpose does this serve?

The operator>> will return the stream (cin) which itself can be converted to a bool that represents if the stream is still valid or not. That will loop until something causes cin's read to fail (end of file, a letters instead of numbers, etc).

This is similar to:
int num;
while(cin.good()) //could also use while(cin)
{
cin >> num;
cout << num << endl;
}
Where you continuously read a number and print it. Inputting a non-number causes the input stream to fail hence cin.good() becomes false.(stream is good no more)

Related

Why does "cin" not wοrk again after EOF?

Today our Data Structure class asked us to implement Horner's Rule. I made it at last, but there is a small bug that upsets me very much. I use a while loop to read and save the coefficients of the polynomial, and I used another cin to read the value of the variable called x. The thing is, after I reach EOF to terminate reading the coefficients, the following cin part that reads the variable x does not execute. This puzzles me very much.
while(std::cin>>n){
coeff.append(n);
}
std::cout<<"Now enter the value";
std::cin>>x;
The program is correct in syntax, but it just skips the second cin which reads the variable x.
After you have terminated the stream, nothing more is added to it and there is nothing more to read.
You need a different "end of coefficients" marker.
The simplest way is to require all coefficients to be entered on one line:
std::string line;
if (std::getline(std::cin, line))
{
std::istringstream is(line);
int n = 0; // or whatever type you're using.
while (is >> n)
{
coeff.append(n);
}
std::cout << "Enter the value: ";
std::cin >> x;
// Evaluation code here.
}
else
{
// Possibly handle error
}
Other options include defining a "magic" coeffient as the marker, or take some invalid (i.e. non-numeric) input and then clear() the stream before continuing.

Cin not waiting for input despite cin.ignore()

I'm new to C++ and I'm using Visual Studio 2015.
cin is not waiting for input after "Please enter another integer:\n" and outputs "You entered 0" every time.
I've searched the Internet more than an hour without a solution. No combination of cin.ignore() is working. Why is the cin buffer still not cleared?
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vals;
int val = 0;
int n = 0;
cout << "Please enter some integers (press a non-numerical key to stop)\n";
while (cin >> val)
vals.push_back(val);
cin.ignore(INT_MAX, '\n');
cin.ignore();
cout << "Please enter another integer:\n";
cin.ignore();
cin >> n;
cout << "You entered " << n;
system("pause");
return 0;
}
The problem is for the user to exit the loop you need to put the cin in a failed state. That is why your
while(cin >> val){ .... }
is working.
If in a failed state cin is no longer in a position to supply you with input so you need to clear() the failed state. You also need to ignore() the previously non-integer response that triggered the failed state initially.
It would also be of merit to use
if(cin >> n){
cout << "You entered " << n;
}
This will assert that a proper input for n was provided.
The problem in your program is that it expects integers, whereas a user can input anything, like a non-integer char.
A better way to do what you seem to want to do is to read characters one by one, ignoring whitespace, and if it's a digit, then continue reading to get the whole number, else stop the loop. Then you can read all chars until you reach '\n', and do the same for one number. While you do that, for each character you should check that there can still be characters in the stream with cin.eof().
Also, instead of using system("pause"), you can prevent the command line window from closing by requesting a last character before terminating the application.
Try getting your integers like this :
#include <sstream>
...
fflush(stdin);
int myNum;
string userInput = "";
getline(cin, userInput);
stringstream s (userInput);
if (s >> myNum) // try to convert the input to int (if there is any int)
vals.push_back(myNum);
without sstream you have to use try catch, so your programme won't crash when input is not an integer

How to read data from stdin, for a given number of test cases in C++

This might sound silly, but it's my first time solving programming contests on line. The problem is usually described as:
Input:
First line indicates the number of test cases t.For the next 't' lines the data is entered.
I've written the following program (with the correct headers included):
vector<string> read_strings(int t_cases) {
vector<string> ip_vec;
string line, str;
int cnt = 0;
while (cnt != t_cases-1) {
std::getline(std::cin, line);
++cnt;
}
std::istringstream iss(line);
while (iss >> str) {
ip_vec.push_back(str);
}
return ip_vec;
}
But this program always gets stuck in an input loop. I've also tried to parse the line as soon as it's entered by putting iss in the first while loop. If anyone could provide me a pointer on how to solve this problem, I will be able to finally test the rest of the program.
Thanks.
You need to add the lines to the vector as they are read. The first while loop is reading through all the test cases, but is not saving them somewhere. Then next while loop tries to reads line, which is the last test case read. Try the following:
vector<string> ip_vec;
string line, str;
for (int cnt = 0; cnt < t_cases; cnt++) {
std::getline(std::cin, line);
ip_vec.push_back(line);
}
Since you're starting to learn how programming contests work, I wouldn't recommend you to store all the input given. In general, you can store the number of inputs t and for each test case, the program outputs the answer for that test before reading the next test case. For example:
for (int i = 1; i <= t; i++) {
cin >> input;
// Some computations specific to the problem
cout << output << endl; // Pay attention on how the problem wants the output to be printed.
}
If the problem doesn't give you the number of test cases, you can simply change the loop to:
while (cin >> input) {
// Computations...
cout << output << endl;
}
It's usually how I solve problems from programming contests.
EDIT: As noted by #AnkitKulshrestha, if there's more than one input that you have to read for each test case, you can simply read them like this (with three inputs, for example):
while (cin >> a >> b >> c) {
// Computations...
cout << output << endl;
}

How to empty the input stream in C++?

I know how to do this in C but have no idea for a C++ solution. I want the following to be fail safe, but after providing a string or even a char to the input, the program hangs. How to read input stream including \n to free it?
int main() {
int num;
do {
std::cin.clear();
std::cin >> num;
while ( std::cin.get() != '\n' );
} while ( !std::cin.good() || num > 5 );
return 0;
}
Once the stream is in an error state all read operations will fail. This means that, if the cin >> num read fails, the loop with the get() calls will never end: all those get()s will fail. Skipping to the end of the line can only be done after clearing the error state.
To build on top of R. Martinho Fernandes answer, here is a possible C++ alternative to your code:
std::string num;
std::getline(std::cin, num);
// Arbitrary logic, e.g.: remove non digit characters from num
num.erase(std::remove_if(num.begin(), num.end(),
std::not1(std::ptr_fun((int(*)(int))std::isdigit))), num.end());
std::stringstream ss(num);
ss >> n;
The std::getline function extracts characters from cin and stores to num. It also extracts and discards the delimiter at the end of the input (you can specify your own delimiter or \n will be used).
The string::erase function removes all characters but digits from the num string, using std::remove_if with a negative std::isdigit predicate.
The string is then represented as an integer using a std::stringstream (a boost::lexical_cast would have worked as well)
The logic here implemented by the erase function can be any other logic, but this code is probably much simpler to read than the one included in the question.
I would approach it using getline(cin,num) and then catch any fails using cin.fail(). I usually use cin.fail() with ints but theoretically should work with strings and chars also, for example :
string num;
getline(cin,num);
if(cin.fail())
{
cin.clear();
cin.ignore();
}
One way would be to check the state after every input and throw an exception if that happens
for example:
#include<iostream>
using namespace std;
int main(){
int a;
cout<<"Enter a number: ";
cin>>a;
//If a non number is entered, the stream goes into a fail state
try
{
if(cin.fail()){
throw 0;
cin.clear();
cin.ignore();
}
}
catch(int){
cin.clear();
cin.ignore();
}
return 0;
}
After that you can continue with whatever code you wish
To clear input stream, use cin.sync() .
no need to use cin.clear() or cin.ignore().

How to signify no more input for string ss in the loop while (cin >> ss)

I used "cin" to read words from input stream, which like
int main( ){
string word;
while (cin >> word){
//do sth on the input word
}
// perform some other operations
}
The code structure is something like the above one. It is compilable. During the execution, I keep inputting something like
aa bb cc dd
My question is how to end this input? In other words, suppose the textfile is just "aa bb cc dd". But I do not know how to let the program know that the file ends.
Your code is correct. If you were interactively inputting, you would need to send a EOF character, such as CTRL-D.
This EOF character isn't needed when you are reading in a file. This is because once you hit the end of your input stream, there is nothing left to "cin"(because the stream is now closed), thus the while loop exits.
As others already answer this question, I would like add this important point:
Since Ctrl-Z on Windows (and Ctrl-D on unix systems) causes EOF to reach, and you exit from the while loop, but outside the while loop you cannot read further input, since the EOF is already reached.
So to enable reading using cin again, you need to clear eof flag, and all other failure flags, as shown below:
cin.clear();
After doing this, you can start reading input using cin once again!
int main() {
string word;
while (cin >> word) {
// do something on the input word.
if (foo)
break;
}
// perform some other operations.
}
Hit Ctrl-Z (Ctrl-D on *nix systems) and hit enter. That sends an EOF and invalidates the stream.
cin >> some_variable_or_manipulator will always evaluate to a reference to cin. If you want to check and see if there is more input still to read, you need to do something like this:
int main( ){
string word;
while (cin.good()){
cin >> word;
//do sth on the input word
}
// perform some other operations
}
This checks the stream's goodbit, which is set to true when none of eofbit, failbit, or badbit are set. If there is an error reading, or the stream received an EOF character (from reaching the end of a file or from the user at the keyboard pressing CTRL+D), cin.good() will return false, and break you out of the loop.
I guess you want to jump out at the end of file.
You can get the value of basic_ios::eof , it returns true at the end of stream.
Take the input from a file. Then you will find that the while loop terminates when your program stops taking input.
Actually cin stops taking input when it finds an EOF marker. Each input file ends with this EOF marker. When this EOF marker is encountered by operator>> it modifies the value of internal flag eofbit into false and consequently the while loop stops.
It helps me to terminate loop by hitting ENTER.
int main() {
string word;
while(getline(cin,word) && s.compare("\0") != 0) {
//do sth on the input word
}
// perform some other operations
}
You can make a check for a special word in input.
F.e. "stop":
int main( ){
string word;
while (cin >> word){
if(word == "stop")
break;
//do sth on the input word
}
// perform some other operations
}
you can try this
string word;
vector<string> words;
while (cin >> word) {
words.push_back(word);
if (cin.get() == '\n')
break;
}
in this way, you don't have to end with CTRL+D(Z). program will quit while sentence end
your program doesn't take in count white spaces. make difference between cin and getline...
here is an example with a trick: the program get input and prints output until you hit twice Enter to quit:
#include <iostream>
#include <string>
using namespace std;
int main(){
char c = '\0';
string word;
int nReturn = 0;
cout << "Hit Enter twice to quit\n\n";
while (cin.peek())
{
cin.get(c);
if(nReturn > 1)
break;
if('\n' == c)
nReturn++;
else
nReturn = 0;
word += c;
cout << word;
word = "";
}
cout << endl;
return 0;
}