How can I (in an external function) differentiate between cout << thingToShow and outfile << thingToWrite with different formats?
I have a single file that I am supposed to build all this implementation around without changing anything, and there are instances of
cout << "\nx matrix is: \n";
cout << x;
cout << "\ny matrix is: \n";
cout << y;
which are supposed to be formatted as
x matrix is:
--- ---
| 30 50 |
| |
| 25 40 |
--- ---
y matrix is:
--- ---
| 2 3 |
| |
| 1 1 |
--- ---
and I have instance of
w = r * w;
outfile << w;
which are supposed to be formatted simply as
-20 40
-80 60
my implementation is
ostream& operator<< (ostream &out, const Matrix& y){
out << "\t\t" << " ---\t\t\t\t ---\n"<< "\t\t|\t\t"<<y.tl<< "\t"<<y.tr<< "\t\t|\n\t\t|\t\t\t\t\t|\n\t\t|\t\t"<<y.bl<< "\t"<<y.br<< "\t\t|\n" << "\t\t" << " ---\t\t\t\t ---\n\n";
return out;
}
which works for the standard cout << thingToShow output format, but obviously messes up the outfile << thingToWrite format.
is there a property of the (stream &out,) argument I can put in an if statement? or is there some other way to differentiate between cout and outfile?
You can test if your ostream is cout:
if (&out == &std::cout)
And you can take the appropriate action, depending upon the result. But if you want my unsolicited opinion, I think it would be better to let the user decide how it prints out, using some kind of formatting class:
std::cout << format(my_matrix, fancy);
outfile << format(my_matrix, not_fancy);
In this example, format would be a function which returns an object of some class which holds a Matrix object (by reference), and formatting options. This class would have its operator<< overloaded to produce the appropriate output to the stream based on the options that were given to it. Alternatively, you could make your own specialized i/o manipulators.
Not quite as easy as I thought.
It can be done by overloading std::ifstream. That means you have to overload it for all types so a catch-all template overload is needed in addition to your Matrix overload.
struct Matrix
{
int a, b;
};
// Matrix for std::cout
std::ostream& operator<<(std::ostream& os, const Matrix& t)
{
os << "[\n\t" << t.a << "\n\t" << t.b << "\n]";
return os;
}
// overload of general types for files
template<typename Type>
std::ofstream& operator<<(std::ofstream& ofs, const Type& t)
{
// this cast prevents infinite recursion
static_cast<std::ostream&>(ofs) << t;
return ofs;
}
// Matrix overload for files
std::ofstream& operator<<(std::ofstream& ofs, const Matrix& t)
{
// this cast prevents infinite recursion
static_cast<std::ostream&>(ofs) << "{" << t.a << ", " << t.b << "}";
return ofs;
}
int main()
{
std::ofstream ofs("test.txt");
Matrix m {3, 7};
std::cout << 4 << m << 9 << '\n';
ofs << 4 << m << 9 << '\n';
}
Output: std::cout
4[
3
7
]9
Output: ofs
4{3, 7}9
NOTE: This approach distinguishes between std::ofstream and its parent class std::ostream. This means you have to pass your std::ifstream explicitly typed to any functions if you want this behaviour to be available within the function.
You need to maintain some short of state to decide whether the output is going to be in short format or the long format. The best place to maintain that data is, I think, in the class Matrix itself.
Then, provide functions that can be used to set the format. You can also provide an overloaded operator<< function so you can use them with an ostream.
Here's a working version.
#include <iostream>
struct Matrix
{
int tl;
int tr;
int bl;
int br;
static void setLongFormat();
static void setShortFormat();
enum OutputFormat
{
LONG_FROMAT,
SHORT_FORMAT
};
static OutputFormat outputFormat;
};
Matrix::OutputFormat Matrix::outputFormat = Matrix::SHORT_FORMAT;
void Matrix::setLongFormat()
{
outputFormat = LONG_FROMAT;
}
void Matrix::setShortFormat()
{
outputFormat = SHORT_FORMAT;
}
std::ostream& operator<< (std::ostream &out, const Matrix& y)
{
if ( Matrix::outputFormat == Matrix::LONG_FROMAT )
{
out << "\t\t" << " ---\t\t\t\t ---\n"
<< "\t\t|\t\t"<<y.tl<< "\t"<<y.tr<< "\t\t|\n"
<< "\t\t|\t\t\t\t\t|\n"
<< "\t\t|\t\t"<<y.bl<< "\t"<<y.br<< "\t\t|\n"
<< "\t\t" << " ---\t\t\t\t ---\n\n";
}
else
{
out << y.tl<< "\t" << y.tr<< "\n"
<< y.bl<< "\t" << y.br<< "\n";
}
return out;
}
std::ostream& operator<<(std::ostream &out, void (*fun)())
{
fun();
return out;
}
int main()
{
Matrix a{30, 50, 25, 40};
std::cout << Matrix::setLongFormat << a << std::endl;
std::cout << Matrix::setShortFormat << a << std::endl;
};
Output:
--- ---
| 30 50 |
| |
| 25 40 |
--- ---
30 50
25 40
PS. The tabs don't look quite right here. I am sure the function can be modified to keep the tabs in their correct location.
Related
I am trying to overload
<<
operator. For instance
cout << a << " " << b << " "; // I am not allowed to change this line
is given I have to print it in format
<literal_valueof_a><"\n>
<literal_valueof_b><"\n">
<"\n">
I tried to overload << operator giving string as argument but it is not working. So I guess literal
" "
is not a string. If it is not then what is it. And how to overload it?
Kindly help;
Full code
//Begin Program
// Begin -> Non - Editable
#include <iostream>
#include <string>
using namespace std;
// End -> Non -Editable
//---------------------------------------------------------------------
// Begin -> Editable (I have written )
ostream& operator << (ostream& os, const string& str) {
string s = " ";
if(str == " ") {
os << '\n';
}
else {
for(int i = 0; i < str.length(); ++i)
os << str[i];
}
return os;
}
// End -> Editable
//--------------------------------------------------------------------------
// Begin -> No-Editable
int main() {
int a, b;
double s, t;
string mr, ms;
cin >> a >> b >> s >> t ;
cin >> mr >> ms ;
cout << a << " " << b << " " ;
cout << s << " " << t << " " ;
cout << mr << " " << ms ;
return 0;
}
// End -> Non-Editable
//End Program
Inputs and outputs
Input
30 20 5.6 2.3 hello world
Output
30
20
5.6
2.3
hello
world
" " is a string-literal of length one, and thus has type const char[2]. std::string is not related.
Theoretically, you could thus overload it as:
auto& operator<<(std::ostream& os, const char (&s)[2]) {
return os << (*s == ' ' && !s[1] ? +"\n" : +s);
}
While that trumps all the other overloads, now things get really hairy. The problem is that some_ostream << " " is likely not uncommon, even in templates, and now no longer resolves to calling the standard function. Those templates now have a different definition in the affected translation-units than in non-affected ones, thus violating the one-definition-rule.
What you should do, is not try to apply a global solution to a very local problem:
Preferably, modify your code currently streaming the space-character.
Alternatively, write your own stream-buffer which translates it as you wish, into newline.
Sure this is possible, as I have tested. It should be portable since you are specifying an override of a templated function operator<<() included from <iostream>. The " " string in your code is not a std::string, but rather a C-style string (i.e. a const char *). The following definition works correctly:
ostream& operator << (ostream& os, const char *str) {
if(strcmp(str, " ") == 0) {
os << '\n';
} else {
// Call the standard library implementation
operator<< < std::char_traits<char> > (os, str);
}
return os;
}
Note that the space after std::char_traits<char> is necessary only if you are pre-c++11.
Edit 1
I agree with Deduplicator that this is a potentially dangerous solution as it may cause undesirable consequences elsewhere in the code base. If it is needed only in the current file, you could make it a static function (by putting it within an unnamed namespace). Perhaps if you shared more about the specifics of your problem, we could come up with a cleaner solution for you.
You might want to go with a user defined literal, e.g.
struct NewLine {};
std::ostream& operator << (std::ostream& os, NewLine)
{
return os << "\n";
}
NewLine operator ""_nl(const char*, std::size_t) // "nl" for newline
{
return {};
}
This can be used as follows.
int main(int, char **)
{
std::cout << 42 << ""_nl << "43" << ""_nl;
return 0;
}
Note three things here:
You can pass any string literal followed by the literal identifier, ""_nl does the same thing as " "_nl or "hello, world"_nl. You can change this by adjusting the function returning the NewLine object.
This solution is more of an awkward and confusing hack. The only real use case I can imagine is pertaining the option to easily change the behavior at a later point in time.
When doing something non-standard, it's best to make that obvious and explicit - here, the user defined literal indeed shines, because << ""_nl is more likely to catch readers' attention than << " ".
I often do something like:
uint8_t c=some_value;
std::cout << std::setfill('0') << std::setw(2);
std::cout << std::hex << int(c);
std::cout << std::setfill(' ');
(in particular while dumping debugging information). Wouldn't it be nice to have something manipulatorish that I could put in a stream like this:
std::cout << "c value: 0x" << hexb(c) << '\n';
that would do all of that? Does anyone know how to do that?
I've gotten this to work but would love to have a simpler way:
#include <iostream>
#include <iomanip>
class hexcdumper{
public:
hexcdumper(uint8_t c):c(c){};
std::ostream&
operator( )(std::ostream& os) const
{
// set fill and width and save the previous versions to be restored later
char fill=os.fill('0');
std::streamsize ss=os.width(2);
// save the format flags so we can restore them after setting std::hex
std::ios::fmtflags ff=os.flags();
// output the character with hex formatting
os << std::hex << int(c);
// now restore the fill, width and flags
os.fill(fill);
os.width(ss);
os.flags(ff);
return os;
}
private:
uint8_t c;
};
hexcdumper
hexb(uint8_t c)
{
// dump a hex byte with width 2 and a fill character of '0'
return(hexcdumper(c));
}
std::ostream& operator<<(std::ostream& os, const hexcdumper& hcd)
{
return(hcd(os));
}
When I do this:
std::cout << "0x" << hexb(14) << '\n';
hexb(c) is invoked and returns a hexcdumper whose constructor saves c
the overloaded operator<< for hexcdumper invokes
hexcdumper::operator() passing it the stream
hexcdumper's operator() does all the magic for us
after hexcdumper::operator() returns, the overloaded operator<<
returns the stream as returned from hexcdumper::operator() so chaining works.
On the output, I see:
0x0e
Is there a simpler way to do this?
Patrick
You can do this directly on the stream pipe:
std::cout << "Hex = 0x" << hex << 14 << ", decimal = #" << dec << 14 << endl;
Output:
Hex = 0xe, decimal = #14
I'm trying to convert a string streamed phone lookup program into file streamed.. I'm missing something, but I'm stuck.. what members can I use in the ofstream process to get this working?
ofstream& process (ofstream &os, vector<PersonInfo> people)
{
// for each entry in people
for (vector<PersonInfo>::const_iterator entry = people.begin();
entry != people.end(); ++entry) {
ofstream formatted, badNums; // objects created on each loop
// for each number
for (vector<string>::const_iterator nums = entry->phones.begin();
nums != entry->phones.end(); ++nums) {
if (!valid(*nums)) {
badNums << " " << *nums; // string in badNums
} else
// ``writes'' to formatted's string
formatted << " " << format(*nums);
}
if (badNums.empty()) // there were no bad numbers
os << entry->name << " " // print the name
<< formatted.str() << endl; // and reformatted numbers
else // otherwise, print the name and bad numbers
cerr << "input error: " << entry->name
<< " invalid number(s) " << badNums.str() << endl;
}
return os;
}
First, you don't want an ofstream, except at the point you're opening
the file (creating the instance). The output stream interface is
defined by std::ostream; std::ofstream derives from this, as does
std::ostringstream (output can become an std::string), and in most
applications, a couple of others written by the local programmers. In
your case (if I've understood the problem correctly), what you want is:
std::ostream& process( std::ostream& os,
std::vector<PersonInfo> const& people )
// Note the use of a const reference above. No point
// in copying the entire vector if you're not going to
// modify it.
{
for ( std::vector<PersonInfo>::const_iterator entry = people.begin();
entry != people.end();
++ entry ) {
std::ostringstream formatted;
std::ostringstream badNums;
// ...
if ( badNums.str().empty() ) {
os << ... << formatted.str() << std::endl;
} else {
os << ... << badNums.str() << std::endl;
}
}
return os;
}
Note the different types: std::ostream formats output, independently
of the destination type. std::ofstream derives from it, and provides
a file as destination. std::ostringstream derives from it, and
provides a std::string as destination type. And the std::ostream
takes a std::streambuf* as argument, and you provide the destination
type.
You never associate a file with ostream, so the compiler doesn't know what to do with the data you write into it.
ofstream& process (ofstream &os, vector<PersonInfo> people)
{
os.open("Data.txt"); //open file to be used
if(!os.is_open())
std::cerr << "Error opening file!\n";
//rest of code goes here
}
EDIT: after reading through your program again, i noticed you're using ofstream wrong. Ofstream is for opening and writing FILES.The program has a lot of syntax and logical errors i would read up on it more here.
It looks like you don't need to use ofstreams for the internal parts of this function. In fact you don't need to use streams at all, a std::string would do:
ofstream& process (ofstream &os, vector<PersonInfo> people)
{
// for each entry in people
for (vector<PersonInfo>::const_iterator entry = people.begin();
entry != people.end(); ++entry) {
string formatted, badNums; // objects created on each loop
// for each number
for (vector<string>::const_iterator nums = entry->phones.begin();
nums != entry->phones.end(); ++nums) {
if (!valid(*nums)) {
badNums += " " + *nums; // string in badNums
} else
// ``writes'' to formatted's string
formatted += " " + format(*nums);
}
if (badNums.empty()) // there were no bad numbers
os << entry->name << " " // print the name
<< formatted << endl; // and reformatted numbers
else // otherwise, print the name and bad numbers
cerr << "input error: " << entry->name
<< " invalid number(s) " << badNums << endl;
}
return os;
}
So in my program I have some classes - Button, Window and WindowButton. Button consists only of text, Window - of a button and coordinates(x,y), and WindowButton consists of a Window.
In WindowButton, I have overloaded the << operator like this:
ostream& operator<<(ostream& out, WindowButton& ref)
{
ref.print();
return out;
}
Where the print function looks like:
void WindowButton::print()
{
theWindow->print();
}
And the window print function, in window class:
void Window::print()
{
char* buttonText = button->getText();
char* theText = new char[strlen(buttonText)+1];
strcpy(theText, buttonText);
cout << endl << "Window with coordinates (" << this->coord.x << "," << this->coord.y << ") , and button text \"" << theText << "\"" << endl;
}
In main:
WindowButton *test = new WindowButton();
cout << endl << test;
test->print();
The last line provides the right output, but the second line provides just a memory adress. What am I doing wrong? Everything should be working fine, because the test->print(); works fine.
You are passing a pointer to operator<< which expects a &.
cout << endl << *test;
You might also make it:
ostream& operator<<(ostream& out, const WindowButton& ref){
Which assumes print doesn't actually modify.
But, the bigger question is why are you using the cout ostream to trigger printing to theWindow -- these appear to be (though aren't) logically disconnected processes. You could pass the given stream into Window::print:
void Window::print(ostream& stream) {
and use that stream in place of cout. This avoids hard-coding cout into Window::print().
It's a pointer, so you'll need to dereference it for the operator to work:
cout << endl << *test;
This line
cout << endl << test;
prints a pointer to WindowButton, and there is an ostream& operator<< specialization for pointers, which prints the address. You can try de-referencing the pointer:
cout << endl << (*test);
As an aside, there is little point in overloading the ostream& operator<< in a way that eventually just prints to std::cout. The point of such an operator is that you can stream to any ostream, not just cout. You could fix this by modifying your print functions to take an ostream by reference, and modify it:
void WindowButton::print(std::ostream& out) const {
theWindow->print(out);
}
and
void Window::print(ostream& out) const {
// stuff
out << "Window with coordinates (" << this->coord.x << "," << this->coord.y << ") , and button text \"" << theText << "\"" << endl;
}
and finally
ostream& operator<<(ostream& out, const WindowButton& ref){
ref.print(out);
return out;
}
How would someone do that?
for example I do like:
std::cout << "something";
then it should print the time before "something"
Make your own stream for that :) This should work:
class TimedStream {
public:
template<typename T>
TimedStream& operator<<(const T& t) {
std::cout << getSomeFormattedTimeAsString() << t << std::endl;
return *this;
}
};
TimedStream timed_cout;
void func() {
timed_cout << "123";
}
You'd be able to use this class for every type for which std::cout << obj can be done, so no further work is needed.
But please note that the time will be written before every <<, so you cannot chain them easily. Another solution with explicit timestamp is:
class TimestampDummy {} timestamp;
ostream& operator<<(ostream& o, TimestampDummy& t) {
o << yourFancyFormattedTimestamp();
}
void func() {
cout << timestamp << "123 " << 456 << endl;
}
You could use a simple function that prints the timestamp and then returns the stream for further printing:
std::ostream& tcout() {
// Todo: get a timestamp in the desired format
return std::cout << timestamp << ": ";
}
You would then call this function instead of using std::cout directly, whenever you want a timestamp inserted:
tcout() << "Hello" << std::endl;
ostream& printTimeWithString(ostream& out, const string& value)
{
out << currentTime() << ' ' << value << std::endl;
return out;
}
Generate current time using your favourite Boost.DateTime output format.
This looks like homework. You want something in the line of:
std::cout << time << "something";
Find a way the retrieve the time on your system, using a system call.
Then you'll have to implement a << operator for your system-dependent time class/struct.