I'm trying to create a function that will take ostream object as an argument, and then print to it. I plan to pass some of my fstream (files), and cout.
This is my code:
void printTask(int op1, int op2, int len, char operation, std::ostream& os = std::cout)
{
os << endl << " " << setw(len) << op1 << endl;
os << operation << " " << setw(len) << op2 << endl;
os << "-------------" << endl;
os << " ";
for(int i = 0; i < len; i++)
{
os << "?";
}
os << endl;
}
From main(), it goes like this...
ofstream output("output.txt", ios::out);
cout << addition(xyz, output) << endl;
and that function looks like this:
int addition(int xyz, ofstream file)
{
int op1 = ...;
int op2 = ...;
char choice = ...;
printTask(op1, op2, xyz, choice, file);
printTask(op1, op2, xyz, choice, cout); //this cout is not necessary, default parameter
}
I get an error about std::ios::base being private, but I did pass my ostream object by reference so it doesn't try to use copy constructor.
Any ideas?
EDIT: Wanted to update this with an answer. Prototype for addition was wrong, ofstream should be passed by reference, instead of copying it.
This works:
int addition(int xyz, ofstream& file) {...}
Big thanks to #Jarod42
Related
I hope this time my question is better formulated and formatted.
Here's the code that produces two separate outputs when I think it should not since I use everytime (I think) the overloaded operator<< for an enum type.
#include <iostream>
using namespace std;
enum Etat { Intact = 5 };
class Ship {
public:
Etat etat_;
Ship ( Etat t = Intact) : etat_(t) {}
~ Ship() {}
ostream& description ( ) const { return cout << "Etat: " << etat_ << " --- ";}
//---------------------------------------ˆˆˆˆ----
};
ostream& operator<< ( ostream& s, const Etat& etat_ )
{
switch ( etat_ )
{
case Intact: s << "intact"; break;
default: s << "unknown state";
}
return s;
}
ostream& operator<< ( ostream& s, Ship n ) { return s << "Etat: " << n.etat_ ; }
int main()
{
Etat etat_ = Intact;
cout << endl << endl << "Etat: "
<< etat_ << " \"cout << etat_\"" << endl << endl;
cout << Ship(etat_)
<< " \"cout << Ship(etat_)\"" << endl << endl;
cout << Ship(etat_).description()
<< " \"cout << Ship(etat_).description()\"" << endl << endl;
return 0;
}
This is what I get in the terminal:
Etat: intact "cout << etat_"
Etat: intact "cout << Ship(etat_)"
Etat: 5 --- 1 "cout << Ship(etat_).description()"
Can anyone explain to me why, in the last case, not only it takes the integer value of the enum attribut, but also adds a "1" after the test string " --- "???
The only thing I can think of is because I used an unorthodox return method in description(), ie 'return cout << ..", but it seems to work since the test string appears.
Is there a way to force the use of the operator<< overload in description()?
Thanks
In the description() function you are returning a reference to std::cout and use it in the std::cout call in main function. There is a reason why operator<< takes an ostream reference as it's first argument. You should modify your function like this and all should work:
ostream& description(ostream& os) const {
return os << "Etat: " << etat_ << " --- ";
}
The random "1" printed out there is caused likely due to the ostream in your example trying to print out reference to itself.
We know that the fascinating class iostream is something too powerful.
it has overloded the insertion operator "<<" to take many datatypes:
ostream& operator(ostream&, int),
ostream& operator(ostream&, char)...
we cannot instantiaate ostream: ostream print;
because ostream because its most CTORSs are "protected-socoped" (cannot be accessed from outside).
the only Constructor we can call is ostream(streambuf*) which takes a pointer to another class object ( class streambuf);
I just wanted to mess up with this class:
#include <ostream>
using namespace std;
int operator << (ostream& out, int* x)
{
out << "invoked!" << endl;
cout << *x; // works well!
cout << x; // normally works well and it prints the address that x points to but instead the program get in infinite loop or crushes!
return *x;
}
int main()
{
system("color 1f");
int* pVal = new int(57);
cout << *pVal << endl;
int* pX = new int(7);
cout << *pX << endl;
cout << *pVal << ", " << *pX << endl;
//cout << pVal << endl; // this doesn't work because my operator returns
//int and not a reference to ostream.
// and it is equal to: 0 << endl; which generates the same error
cout << pVal; // this works
// cout << endl << endl << endl;
return 0;
}
I overloaded the insertion operator to take an lvalue as a reference to an ostream object and a pointer to int as rvalue, I popup a message inside my function to get sure that it is invoked.
Note that I intentionally overloaded it to return int value so that no one can write:
out << pInt << *pInt << endl;
... but just:
out << pInt;
My problem, as you can see in the inline-comments above, is that whilst cout << x normally works well, instead the program get in infinite loop or crushes!
return *x;
Can anyone explain why I am getting the error?
The problem hapens because if you just cout << x, it will call your overloaded function over and over. It never returns.
Here's the solution (cast x to void*)
int operator << (ostream& out, int* x)
{
out << "invoked!" << endl;
cout << *x; // works well!
cout << (void*)x;
return *x;
}
I'm trying to overload the << operator for the display function call.
Heres my code:
#include <iostream>
#include <cstring>
using namespace std;
// global variable
const int MAX = 3;
// class definition
class CString{
char str[MAX+1];
public:
CString(char* param){
if(param == nullptr){
str[0] = '\0';
return;
}
strncpy(str,param,MAX);
str[MAX] = '\0';
}
void display(ostream& os){
os << str;
}
};
// << operator overloading
ostream& operator << (ostream& os, CString& cs){
static int call = 0;
os << call << ": ";
cs.display(os);
call++;
return os;
}
void process(char* parm){
CString cs(parm);
// here is where my issue is
cs.display(cout);
cout << endl;
}
//----------------------------------------------------------------
int main(int argc,char *argv[]){
cout << "Command Liine : ";
for(int arg = 0; arg < argc ; arg++){
cout << " " << argv[arg];
}
cout << endl;
if( argc == 1){
cout << "Insufffiecentnumber of arguemnts (min1)" << endl;
return 1;
}
cout << " Maxium numver of characters stored: " << MAX << endl;
for(int arg = 1; arg < argc; arg++){
process(argv[arg]);
}
return 0;
}
EDIT:
Here is the correct output and the output I have:
Correct:
Command Line : w1 oop345 btp305
Maximum number of characters stored : 3
0: oop
1: btp
Mine:
Command Line : w1 OOP345 DBS305
Maxium number of characters stored: 3
OOP
DBS
I'm having an issue with my << operator not working, I can't seem to figure it out. The ostream& operator<<(ostream& os, CString& cs) does not seem to be loading its syntax.
Question:
Does anyone know where my mistake has been made?
You wrote a correct overloading of << operator, but in method process() you used a public method display() of class CString instead of using << operator directly.
Just change one line in method process():
cs.display(cout); to: cout << cs;
void process(char* parm){
CString cs(parm);
// here is where my issue is
cout << cs;
cout << endl;
}
P.S. you do not need method CString::display at all as you already overload << operator for this class.
i have the following code
void print(int & a, double & b, string & c)
{
cout << setprecision(2) << fixed;
const double GPA = a/b;
if(c == "Y")
{
cout << "\n\nTotal number of credit hours: " << a << endl;
}
else
{
cout << "\n*** Grades are being held for not paying the tuition. ***"
}
}
How can I write the cout in print(int, double, string) into a text file without tampering with print(int, double, string);? I tried something like this
ofstream file;
file.open("file.txt");
file << print(a,b,c);
file.close();
cout << "file created" << endl;
but this doesn't compile. Why not, and how do I fix it?
The way you've written it, your print() function is not capable of outputting to any given stream. This is because it hard-codes the stream that it writes to as cout.
If you want it to be able to write to any given stream, you have to parameterize the stream as another function parameter. For (1) convenience and (2) compatibility with existing code that assumes print() only takes three arguments and writes to cout, you can make the new parameter optional by defaulting it to cout:
void print(int& a, double& b, string& c, ofstream& os=cout) {
os << setprecision(2) << fixed;
const double GPA = a/b;
if (c == "Y") {
os << "\n\nTotal number of credit hours: " << a << endl;
} else {
os << "\n*** Grades are being held for not paying the tuition. ***";
}
}
Then you can call it as follows:
print(a,b,c,file);
The reason why your code doesn't compile is that you cannot pass void as a function argument or operator operand. When a function is declared as returning void, that means it does not return anything at all. There is no data returned by print() to stream to the ofstream. The streaming takes place inside the function, so it is only there that you can select the stream to which the output will be written.
bgoldst's answer solves the problem as asked, but I recommend a completely different solution. Stick your data in a class that has operator<< overloaded.
struct class_results {
int credits;
double GP_total;
bool tuition_paid;
};
std::ostream& operator<<(std::ostream& out, const class_results& c) {
if (c.tuition_paid) {
const double GPA = c.credits/c.GP_total;
out << "Total number of credit hours: ";
out << setprecision(2) << fixed << c.credits<< '\n';
} else
out << "\n*** Grades are being held for not paying the tuition. ***"
return out;
}
Then usage is slightly more normal:
class_results results = {num_credits,GPTottal,tuition};
ofstream file;
file.open("file.txt");
file << results;
file.close();
cout << "file created" << endl;
How can I write the cout in print(int, double, string) into a text file without tampering with print(int, double, string);?
You can't.
The function print is broken and you can't do what you want without fixing it.
I have been looking for a solution but couldn't find what I need/want.
All I want to do is pass a stream intended for std::cout to a function, which manipulates it. What I have used so far is a template function:
template<typename T>
void printUpdate(T a){
std::cout << "blabla" << a << std::flush;
}
int main( int argc, char** argv ){
std::stringstream str;
str << " hello " << 1 + 4 << " goodbye";
printUpdate<>( str.str() );
return 0;
}
What I would prefer is something like:
printUpdate << " hello " << 1 + 4 << " goodbye";
or
std::cout << printUpdate << " hello " << 1 + 4 << " goodbye";
I was trying to do:
void printUpdate(std::istream& a){
std::cout << "blabla" << a << std::flush;
}
but that gave me:
error: invalid operands of types ‘void(std::istream&) {aka void(std::basic_istream<char>&)}’ and ‘const char [5]’ to binary ‘operator<<’
You can't output data to an input stream, just not a good thing to do.
Change:
void printUpdate(std::istream& a){
std::cout << "blabla" << a << std::flush;
}
To:
void printUpdate(std::ostream& a){
std::cout << "blabla" << a << std::flush;
}
Note the stream type change.
Edit 1:
Also, you can't output a stream to another stream, at least std::cout.
The return value of << a is a type ostream.
The cout stream doesn't like being fed another stream.
Change to:
void printUpdate(std::ostream& a)
{
static const std::string text = "blabla";
std::cout << text << std::flush;
a << text << std::flush;
}
Edit 2:
You need to pass a stream to a function requiring a stream.
You can't pass a string to a function requiring a stream.
Try this:
void printUpdate(std::ostream& out, const std::string& text)
{
std::cout << text << std::flush;
out << text << std::flush;
}
int main(void)
{
std::ofstream my_file("test.txt");
printUpdate(my_file, "Apples fall from trees.\n");
return 0;
}
Chaining Output Streams
If you want to chain things to the output stream, like results from functions, the functions either have to return a printable (streamable object) or the same output stream.
Example:
std::ostream& Fred(std::ostream& out, const std::string text)
{
out << "--Fred-- " << text;
return out;
}
int main(void)
{
std::cout << "Hello " << Fred("World!\n");
return 0;
}