C++ Passing ostream as parameter - c++

I'm working on a homework project for a virtual rolodex that has called for a main class, a rolodex class, and a card class. To output the contents of all of the "cards" to the console, the assignment says that main() should call a show(...) function in the rolodex class, passing it an ostream and show(...) then iterates over the cards, calling each of their showCard() functions. The actual showing is done by the card objects' showCard() function, showing on the provided ostream.
What I don't understand is why an ostream would/should be passed anywhere. Seems like the assignment is calling for something like this:
main() {
Rolodex myRolodex;
ostream myStream;
myRolodex.show(myStream);
}
void Rolodex::show(ostream& theStream) {
//for each card 'i' in the Rolodex...
myCard[i].show(theStream);
}
void Card::show(ostream& theStream) {
theStream << "output some stuff" << endl;
}
instead of something like this:
main() {
Rolodex myRolodex;
myRolodex.show(); //no ostream passed
}
void Rolodex::show() {
//for each card 'i' in the Rolodex...
myCard[i].show();//no ostream passed
}
void Card::show() {
cout << "output some stuff" << endl;
}
Am I either misunderstanding the use of ostream as a parameter or missing some other obvious reason to pass an ostream down the stream like that?

What I don't understand is why an ostream would/should be passed anywhere.
This is often used for things like testing. Say you want console output normally, so you'd pass around a reference to std::cout. But sometimes you want to do testing, e.g. unit or acceptance testing, and you want to store the output in memory for that. You could use std::stringstream for this, and the function you're working with is none the wiser.
That's one specific case -- but in general any place where you'd want to change where the data source or sink could be coming from / going to, you can do that by passing a stream around.
For example, the following would print your rolodex to the console:
int main()
{
Rolodex myRolodex;
myRolodex.show(std::cout);
}
... but if tomorrow you wanted to write to a file instead, you can do that without affecting the code inside Rolodex at all:
int main()
{
Rolodex myRolodex;
std::ofstream file("This\\Is\\The\\Path\\To\\The\\File.txt");
myRolodex.show(file); // Outputs the result to the file,
// rather than to the console.
}

I would just overload the << operator:
class Card{
public:
friend ostream& operator<<(ostream& os, const Card& s);
};
ostream& operator<<(ostream& os, const Card& s){
os << "Print stuff";
return os;
}
And you could overload in the Rolodex as well to just iterate over the cards.

Related

Overloading << for both iostream and fstream

I am trying to overload both cout from iostream and fout from fstream
ostream& operator<<(ostream& cout, const Object& obj);
ofstream& operator<<(ofstream& fout, const Object& obj);
I want the first function to work with the console so have text for the user while I want the second function to only output the value of the variables onto a file.
However, in
void save_data(const Object& obj)
{
fstream fout("DataBase.txt", ios::out);
if (fout.is_open())
{
fout << obj;
fout.close();
}
else
cout << "DataBase.txt could not be saved!" << endl;
}
I have text that I used to guide the user inside my function that overloads cout in my file.
std::fstream inherits from std::iostream, which in turn inherits from std::ostream. There's no std::ofstream in that chain, making that overload an unsuitable candidate.
One way to fix this is to use std::ofstream at the callsite instead of std::fstream. You can also add an overload for std::fstream. However, be aware that std::ostream is not necessarily the console; that's a guarantee you have to provide yourself from the rest of the code. For example, a std::ofstream could be upcast to std::ostream and then used to print an Object and your overload set would assume this stream is for the console. It might be hard to ensure the rest of your code provides that guarantee. In addition, robust detection of a console is going to be platform-dependent with its own answers elsewhere on the site (e.g., for Windows).
One way that existing programs handle this requirement is to have an explicit "interactive" option on the command line. For example, git commands use --interactive and sometimes -i for this purpose. This way, the user asks for the extra guiding output and there's no clever detection trickery required.
Thanks to the help from #chris I was able to figure out what the real problem was. Normally one doesn't need to overload based on the base and derived I/O stream types. There's usually a polymorphic way to do what you want. In this case you can check if the stream being written to is std::cout and construct a new stream with a buffer to write to it.
std::ostream& operator<<(std::ostream& os, Obj const& obj) {
std::ostream o(nullptr);
if (&os == &std::cout) {
o.rdbuf(std::cout.rdbuf());
}
o << "hello\n";
return os;
}
Writing to o will do nothing if the buffer is a null pointer. This will allow you to write your console output guides for the user without separating both implementations.
If you would still like to split the implementations, create two functions and call the appropriate one when the above if condition is true and false.
std::ostream& write_with_console_o(std::ostream&);
std::ostream& write_with_file_o(std::ostream&);
std::ostream& operator<<(std::ostream& os, Obj const& obj) {
if (&os == &std::cout) {
return write_with_console_o(os);
}
return write_with_file_o(os);
}

