Explain how the for loop is terminating? - c++

I came across the a code which I didn't understand. It was on a coding website. The code was like this-
#include<iostream>
using namespace std;
char s[4];
int x;
int main()
{
for(cin>>s;cin>>s;x+=44-s[1]);
cout<<x;
}
My question is how the for loop is terminating and since it was on a coding website so answers are checked using file operation in my knowledge. But if we are running it on IDE this for loop is not terminating instead it keeps on taking input from the user.So whats the explanation for this??
Sample Input
3
x++
x--
--x
Output
-1
EDIT
This is the problem link - Bit++
This is the solution link - In status filter set language to MS C++ Author name - wafizaini (Solution id - 27116030)

The loop is terminating because istream has operator bool() (prior to C++11 it was operator void*) which returns false when no additional input is available. Basically, the reason the loop stops is the same as why a more common while loop terminates:
while (cin >> s) {
...
}
The reason this does not terminate when you run with an IDE is that you need to supply an end-of-stream mark, which is delivered in a system-dependent way. On UNIX and other systems derived from it you press Ctrl+d, while on Windows you press Ctrl+z.
Note: Your program is at risk of getting a buffer overrun in case an end-user enters more than three characters (character #4 would be used for null terminator of the string). Also note that the initial input cin>>s is thrown away, because loop condition is checked before entering the body of the loop.

That's perfectly valid, although a bit difficult to read, C++11 code.
std::istream::operator>>()
returns a reference to the input stream itself, and
std::istream::operator bool()
in turn evaluates the stream to a boolean value, returning false whenever a fail bit is set.
When reading from a file, that loop will eventually try to read past the end of file, causing the eof fail bit to be set and thus stopping the loop.
However, when running that code on a shell, you need to manually input the EOF control code on the stream, otherwise the for loop won't stop. This can be done by pressing Ctrl+D on Unix shells, for example.

A more common loop condition is while (cin >> s).
The convention is that operator>> returns a reference to the stream (cin). The stream classes then have a conversion operator that will return false in if (cin) or while (cin) after some input has failed.
This would work in the middle part of a for-loop as well, but is a bit unusual.

Related

Are there cases where the last operation succeeds but the istream/ostream goes fail()?

I'm a new learner of C++. In my understanding, fail() indicates whether the last operation on the istream/ostream succeeded or not. For example, let ifs be an ifstream opened to some valid file:
string s;
while (ifs >> s) {
// 1. assume the reading was taken successfully
// and do something according to that
}
// 2. assume the reading was unsuccessful
// and do something according to that
May I ask if it is possible that, in some (corner) cases, we arrive at 2. while the reading was actually successfully taken?
If so, what we do at 2. could be problematic. For example, if we have set ifs.exceptions(ifs.exceptions() | ios_base::badbit);, then we would (probably) have assumed that ifs is empty at 2..
I came up with this question when I was self-learning C++ using Stroustrup's book Programming: Principle and Practice Using C++ (2nd ed.). In Chapter 11.7 of this book, the writers design a Punct_stream class that takes an istream as source, processes data extracted from the source and then put the processed data into a data member of type istringstream called buffer waiting to be inputted into the program. The writers design the operator bool() method as follows (Page 404):
Punct_stream::operator bool()
{
return !(source.fail() || source.bad()) && buffer.good();
}
Firstly, I think !(source.fail() || source.bad()) should be equivalent to just checking source since fail() accounts for both failbit and badbit, and checking source is equivalent to checking !fail().
What is more related to my question is that, by this design, operator bool() will first check if the source is in an error state, and if so, it won't even look at the buffer. But reading data from a Punct_stream into a string will be done as long as there is character in buffer. So, if the buffer is not empty and the source is fail() somehow, then reading from the Punct_stream into a string will actually succeed while the checking on the Punct_stream condition will be false.
I wonder if the implementation of the standard library istreams may behave in some similar way such that in some cases the reading is actually successfully taken but the condition is evaluated to false?
All iostream input functions start by creating a sentry object which checks the good state of the stream. If the state is not good (that is any of badbit, eof or failbit is set), then the sentry will set the failbit and return false, which will cause the input function to immediately return without reading anything, without modifying (or even checking) the streambuffer, and without writing anything into the destination of the input function.
So by definition, if the stream test in the while is false, it must have either been false or eof before (and nothing was read into the string s), or it failed to be able to read anything into the string and it set the state to false. In either case, nothing was read into the string.

C++: end-of-file interpretation when using std::cin as a condition

I know that we can use std::cin as a condition, for example, in
while (std::cin >> value)
using std::cin as a condition will call a member function std::ios::operator bool. It says that
it "returns whether an error flag is set (either failbit or badbit)", which does not include
eofbit. Despite this, passing end-of-file (by Ctrl+d) terminates the loop. Why? Can failbit or badbit also set an eofbit?
I also found this explanation, but in C++ Reference it specifically says that "this function does not return the same as member good"
The loop above does not test for end of file. It tests for failure to read a value, end of file is just one possible cause of this. Even end of file does not necessarily cause a failure to read a value, imagine reading an integer where the digits are terminated by the end of file, you still read an integer even though you hit the end of file.
The bottom line is that failure to read a value for any reason sets the fail bit, and this loop tests for that.

while( cin >> value ) breaks the loop when i entered a character

In the past, I have been programming in c# but now I am learning c++. Why the while loop exit in c++ when I enter a string and in c# if I don't use tryparse it will give an exception. Does the c++ explicitly do something like tryparse in the backend ?
Sorry if my question
I am using codeblocks as my c++ IDE.
I am reading the book c++ primes and code a simple program that continuously takes integer as input until a string is entered. I wrote the same code in c# but it leads me to an error. So I have to use tryparse method in C#.
int value = 0;
In C++
while( cin >> value );
In C#
while( value == int.parse(Console.ReadLine());
Why the while loop exit in c++ when I enter a string
operator>> performs error handling internally. If it fails to extract an integer, the stream enters a failure state, and the loop is checking the stream's state, so it exits when the stream fails.
in c# if I don't use tryparse it will give an exception.
Yes, because that is the way int.parse() is defined to work.
You can get similar behavior in C++ by enabling exceptions in the stream . That way, if an extraction failure occurs, a std::ios_base::failure exception is thrown.
Does the c++ explicitly do something like tryparse in the backend ?
In a way, yes.
I am reading the book c++ primes and code a simple program that continuously takes integer as input until a string is entered. I wrote the same code in c# but it leads me to an error.
Your C++ and C# codes are not equivalent.
Your C# code reads an entire line as-is, discarding the line break, and then tries to convert the entire line as-is to an int.
Your C++ code discards leading whitespace - including line breaks - until it encounters a non-whitespace character, then it tries to read an int value, and whatever follows after it - including a line break - remains in the stream for subsequent reads.
So I have to use tryparse method in C#.
If you don't want a failed conversion to throw an exception, then yes.
C++ knows to parse for an integer because you defined the variable "value" as type int.
From the C++ reference:
As an object of class istream, characters can be retrieved either as
formatted data using the extraction operator (operator>>) or as
unformatted data, using member functions such as read.

why is failbit set when I hit end-of-file but eofbit is not [duplicate]

Why Ctrl+Z does not trigger the loop to finish on the following small program?
#include <stdio.h>
main()
{
int c;
while ((c = getchar()) != EOF)
{
//nothing
}
return 0;
}
If I enter: test^ZEnter, it does not get out of the loop.
I found related questions around (here and here) but none to explain it for C (not C++) under Windows.
Note: I use Visual Studio 2015 PRE on a windows 8.1
You need to hit Enter and then use ctrl+Z and then Enter again.
or, you may also use F6
EOF like you use it is not a character. It's the status in which that stream is.
I mean, heck, you even link this question, so you might as well read the accepted answer:
The underlying form of an EOF is a zero-length read.
It's not an "EOF character".
http://www.c-faq.com/stdio/getcharc.html cites a different case than yours, where someone stored the return value of getchar in a char. The underlying problem still occurs occasionally: different runtimes implement different values for the EOF integer (which is why I said, it's not an EOF character), and things love to go wrong. Especially in Visual C++, which is not a "real" C compiler but a C++ compiler with a compatibility mode, it seems things can go wrong.

istream_iterator copy example keeps waiting for input

I tried implementing an example of stream iterators from page 107 of "The C++ Standard Library". I get stuck on this line:
copy (istream_iterator<string>(cin), istream_iterator<string>(), back_inserter(coll));
The program keeps reading data from the console here, but does not pass on to the next line. How do I continue past this point?
From cppreference:
The default-constructed std::istream_iterator is known as the
end-of-stream iterator. When a valid std::istream_iterator reaches the
end of the underlying stream, it becomes equal to the end-of-stream
iterator. Dereferencing or incrementing it further invokes undefined
behavior
bold added
In other words, std::istream_iterator<string>(std::cin) keeps going until the end-of-input for std::cin. This doesn't happen at the end of the line, but at the end-of-file. In a console, there are specific commands to trigger the EOF:
In UNIX systems it is Ctrl+D, in Windows Ctrl+Z.
take for instance, if you would have made an input stream of int then you would have given input like - 45 56 45345 555 ....., so in all those cases, the reading operation of input stream would have returned a true value - while (cin>>var) { }
the while statement will not stop if it is getting a valid input, so to stop the reading of characters, we gave it following input, ... 54 56 3545 | , and as soon as it receives a special character the while loop stops as the conditions returns false.
That's the same case for all other type of input streams as well.
So I assume you understand here why your string type input stream never stops taking input because every possible input can be considered string.
The solution to this problem is using "ctrl + D in UNIX" and "ctrl + Z in windows", as it gives NULL in condition of while loop which means false, hence stoping the reading of string input.