Redirecting std::cin directly to std::cout - c++

An exercise about standard io asks me to:
Read input from the standard input and write it to the standard output.
A possible solution is:
#include<iostream>
#include<string>
using std::cin; using std::cout;
using std::string;
int main()
{
string word;
while (cin >> word)
cout << word;
return 0;
}
The string acts as a buffer in this example. If one tries to get rid of the buffer by doing something like this:
#include<iostream>
using std::cin; using std::cout;
int main()
{
while (cout << cin)
;
return 0;
}
the results are very different. When I run this code I get an interminable stream of
0x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d300x600d30
on the terminal.
Why this happens? Why do these programs behave differently?

cout << cin will not work the way you want it to. In C++11 and later, it won't even compile.
You are seeing an unfortunate side-effect of the (now obsolete) "safe bool" idiom.
Before C++11, a std::istream could be implicitly converted to a void* to emulate bool semantics. (Since C++11, explicit operator bool() const fills that role)
Therefore, the code:
while (cout << cin)
compiles in C++98 or C++03, because it can be implicitly converted to:
while (cout << static_cast<void*>(cin) )
This cast is allowed to produce any non-NULL void* when cin is not in an error state. In your case, it is producing the pointer 0x600d30.

In first solution, you extract a string from cin and reinject it in cout. But in the second way, compiler tries to convert cin into a value suitable for injection in cout.
Your implementation converted cin to a pointer and repeatedly printed it. Mine simply converted cin to a bool and repeadedly prints 1.
But beware, even your first version is not transparent to multiple spaces or tabs, and would probably not respect lines either. I would prefer:
#include<iostream>
#include <string>
int main()
{
std::string line;
while (std::getline(std::cin, line)) {
std::cout << line << std::endl;
}
return 0;
}

Related

Return value of (std::cin >> variable)

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

How to pass string to gets_s() in C++?

#include<iostream>
using namespace std;
int main() {
string str;
gets_s(str);
cout << str << endl;
return 0;
}
When I tried to run the above code it threw an error that no instance of gets_s() matched the argument list.
How can I pass an std::string instead of a char[] to gets_s() function if is possible?
The C function get_s takes a char* and a length argument, not a std::string.
Your best options are:
Formatted input:
std::cin >> str;
Read a line:
std::getline(std::cin, str);
Don't do that. Use the stream in a normal way:
#include<iostream>
using namespace std;
int main()
{
string str;
cin >> str;
cout << str << endl;
return 0;
}
gets_s has a significant limitation in that you must provide an upper limit on the number of characters you want to read.
Since you are using string the superior alternative is to use getline
#include <iostream>
#include <string>
using namespace std;
string str;
getline(cin, str);
This will expand the string to hold as many characters as are entered by the user.
gets_s() takes two arguments: pointer to char array and maximal size (your call is missing it). You cannot pass std::string - only C style strings.
Instead of C functions, why not use C++ way std::cin >> str or getline(std::cin, str)?
In C also don't use gets_s() (it's optional in C11) or gets() - use fgets() instead.
Well, there are a lot of answers about std::getline, but in case if you really need to use get_s, you may write such code:
size_t length = 10; // Just for example
std::string my_string(length, 0);
get_s(&my_string[0], length); // C++14 and older
get_s(my_string.data(), length); // C++17 and newer

Invalid Operands to binary expression after switching from g++ to clang++ Error occurs in assert [duplicate]