How do I output the cout output from a method into an ofstream file in c++?

I have a main function that prints a sudoku game to the console as I play. I call a print board method which outputs the board along with a 2D array with the numbers. I've been modifying the game to output to the file after every cout:
cout << "puzzle created" << endl;
output << "puzzle created" << endl;
Then the problem is that there is an error when I try the same with a method:
sudoku.printBoard(); //method to print board to console
I can't simply say:
output << sudoku.printBoard();
and I can't say:
output << "number";
in the method in the board.cpp file either.
Does anyone know any way around this?
This is the problem with print() member functions, and the reason you shouldn't write them. At least, not like this. You've locked yourself into printing to stdout, and now that you want to print somewhere else instead, you're stuck.
Instead, have a function that prints where you tell it to. This may be stdout or a file or whatever.
The function will be declared like this:
void printBoard(std::ostream& os);
and inside its definition, you will use os rather than std::cout.
Then your code will look like this:
sudoku.printBoard(std::cout);
sudoku.printBoard(output);
It works because both std::cout and output are of types that derive from std::ostream.
If you need the cout variant a lot, and you don't want to provide the argument every time because it's getting messy, simply provide an overload:
void printBoard()
{
printBoard(std::cout);
}
Now you can still write:
sudoku.printBoard();
Whether this is more or less confusing for developers on your project is for you to decide.
If you don't have other things to print, so that this is the only function of its kind within the type of sudoku, a more idiomatic approach would be to create an operator<< for that type:
std::ostream& operator<<(std::ostream& os, const SudokuBoard& board)
{
board.printBoard(os);
return os;
}
Now you can use it like this:
std::cout << sudoku;
output << sudoku;
Make a class that takes two ostreams in the constructor. One of these can be std::cout. Store these in the class as references.
Create output stream operators (<<) and use those to write to the two streams.
To use this in other classes pass it as a reference in their constructor (look up dependency injection).
Pass ofstream as a reference to your funtion or simply return string from your function and print it in main() or callee function.
In 2nd case you go like this
string f()
{
ostringstream os;
os<<"whatever I want to print in output";
....
...
return os.str();
}
int main() or //womain() from wherever you call
{
output<<f()<<endl;
}

Return type of << operator overloading function in C++

