using setw with user-defined ostream operators - c++

How do I make setw or something similar (boost format?) work with my user-defined ostream operators? setw only applies to the next element pushed to the stream.
For example:
cout << " approx: " << setw(10) << myX;
where myX is of type X, and I have my own
ostream& operator<<(ostream& os, const X &g) {
return os << "(" << g.a() << ", " << g.b() << ")";
}

Just make sure that all your output is sent to the stream as part of the same call to operator<<. A straightforward way to achieve this is to use an auxiliary ostringstream object:
#include <sstream>
ostream& operator<<(ostream& os, const X & g) {
ostringstream oss;
oss << "(" << g.a() << ", " << g.b() << ")";
return os << oss.str();
}

maybe like so using the width function:
ostream& operator<<(ostream& os, const X &g) {
int w = os.width();
return os << "(" << setw(w) << g.a() << ", " << setw(w) << g.b() << ")";
}

Related

C++ access object behind iterator in loop

I have created a list of objects of a class.
The class has an overloaded ostream << operator to output customer data in a structured way.
What I am trying to do is loop over the list of objects and call cout on the object in the iteration.
Code for the loop is as follows:
for (list<Kunde>::iterator it = this->kun_list.begin(); it != this->kun_list.end(); ++it) {
cout << it << endl;
}
With Kunde being the class with the overloaded << operator and kun_list being the list of objects of type Kunde.
friendly overload within the Kunde class:
friend ostream& operator<< (ostream& os, Kunde& kd) {
os << "__Kundendaten__" << endl;
os << "Name: " << kd.vorname << " " << kd.name << endl;
os << "Geburtsjahr: "<< kd.geburtsjahr << endl;
os << "Adresse: " << kd.strasse << " " << kd.hausnummer << endl << kd.plz << " " << kd.ort << endl;
os << "Telefon: " << kd.telefonnummer << endl;
string fschein = "Nein.";
if (kd.klasse_a_vorhanden) {fschein = "Ja.";}
os << "Führerschein Kl. A vorhanden: " << fschein << endl;
return os;
};
The above loop does not work because I am using the list iterator instead of an object of class Kunde. I can access members of Kunde via it→member but how do I use that iterator as reference to the whole object?
Thanks!
Use a const reference loop over the container:
for (const auto & kunde : kun_list) {
cout << kunde << endl;
}
Obviously you also have to fix <<:
friend ostream& operator<< (ostream& os, const Kunde& kd) {...}

Setting precision/field width in operator<< for an entire vector

