I am a C++ beginner,
#include <iostream>
int main()
{
char v1;
// valid no warning
std::cout << (std::cin >> v1) << std::endl; // return value of the expression expected
return 0;
}
// output: 1
// return value of the expression is 1?
Is the return value of (std::cin >> v1) really 1? Why?
I don't know of a current compiler that will accept your code as it stands right now. g++, clang and Microsoft all reject it, saying they can't find an overload to match the arguments (i.e., an operator<< for ostream that takes an istream as an operand).
It's possible to get the result you've posited with code on this order: std::cout << !!(std::cin >> v1) << "\n";. Depending on the age of the compiler and standard with which it complies, this does one of two things.
With a reasonably current compiler, this will use the Boolean conversion on the istream to get it to match the ! operator, then apply that (twice) to the result, so you write out the result of that operator.
With old enough compilers, there won't be a Boolean conversion operator, but there will be an overload of operator!, which also does a conversion to Boolean (but negated in sense, of course). The result of that will then be negated by the second !.
Either way, you end up writing out a Boolean value (or int containing zero or one on an old enough compiler) that indicates whether the stream is in a failed or successful state.
This is done to allow you to check input as you're reading it, so you can process input data sanely. For example, when/if you want to read all the values in a file, stopping at the end of the file, or when you encounter something that can't be interpreted as the desired type, you can write code on this general order:
// read integers from a file and print out their sum
int temp;
int total = 0;
while (std::cin >> temp) {
total += temp;
}
std::cout << total << "\n";
The while loop uses the conversion to Boolean to determine whether an attempt at reading a value was successful or not, so it continues reading values as long as that happens successfully, and quits immediately when reading is unsuccessful.
One common source of errors is to write a loop on this order instead:
while (std::cin.good()) { // or almost equivalently, check for end of file.
std::cin >> temp;
total += temp;
}
But loops like this get the sequence incorrect. One common symptom of the problem with this is that the last number in the file will be added to the total twice instead of once.
std::cin >> v1 returns cin; Not sure what type it gets converted to for std::cout, but most likely it indicates the state of cin, where 1 is good
Is the return value of (std::cin >> v1) really 1
No, see the ref for cin, it will return a istream.
Your codes will not work, we can not pass ::istream (std::cin) to operator<< of a std::ostream (std::cout).
Shoule be like the following:
char v1;
cout << "Input a char:";
cin >> v1;
The program only works for Pre-C++11 because the conversion to bool is not explicit.
Starting from C++11, the program will no longer work because the conversion to bool is explicit.
Note that std::cin >> v1; returns std::cin and not 1. But there is no operator<< for std::ostream that takes a std::cin.
The reason it works for Pre-C++11 is because in this case the conversion to bool was not explicit. But starting from C++11, the conversion to bool was made explicit and so the code no longer compiles.
For example,
bool b = std::cin; //WORKS for Pre-C++11 but FAILS for C++11 & onwards
bool b{std::cin}; //OK, WORKS for all versions(Pre-C++11 as well as C++11 & onwards) because in direct initialization we can use explicit conversion
Related
New to C++ and am currently reading "Accelerated C++" (Koenig & Moo) but struggling to understand the logic of left-associativity in one particular section. Specifically, on p.62, the expression:
is >> s.name >> s.midterm >> s.final;
Evaluates
( is >> s.name >> s.midterm ) >> s.final;
That is, the first term inside () reads-into the second s.final. However, is characters stream into each s.name, s.midterm and s.final variables independently - how can this be? Am I confusing operations (relational against arithmetic) or how do I interpret this directional flow of information in a strict technical sense?
If you are new to the language I think a good interpretation for is >> x is as follows:
is is an object capable of using low level functions to request an input from the keyboard (or another device, including a file)
the << operator is the one to which you can feed is and x so that is does it's job and puts in x what it reads from the device
the value returned by the expression is >> x is essentially of the same nature as is, and can be used again in the same way.
As regards the 3rd point, refer to this page on operator<</operator>> for std::basic_string: you'll see that the signature is the following (cleaning it up from things not relevant to the question)
template <class CharT>
std::basic_istream<CharT>&
operator>>(std::basic_istream<CharT>& is,
std::basic_string<CharT>& str);
where it's clear that operator>> returns an object of the same type as its first input, i.e. the expression is >> x, after having the side effect of reading stuff from device and altering the value of x, eventually evaluates to an object of the same type as is.
If you really want to go deep into this, you can write this simple code:
#include <iostream>
#include <string>
int main()
{
int x;
std::string y;
std::cin >> x >> y;
}
and, with the help of your IDE, jump to the two >>s to explore what they do or look like. Among other things, you'll find out that
the first >> will result in a call to basic_istream<_CharT, _Traits>::operator>>(int& __n), which is a member function of the class basic_istream<_CharT, _Traits> and returns and object of that class by reference, basic_istream<_CharT, _Traits>&. What is the object on which ???.operator>> is called? Well, it's obviously std::cin. And what is the object that the call returns? Go to the bottom of that function and you'll find return *this;, so it returns std::cin itself, possibly modified in the body of the function;
the second >> results in a call to std::operator>>(basic_istream<char>& __is, basic_string<char>& __str);, which is a free function in the std namespace. This, unlike the previous one, explicitly takes a first argument of type basic_istream<char> (which in our example is the expression (std::cin >> x), but like the previous one returns a reference to the stream, basic_istream<char>&, which is still an altered version of std::cin, ready to be used again.
To address this comment of yours:
reads-into string s.name a stream of characters input by the user, which are then in-turn used to identify the string to be read-into s.midterm
When you see (is >> x) >> y, the fact that "is reads stuff from input and puts it in x" is a side effect (yeah, the side effect is the main reason why we are doing this, but it's still a side effect); the non side effect is that is >> x takes is and x into input and gives you back an object of the same type of is.
In (is >> x) >> y, the x does influence what can be read in y, but only in the sense that is >> x doesn't give you back exactly is but an altered version of it.
The first alteration is that whatever you have read into x, if x was, say, a int, char *, or whatever, can't be read again, so it's not available for y.
Another alteration, is that x might be some type of object that is merely used to alter std::cin. I don't have an example for this right now, but I have one for std::cout: in std::cout << std::boolalpha << true; the effect of the first << is to take std::cout and give you back something which will print true/false instead of 1/0 when you feed it with a bool.
I've used statements such as this quite a bit in my C++ programming:
std::string s;
std::ifstream in("my_input.txt");
if(!in) {
std::cerr << "File not opened" << std::endl;
exit(1);
}
while(in >> s) {
// Do something with s
}
What I want to know is, why does this work?
I looked at the return value of operator>>, and it's an istream object, not a boolean. How does an istream object somehow get interpreted as a bool value that can be put inside of if statements and while loops?
The base class std::basic_ios provides an operator bool() method that returns a boolean representing the validity of the stream. For example, if a read reached the end of file without grabbing any characters, then std::ios_base::failbit will be set in the stream. Then operator bool() will be invoked, returning !fail(), at which time extraction will stop because the condition is false.
A conditional expression represents an explicit boolean conversion, so this:
while (in >> s)
is equivalent to this
while (static_cast<bool>(in >> s))
which is equivalent to this
while ((in >> s).operator bool())
which is equivalent to
while (!(in >> s).fail())
std::basic_ios, from which the input and output streams inherit, has the conversion function operator bool (or operator void* prior to C++11 to get around the safe-bool problem, which is no longer an issue thanks to the explicit keyword).
See std::basic_ios::operator bool:
This operator makes it possible to use streams and functions that return references to streams as loop conditions, resulting in the idiomatic C++ input loops such as while(stream >> value) {...} or while(getline(stream, string)){...}. Such loops execute the loop's body only if the input operation succeeded.
I was trying to verify if the entered value was an integer with the type id function. I know that the returned value would be i and not integer. I don't know why any entered value returns false and the programs stops. Any help would be appreciated.
The program works fine without the while statement
#include <iostream>
#include <typeinfo>
using namespace std;
int main() {
int number, factorial;
cout << "Enter a number: ";
cin >> number;
factorial = 1;
while (typeid(number).name() == "i") {
for (int i = number; i >= 1; --i){
factorial *= i;
}
cout << factorial;
}
}
The returned string of the member function name of std::type_info is implementation defined. It's not guaranteed to be "i". If you want to check the type of an object against another type you should do:
typeid(object) == typeid(T)
for any T type. In your example:
typeid(number) == typeid(int)
But the above comparison will always return true because number is declared as int. typeid is usually helpful to inspect the dynamic type of a polymorphic object. In your case number is not polymorphic at all. Therefore you don't need it.
What you seem to be worried about is validation of the input. For that you should consider that if operator>> of std::cin fails the following will happen:
(until C++11)
If extraction fails (e.g. if a letter was entered where a digit is expected), value is left unmodified and failbit is set.
(since C++11)
If extraction fails, zero is written to value and failbit is set. If extraction results in the value too large or too small to fit in value, std::numeric_limits<T>::max() or std::numeric_limits<T>::min() is written and failbit flag is set.
Therefore all you need to do is check the fail bit right after requiring it:
std::cin >> number;
if (std::cin) {
// ...
}
When streams read to an object, they check the format that's being read and parse that format into the object. If the stream cannot correctly parse that data, it sets an error in its error mask. The error mask is used to determine if an I/O operation succeeded or failed. When a stream is put into a boolean context (like in the parameters of an if() or while() loop), it will return true if its error mask is free of any errors.
If your intention is to only use an integer, then I suggest you adopt the pattern of using the stream itself to check if I/O operations succeeded. For example, this is how it will look in your code:
if (std::cin >> number) {
...
}
The formatted extractor operator>>() returns a reference to the stream which will then call its member function explicit operator bool() const to access its stream state and return true or false depending on whether the stream successfully read the contents of the stream into number.
istream & operator >>(istream & input, CustomLong & longi)
{
string inputstring;
input >> inputstring;
vector<long> trans;
for (int i = 0; i<inputstring.length(); ++i)
{
trans.push_back((long)(str.at(i)-'0'));
}
(longi.classVec) = trans; // assign vector to the class variable
return input; //works fine without it
}
I noticed that the method works fine even if we don't return input, is there any problem that can arise if we don't return input? If it doesn't do anything, I'd prefer not to put it, because it uses unnecessary resources.
The method itself may work fine, but if you are chaining inserters it won't.
std::cout << thisCustomLong << std::endl;
Will fail.
Edit: Also returning a value does not "use extra resources" for any practical definition of the term. Avoid micro-optimizing your program (I routinely work on systems than handle over ten million transactions a second (yes I got my decimal point right)) and I wouldn't worry about method like this returning a value.
cout << "Enter a positive integer or zero: ";
getline(cin, streamStr);
stringstream(streamStr) >> number;
if (!number) {
cout << "invalid input detected or the input is too big.\n";
return 1;
}
inputs like "%234" or "sdf2334" always fall to 0 , which is false in bool expression, but 0 is still a number.
How to check if the input is really invalid like "%234"??
You need to check the returned value of the operator>>, which is not the same as the value of the variable you're reading into:
if (stringstream(streamStr) >> number) {
...
So what's the returned value, then? If you check the docs, you'll see it's a stream itself. It goes to the operator bool of it (because it's used in an if statement), which in turn returns the validity of the stream, or, IOW, if the last operation succeeded.
If you want to ensure the stream doesn't contain anything besides the number use
if (sstream.rdbuf()->in_avail() > 0) {
// something is still there
And to skip whitespace at the end if you want to allow it:
sstream >> std::ws;
So, all in all...
template<typename T,
// those are optional
enable_if<is_default_constructible<T>::value>::type,
enable_if<is_input_streamable<T>::value>::type
>
optional<T> myRead(string input, bool allowTrailingWs = true) {
stringstream str(input);
T val;
// check parsing
if (!(str >> val))
return none;
// allow whitespace at the end
if (allowTrailingWs)
str >> std::ws;
// check if there's any garbage left
if (str.rdbuf()->in_avail() > 0)
return none;
return val;
}
The code above is just for illustration purposes. Shall you need more advanced parsing, check out Boost.Spirit.
Also, apparently this isn't guaranteed to work every time. Using:
auto inputEnd = ss.tellg();
ss.seekg(0, std::ios::end);
if (inputEnd == ss.tellg()) {
To check if the ss is empty could help fix that.
I don't think you understand how streams work. Allow me to address your misconception:
The stream won't attempt to extract any value into number if the data being evaluated doesn't correspond to formatting requirements of the type. Extraction works by the stream iterating through each character in the character sequence one by one, and testing each character as a viable datum for the type to which the extraction is targeted. If the character is not viable, extraction stops (this is why you are seeing success upon entering something like "2342fdsf"; the stream will keep extracting until it finds an invalid character. "2342" are valid characters for an integer while "f" is not)
If the stream finds an invalid character, nothing further is done to the variable (in this case number). In fact, it is implementation-defined what value an uninitialized variable has if extraction failed to produce any characters. With that in mind, it is potentially dangerous to check the value of the operand to determine if I/O failed. This is where checking the stream state comes in:
std::istringstream iss(streamStr);
if (iss >> number)
{
std::cout << "Extraction produced: " << number << '\n';
}
If the extractions fails, the stream will set the appropriate bits. The stream will then be implicitly converted to a boolean using operator bool() (or operator void*() pre-C++11 where it will subsequently undergo conversion to boolean). The boolean function will check the stream state using !this->fail() (which checks both badbit and failbit) and if the function returns true, the if body will be executed.
If the stream is not in a good state (!this->fail() returns false), that means the extraction failed to produce a value and the if statement body goes unevaluated.
By encasing the extraction in a conditional check, not the value of the thing you tried to extract into.
Assuming number must be a char value, try using the cctype library which is helpful for dealing with strings. It has functions such as
isdigit(Char_Exp) //Returns true if the value is a digit
and
isctrl(Char_Exp) //Returns true if the value is a control character like %(modulus)
Here is a link to a C++ cctype library reference: cctype library reference
To test number I would advise you create a function of type Boolean and so that it tests all possible input errors at once.