I have create a program to overload << operator for my class.
I have a doubt about the return type of the overloaded method.
When i am returning the out from the overloaded operator function the program is working fine.
But when i am not returning any thing from the function the program crashing under one condition.
In many C++ resource i have read that the return type is necessary to print operators in cascading .
Condition 1 : Passing
When i am using statement
// cout<<"\n"<<mv1<<mv2<<mv3;
Every thing is working fine. Passing without return from overloaded function.
Condition 2:Failing
When i am using statemtent
cout<<"\n"<
This i know that return was not there so the program crashed at runtime.
But the question is what made program run in Condition 1 . Even without the return statement was not present in the overloading function.
Program below
I have create a program to overload << operator for my class.
I have a doubt about the return type of the overloaded method.
When i am returning the out from the overloaded operator function the program is working fine.
But when i am not returning any thing from the function the program crashing under one condition.
In many C++ resource i have read that the return type is necessary to print operators in cascading .
Condition 1 : Passing
When i am using statement
// cout<<"\n"<<mv1<<mv2<<mv3;
Every thing is working fine. Passing without return from overloaded function.
Condition 2:Failing
When i am using statemtent
cout<<"\n"<
This i know that return was not there so the program crashed at runtime.
But the question is what made program run in Condition 1 . Even without the return statement was not present in the overloading function.
Program below
#include <iostream>
#include <stdio.h>
using namespace std;
class myvar{
private:
int var_x,var_y;
public:
friend ostream& operator<<(ostream &out,myvar n);
void setvalue(int x,int y)
{
var_x = x ;
var_y = y ;
}
};
ostream& operator<<(ostream &out,myvar n)
{
cout<<"("<<n.var_x<<","<<n.var_y<<")";
//return out;
}
int main()
{
myvar mv1,mv2,mv3;
mv1.setvalue(10,20);
mv2.setvalue(30,40);
mv3.setvalue(50,60);
//Working
// cout<<"\n"<<mv1<<mv2<<mv3;
//Not Working
// cout<<"\n"<<mv1<<mv2<<mv3<<"Hello"<<1243<<11.5;
}
This code has Undefined Behavior.
This is very bad. Usually it means that a crash will happen (but technically anything can happen).
ostream& operator<<(ostream &out,myvar n)
{
out<<"("<<n.var_x<<","<<n.var_y<<")"; // fixed cout to out.
//return out;
}
This is because you specify a return type in the function signature.
ostream& operator<<(ostream &out,myvar n)
^^^^^^^^
If your function does not contain a return keyword then your code is invalid. So for the function as defined (with the commented out return) your program will most likely crash.
If you change your code to:
void operator<<(ostream &out,myvar n)
{
out<<"("<<n.var_x<<","<<n.var_y<<")";
}
Now it will compile (be valid) and work.
But the consequence is you can not chain stream operations together.
myvar x;
// Set some value in x
// This will work fine.
std::cout << x;
// But this will fail to compile.
std::cout << x << " Another Thing";
Because the first call to operator<< returns a void the second call to operator<< does not know what to do.
So your best bet is to return the stream to allow chaining.
ostream& operator<<(ostream &out,myvar n)
{
out<<"("<<n.var_x<<","<<n.var_y<<")";
return out;
}
PS: Some space characters would be really nice to aid readability.
// This is easier to read for a human.
std::ostream& operator<<(std::ostream &out, myvar n)
{
out << "(" << n.var_x << "," << n.var_y << ")";
return out;
}
Yes, you always return the passed in ostream and probably want to pass in a const reference to the value you want outputed:
ostream& operator<<(ostream &out, const myvar& n)
{
out << "(" << n.var_x << "," << n.var_y << ")";
return out;
}
My biggest doubt is that why chaining of << in following statement
is working even without the return of out from overloaded function.
cout<<"\n"<<mv1<<mv2<<mv3;

what's the best practice to print out(print debugging information) for a class?