The code below prints a vector to std::cout.
struct vect {
double x;
double y;
};
std::ostream& operator<<(std::ostream& os, vect v){
os << "[" << v.x << " " << v.y << "]";
return os;
}
int main(){
vect v = {1.0, 2.0};
std::cout << v << std::endl;
return 0;
}
What would be a good way to control the width/precision of each field? I could hardcode it in operator<<:
std::ostream& operator<<(std::ostream& os, vect v){
os << "[" << std::setprecision(3) << std::setw(7) << v.x << " " << std::setprecision(3) << std::setw(7) << v.y << "]";
return os;
}
but I would rather want to control it from the outside:
std::cout << std::setprecision(3) << std::setw(7) << v << std::endl;
However I think this would only set the precision and width for the first field of the vector.
What I have in mind is to first "getw" and "getprecision" at the start of operator<< and then persist them to the other fields. Are there ways to retrieve these things from the stream, and is this basic design based on correct assumptions? (I'm not very confident about how iomanipulators work; I just know to send in std::setw before the data.)
as covered in comments, setprecision persists, but setw does not.
Supposing you want setw to apply to each individual field in your composition type, but not to the formatting characters around it. To do this, look at the width property, then set it for each of the numeric fields.
#include <iostream>
#include <iomanip>
struct coordinate {
double x;
double y;
};
std::ostream& operator<<(std::ostream& os, coordinate p) {
auto w = os.width();
os << std::setw(0) << "[" // we don't want the width yet
<< std::setw(w) << p.x // set width on specific field
<< " "
<< std::setw(w) << p.y // set width on specific field
<< "]";
return os;
}
int main() {
coordinate value = { 1.000019, 2.000019 };
std::cout << std::setprecision(3) << std::setw(7) << value << std::endl;
std::cout << std::setprecision(6) << std::setw(7) << value << std::endl;
std::cout << std::setprecision(1) << std::setw(3) << value << std::endl;
return 0;
}
output:
[ 1 2]
[1.00002 2.00002]
[ 1 2]
This is what I've done. Is it a sound design?
std::ostream& operator<<(std::ostream& os, vect v){
auto p = os.precision();
auto w = os.width();
os << "[" << std::setprecision(p) << std::setw(w) << v.x << " " << std::setprecision(p) << std::setw(w) << v.y << "]";
return os;
}
However I think this would only set the precision and width for the first field of the vector.
I think you should verify this before spending more time trying to "solve" it.
(not really an answer, but I can't quote, etc in a comment)

Comma separate in overloading ostream and istream in struct

I want my struct PersonData to get the output (firstname,lastname,personage,countrycode,income) with the comma seperator.
I have written this code but it only works with whitespace.
So output will be (firstname lastname personage countrycode income)
How can i change this to ,(comma) instead?
std::ostream& operator<<(std::ostream& output, const PersonData &pd)
{
output << pd.firstName << " " << pd.lastName << " " << pd.age << " " << pd.countryCode <<
" " << pd.income;
return output;
}
std::istream& operator>>(std::istream& indata, PersonData &pd)
{
indata >> pd.firstName >> pd.lastName >> pd.age >> pd.countryCode >> pd.income;
}
You can just change symbols (string literals) you've been outputting between PersonData's fields.
std::ostream& operator<<(std::ostream& output, const PersonData &pd)
{
output << pd.firstName << ", " << pd.lastName << ", " << pd.age << ", " << pd.countryCode <<
", " << pd.income;
return output;
}

Can't get rid of trash while overloading operator << in C++

class point //declaration of class
{
private:
int x, y;
friend std::ostream &operator << (std::ostream &input, point &p);
public:
//constructors and some other methods
};
//definition of overloading <<
std::ostream &operator << (std::ostream &input, point &p)
{
input << std::cout << "x = " << p.x << " y = " << p.y << " ";
return input;
}
And it works but when I use it
std::cout << object;
it shows some trash before my text:
062ACC3E8x = 1 y = 22
So 062ACC3E8X is something that always appears. It is defferent if I restart Visual Studio which I'm working on, so I suppose It's some memory adress. How to get rid of it? Is it something missing or wrong in my code?
You output some adress, since std::ostream has implicit void* conversion operator.
1) Returns a null pointer if fail() returns true, otherwise returns a
non-null pointer. This pointer is implicitly convertible to bool and
may be used in boolean contexts.
Should be just
input << "x = " << p.x << " y = " << p.y << " ";
You are passing std::cout into your output stream. Change your code to:
//definition of overloading <<
std::ostream &operator << (std::ostream &input, point &p)
{
input << "x = " << p.x << " y = " << p.y << " ";
return input;
}

Errors with operator overloading

i have two different operator overloading. For some reason it is giving error.
If i remove one of it, than it does not show any error. May i know why ?
Can i combine both ?
This is used for printing on screen.
ostream& operator<<(ostream &out, const Point &p) {
return out << "[" << setw(4) << p.getX() << setw(1) << "," << setw(4) << p.getY() << "] " << setprecision(3) << p.getScalarValue() << endl;
}
This is used for printing on a text file.
ofstream& operator<<(ofstream &out, const Point2D &p){
return out << "[" << setw(4) << p.getX() << setw(1) << "," << setw(4) << p.getY() << "] " << setprecision(3) << p.getScalarValue() << endl;
}
Error:
Point.cpp:91:147: error: invalid initialization of reference of type ‘std::ofstream& {aka std::basic_ofstream&}’ from expression of type ‘std::basic_ostream::__ostream_type {aka std::basic_ostream}’
You do not need the second version. You can use the first:
Point p;
std::ofstream pointsFile("points.txt");
pointsFile << p << "\n";
First, The std::ostream& operator<< works for writing to files as well as writing to the standard output or stderrt
Second, assuming Poind2D inherits from Point, passing a Point2D to a function or operator that takes a Point reference will work too.