I was trying a test program on failures of opening a file using ifstream. The code is below :-
#include <iostream>
#include <fstream>
#include <type_traits>
using namespace std;
int main()
{
ifstream ifs ("wrong_filename.txt");
cout << boolalpha;
cout << is_pointer<decltype(ifs)>::value <<"\n";
cout << (ifs==nullptr);
return 0;
}
Output is :-
false
true
If ifs is not a pointer, then how does it equal to nullptr?
Until C++11, C++ streams are implicitly convertible to void*. The result will be NULL if the stream is not in an errorless state and something else if it is. So ifs == NULL (should not work with nullptr, see below) will find and use that conversion, and since your filename was wrong, the comparison will yield true.
In C++11, this was changed to an explicit conversion to bool, with false indicating an error and true a good stream, because the void* conversion allowed too much nonsensical code, such as your example. Indeed, a current compiler in C++11 or C++14 mode will reject your snippet, live. Since your code is obviously at least C++11, your compiler is non-conforming by accepting it.
Those conversions allow and are intended for error checks like this:
if ( !(ifs >> data) )
std::cout << "Reading data failed.";
or, analogous to your example:
std::ifstream ifs ("wrong_filename.txt");
if (!ifs)
std::cout << "Could not open file.";
Fun fact of the day: You can also use this to cleanly loop over a file, e.g.:
for (std::string line; std::getline(ifs, line);) {
// Process line
}

What does operator > and < mean when going with std::cout? [duplicate]

I was trying a test program on failures of opening a file using ifstream. The code is below :-
#include <iostream>
#include <fstream>
#include <type_traits>
using namespace std;
int main()
{
ifstream ifs ("wrong_filename.txt");
cout << boolalpha;
cout << is_pointer<decltype(ifs)>::value <<"\n";
cout << (ifs==nullptr);
return 0;
}
Output is :-
false
true
If ifs is not a pointer, then how does it equal to nullptr?
Until C++11, C++ streams are implicitly convertible to void*. The result will be NULL if the stream is not in an errorless state and something else if it is. So ifs == NULL (should not work with nullptr, see below) will find and use that conversion, and since your filename was wrong, the comparison will yield true.
In C++11, this was changed to an explicit conversion to bool, with false indicating an error and true a good stream, because the void* conversion allowed too much nonsensical code, such as your example. Indeed, a current compiler in C++11 or C++14 mode will reject your snippet, live. Since your code is obviously at least C++11, your compiler is non-conforming by accepting it.
Those conversions allow and are intended for error checks like this:
if ( !(ifs >> data) )
std::cout << "Reading data failed.";
or, analogous to your example:
std::ifstream ifs ("wrong_filename.txt");
if (!ifs)
std::cout << "Could not open file.";
Fun fact of the day: You can also use this to cleanly loop over a file, e.g.:
for (std::string line; std::getline(ifs, line);) {
// Process line
}

Building an istringstream with a string temporary

While trying my code to answer another question I found out that the following didn't compile
#include <iostream>
#include <cstring>
#include <sstream>
#include <string>
using namespace std;
// (main omitted)
const char * coin = "3D";
istringstream ss(string(s));
int i;
ss >> hex >> i; <--- error here
cout << (char) i << endl;
It failed with the following error:
test.cpp:15:11: error: invalid operands of types ‘std::istringstream(std::string) {aka std::basic_istringstream<char>(std::basic_string<char>)}’ and ‘std::ios_base&(std::ios_base&)’ to binary ‘operator>>’
While the following compiled and ran properly :
const char* coin = "3D";
string s(coin);
istringstream ss(s); // or directly istringstream ss("3D")
int i;
ss >> hex >> i;
cout << (char) i << endl;
If I look at the definition of the constructor of istringstream, it accepts const std::string& (actually the basic_string<char> equivalent), and that compiles. So I guess the template argument deduction has a behaviour I don't understand and create a not so conform istringstream, but why ?
I am using GCC 4.6.1 (Ubuntu flavor).
EDIT : since istringstream is a typedef, I doubt there's any problem with templates in the end.
istringstream ss(string(s));
Your compiler thinks that's a declaration of a function taking a string (named s) and returning an istringstream. Surround the argument in parentheses in order to disambiguate it. By the way, what is s? Did you mean coin there?
istringstream ss( (string(coin)) );
Read this if you are confused.
In this particular case, you could of course have just done this:
istringstream ss(coin);
If your compiler supports it, you can also avoid the MVP using uniform initialization syntax:
istringstream ss{string{coin}};
That probably looks a bit odd to most people, I know it looks odd to me, but that's just because I'm so used to the old syntax.