I am wondering what's the best practice to print out a class (say classA), I have several method
classA ca;
1) Define a debug method and inside this method , print out all its members.
2) Define a str() method, and use cout<< ca.str()
3) Define something like string conversion(I am not sure how yet), and just use cout << ca
The usual way is to overload operator<< roughly like this:
std::ostream &operator<<(std::ostream &out, classA const &a) {
// precise formatting depends on your use case. Do the same thing you would
// if you wanted to print a to cout or a file, because that is what this code
// will end up doing.
out << a.some_data() << ", " << a.some_more_data();
return out;
}
If classA has a limited interface (does not expose all relevant data members), it may be necessary to make the operator<< a friend of classA, such as
class A {
public:
// stuff
friend operator<<(std::ostream &out, classA const &a);
};
// private members can then be accessed
std::ostream &operator<<(std::ostream &out, classA const &a) {
out << a.some_private_member << ", " << a.some_other_private_member;
return out;
}
There is not usually a good reason to prevent read access to private members that you then enable the user to dump out per operator<<, though, since it would be rather leaky access control.
This then enables you to write
classA a;
std::cout << a;
std::ofstream file("foo.txt");
file << a;
std::ostringstream fmt;
fmt << a;
std::string s = fmt.str();
and so forth.
As a style note: It is possible to write
std::ostream &operator<<(std::ostream &out, classA const &a) {
// precise formatting depends on your use case
return out << a.some_data() << ", " << a.some_more_data();
}
This achieves the same thing as the split return because operator<< (by convention) returns the same stream object that was passed into it (to enable the chaining of << as in std::cout << i << j << k;).
Style note 2: If there is nothing in classA that makes it difficult, an upgrade to this technique is to write
template<typename char_type>
std::basic_ostream<char_type> &operator<<(std::basic_ostream<char_type> &out, classA const &a) {
// rest as before. Put it in a header because it is a function template now.
}
This enables you to write classA objects not only to cout, cerr, clog, ofstream, ostringstream etc., but also to their wchar_t counterparts wcout, wcerr, wclog, wofstream, and wostringstream. These are rarely used in practice, but often it will cost you nothing to implement this feature. The trick is that std::ostream and std::wostream -- base classes of all these output streams -- are aliases for std::basic_ostream<char> and std::basic_ostream<wchar_t>, respectively. That gives us this nice way to handle both (and potentially other) character classes without code duplication.
clog can be an option if you want to log your steps of a process in some file and review the file later to see what goes wrong. Also you can check state of data members at certain interval by logging them externally in file.

Writing a class object into a file using fstream and then read it

I want to make a class of a student and take 3 inputs information and make an output of this file. How to this? This is my try:
#include <iostream>
using namespace std;
class Student{
private:
char name[50];
char id[50];
int age;
public:
void getdata()
{
//take name as input
//take id as input
//take age as input
}
void showdata()
{
//display stored file
}
}
int main()
{
Student s1;
ofstream s1("student.txt"); //i want to store that 's1' object
//anything else
return 0;
}
C++ uses the stream paradigm to implement standard input/output.
Stream paradigm means that if you application wants to access/use a resource (A file, the console, etc) a stream acts as a mediator between your application and the resource:
ofstream +----+
+-------------------->|File|
| +----+
|
+------+------+
| Application |
+------+------+
|
| +-------+
+-------------------->|Console|
cout +-------+
It means every write/read operations you perform are really stream operations. The point of this is that stream operations are basically the same, independently of what type of resource (And what type of stream) are you using.
This allows us to implement a "generic" (Generic meaning valid for any type of stream/resource). How? Overloading C++ operators >> and <<.
For input operations (Input means receiving data from the stream and put it in our variable/object), we need to overload the >> operator as follows:
istream& operator>>(istream& is , MyClass& object)
{
is >> object.myClassAtributte; (1)
... //Same for every attribute of your class.
return is;
}
First, note that the input stream is passed by reference. By reference because streams are non-copyable (What exactly means to copy a stream? Copy the link between your app and the resource? That sounds ridiculous), and non-const beacuse you are going to modify the stream (You are going to write through it).
Finally, note that the function not returns void, returns a reference to the same stream that was passed to the function. That allows you to write concatenated-write/read sentences like cout << "Hello. " << "Im" << " Manu343726" << endl;
For output operations (Output means sending data to the stream), we need to overload the << operator, wich implementation is exactly the same:
ostream& operator<<(ostream& os , const MyClass& object)
{
os << object.myClassAtributte; (1)
... //Same for every attribute of your class.
return os;
}
Note that in this case, your object is passed const, beacuse we won't modify it (We will only read its attributes).
(1) Is preferable to implement this functions making them friend of your class, to allow us access to private/protected members.
You have to overload << and >> operators for ostream and istream
std::ostream& operator<< (std::ostream& stream, const Student& student)
std::istream& operator<< (std::istream& stream, Student& student)
make them friend and implement