cout << setw(20) << setiosflags(std::ios_base::left) << stamp; // this is char stamp[200] dataype.
cout << setw(1) << setiosflags(std::ios_base::left) << " ";
cout << setw(10) << setiosflags(std::ios_base::left) << appName1; // this is stl string data dtype
cout << setw(1) << setiosflags(std::ios_base::left) << ":";
cout << setw(15) << setiosflags(std::ios_base::left) << myname; // this is stl string data type.
cout << setw(1) << setiosflags(std::ios_base::left) << ":";
cout << setw(10) << setiosflags(std::ios_base::left) << myotherappname; // this is stl string data type.
cout << endl;
cout << finallyMyMessage; // this is char finallyMyMessage[200];
now my requirement is to put the above formatted text to file also in addition to console. I know that we can do this with ostringstream, but not able to sampel code how we can do this. Can any one help me in providing an exampel code how we can do this using ostringstream, later i can write to file using using ostreamobject.
Thanks!
Streams are polymorphic. They all derive from a common base class. That common base class defines most operations. Derived classes just setup the right stream buffer.
So use them polymorphically:
void write(std::ostream& os)
{
os << setw(20) << setiosflags(std::ios_base::left) << stamp;
os << setw(1) << setiosflags(std::ios_base::left) << " ";
os << setw(10) << setiosflags(std::ios_base::left) << appName1;
os << setw(1) << setiosflags(std::ios_base::left) << ":";
os << setw(15) << setiosflags(std::ios_base::left) << myname;
os << setw(1) << setiosflags(std::ios_base::left) << ":";
os << setw(10) << setiosflags(std::ios_base::left) << myotherappname;
os << endl;
os << finallyMyMessage;
}
// ...
write(std::cout);
std::ostringstream oss;
write(oss);
std::ofstream ofs("file.txt");
write(ofs);
If you have boost available, you can use the boost format library:
#include <boost/format.hpp>
cout << format("%20s %10s %15s %10s") % stamp % appName1 % myname % myotherappname << endl;
you can send the output to any ostream-derived type.
What you actually need is an ofstream to write to a file. Writing to a ostringstream first and then writing that string to both console and file may indeed be faster, but let's start with how to write to a file:
ostream& st = use_file? ofstream("output.txt"): cout;
ofstream st("output.txt");
st << setw(20) << setiosflags(std::ios_base::left) << stamp; // this is char stamp[200] dataype.
st << setw(1) << setiosflags(std::ios_base::left) << " ";
st << setw(10) << setiosflags(std::ios_base::left) << appName1; // this is stl string data dtype
st << setw(1) << setiosflags(std::ios_base::left) << ":";
st << setw(15) << setiosflags(std::ios_base::left) << myname; // this is stl string data type.
st << setw(1) << setiosflags(std::ios_base::left) << ":";
st << setw(10) << setiosflags(std::ios_base::left) << myotherappname; // this is stl string data type.
st << endl;
st << finallyMyMessage; // this is char finallyMyMessage[200];
You can use the OS to do this.
On unix you have tee
./a.out | tee plop.txt
Dumps output to file "plop.txt" and console.
Pretty straightforward really...
#include <sstream>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <string>
int main(int argc, char* argv[])
{
std::ostringstream oss;
// defined just so my example will compile
std::string stamp, appName1, myname, myotherappname, finallyMyMessage;
oss << std::setw(20) << std::setiosflags(std::ios_base::left) << stamp; // this is char stamp[200] dataype.
oss << std::setw(1) << std::setiosflags(std::ios_base::left) << " ";
oss << std::setw(10) << std::setiosflags(std::ios_base::left) << appName1; // this is stl string data dtype
oss << std::setw(1) << std::setiosflags(std::ios_base::left) << ":";
oss << std::setw(15) << std::setiosflags(std::ios_base::left) << myname; // this is stl string data type.
oss << std::setw(1) << std::setiosflags(std::ios_base::left) << ":";
oss << std::setw(10) << std::setiosflags(std::ios_base::left) << myotherappname; // this is stl string data type.
oss << std::endl;
oss << finallyMyMessage; // this is char finallyMyMessage[200];
// ...
std::ofstream outfile("something.txt"); // open a file for writing
outfile << oss.str(); // output the ostringstream's string to the ofstream
outfil.close();
// or if you need a char*...
std::string str(oss.str());
usecharstar(str.c_str());
return 0;
}
You don't have to repeat the left adjust for each output, it sticks to the stream.
You also don't have to change width for each output, as it sets the minimum width for the field. That makes width(1) totally meaningless for a single character output.
This is easy. You are just trying too hard!
Related
My Code:
#include <iostream>
#include <iomanip>
using namespace std;
int main () {
int time;
int honolulu, seattle, london, moscow, hongkong, auckland;
cout << "What is the current time in Philadelphia? ";
cin >> time;
honolulu = (time+2400-600)%2400;
seattle = (time+2400-300)%2400;
london = (time+2400+500)%2400;
moscow = (time+2400+800)%2400;
hongkong = (time+2400+1200)%2400;
auckland = (time+2400+1700)%2400;
cout << endl << "Current times in other cities: " << endl;
cout << setw (12) << left << "Honolulu:";
cout << setw (4) << setfill('0') << honolulu << endl;
cout << setw (12) << left << "Seattle:";
cout << setw (4) << setfill('0') << seattle << endl;
cout << setw (12) << left << "London:";
cout << setw (4) << setfill('0') << london << endl;
cout << setw (12) << left << "Moscow:";
cout << setw (4) << setfill('0') << moscow << endl;
cout << setw (12) << left << "Hong Kong:";
cout << setw (4) << setfill('0') << hongkong << endl;
cout << setw (12) << left << "Auckland:";
cout << setw (4) << setfill('0') << auckland << endl;
return 0;
}
Required Output :
What is the current time in Philadelphia? 0415
Current times in other cities:
Honolulu: 2215
Seattle: 1150
London: 9150
Moscow: 1215
Hong Kong: 1615
Auckland: 2115
My output :
What is the current time in Philadelphia? 0415
Current times in other cities:
Honolulu: 2215
Seattle:00001150
London:000009150
Moscow:000001215
Hong Kong:001615
Auckland:0002115
What am I doing wrong? The first line of output, Honolulu: 2215, is correct. But the next lines have leading zeroes. I do not understand why this is happening? Is there a problem with my code or am I misunderstanding how the functions setfill and setw work?
The fill character is "sticky", so it remains in effect until you change it.
In your case, you want 0 as the fill for the numeric fields, but space as the fill for the character fields, so you'll have to set that explicitly, something like this:
cout << setfill(' ') << setw (12) << left << "Seattle:";
Many of the iomanip objects are "sticky", that is, they stick to the stream and affect subsequent lines.
When you have this:
cout << setw (12) << left << "Seattle:";
cout << setw (4) << setfill('0') << seattle << endl;
that is going to leave the setfill active for the next line. So you might instead prefer
cout << setw (12) << setfill(' ') << left << "Seattle:";
cout << setw (4) << setfill('0') << seattle << endl;
As mentioned in other comments many of I/O manipulators are "sticky".
I personally prefer to solve this kind of problem using RAII:
class stream_format_raii {
public:
stream_format_raii(std::ostream &stream)
: stream_(stream)
, state_(NULL) {
state_.copyfmt(stream_);
}
~stream_format_raii() {
stream_.copyfmt(state_);
}
public:
std::ostream &stream_;
std::ios state_;
};
That this class does is backing up your current stream's format upon constructing and setting it back upon destructing.
You can use it this way:
void printCity(std::ostream &os, const std::string name, int time) {
stream_format_raii back(os);
os << std::setw(12) << std::left << (name + ":");
os << std::setw(4) << std::setfill('0') << time;
}
int main() {
// Same as before
printCity(std::cout, "Honolulu", honolulu);
// Same as before
}
I have been at this for days now and I just can't seem to find out why my last two things won't print. The code is quite long so I won't post it all , but if you need it I am willing to provide the entire source.
Basically I call the print function after adding 1 element to each of the listed elements. It will print them all EXCEPT the last two Spouse and Child. Those two are the most complicated as they are their own lists as well. When I tested the for loop for child it showed that no matter how many children I add to the Vector it reads the size as 0. Why is this?
void AddressNode::PrintFull()
{
cout << setfill(' ') << endl;
cout << setw(15) << "UID " << "ID" << setfill('0') << setw(3) << id_ << setfill(' ')<< endl;
cout << setw(15) << "NAME:" << firstName_ << " " << lastName_ << endl;
cout << setw(15) << "Address1:" << address_ << endl;
cout << setw(15) << "City:" << city_<< " " << endl;
cout << setw(15) << "State:" << state_<< " " << endl;
cout << setw(15) << "Zip:" << zip_<< " " << endl;
cout << setw(15) << "Date_Birth:" << dob_<< " " << endl;
cout << setw(15) << "Date_Death:" << dod_<< " " << endl;
cout << setw(15) << "Date_Wedding:" << dow_<< " " << endl;
cout << setw(15) << "Spouse:" << (spouse_ ? spouse_->GetFirstName() : "") << " " << (spouse_ ? spouse_-> GetLastName() : "") << endl;
for(unsigned int i = 0; i < children_.size(); i++)
{
cout << setw(15) << "Child: " << i << ": " << children_[i]->GetFirstName()<< " " << children_[i]->GetLastName()<< endl;
}
}
private:
std::string firstName_;
std::string lastName_;
std::string city_ ;
std::string state_ ;
std::string zip_ ;
std::string dob_ ;
std::string dow_;
std::string dod_;
std::string address_;
std::string spouseTempString;
std::vector<AddressNode*> children_;
AddressNode* spouse_;
unsigned int id_;
void AddressNode::AddChild(AddressNode& child)
{
vector<AddressNode*>::iterator iter;
if((iter = find(children_.begin(), children_.end(), &child)) != children_.end())
return;
children_.push_back(&child);
if (spouse_)
spouse_->AddChild(child);
}
public:
AddressNode(const std::string& firstName, const std::string& lastName, int id)
: children_(), id_(id)
{
firstName_= "";
firstName_+= firstName;
lastName_="";
lastName_+= lastName;
}
There's not enough code here to tell, but passing an object by reference and then storing its address is always fishy.
If a stack object gets passed to that function you'll get all kind of weird results.
Since your error only occur on pointer objects, I'm even more inclined to think you've got memory management issues somewhere.
If you really want to store a pointer, pass the pointer in the first place, or pass a const reference and store a copy?
finishing up a long project and the final step is to make sure my data lines up in the proper column. easy. Only I am having trouble with this and have been at it for longer than i wish to admit watching many videos and can't really grasp what the heck to do So here is a little snippet of the code that I'm having trouble with:
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
cout << "Student Grade Summary\n";
cout << "---------------------\n\n";
cout << "BIOLOGY CLASS\n\n";
cout << "Student Final Final Letter\n";
cout << "Name Exam Avg Grade\n";
cout << "----------------------------------------------------------------\n";
cout << "bill"<< " " << "joeyyyyyyy" << right << setw(23)
<< "89" << " " << "21.00" << " "
<< "43" << "\n";
cout << "Bob James" << right << setw(23)
<< "89" << " " << "21.00" << " "
<< "43" << "\n";
}
which works for the first entry but the bob james entry has the numbers all askew. I thought setw was supposed to allow you to ignore that? What am i missing?
Thanks
It doesn't work as you think. std::setw sets the width of the field only for the next insertion (i.e., it is not "sticky").
Try something like this instead:
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
cout << "Student Grade Summary\n";
cout << "---------------------\n\n";
cout << "BIOLOGY CLASS\n\n";
cout << left << setw(42) << "Student" // left is a sticky manipulator
<< setw(8) << "Final" << setw(6) << "Final"
<< "Letter" << "\n";
cout << setw(42) << "Name"
<< setw(8) << "Exam" << setw(6) << "Avg"
<< "Grade" << "\n";
cout << setw(62) << setfill('-') << "";
cout << setfill(' ') << "\n";
cout << setw(42) << "bill joeyyyyyyy"
<< setw(8) << "89" << setw(6) << "21.00"
<< "43" << "\n";
cout << setw(42) << "Bob James"
<< setw(8) << "89" << setw(6) << "21.00"
<< "43" << "\n";
}
Also related: What's the deal with setw()?
The manipulators << right << setw(23) are telling the ostream that you want
the string "89" set in the right-hand edge of a 23-character-wide field.
There is nothing to tell the ostream where you want that field to start,
however, except for the width of the strings that are output since the
last newline.
And << "bill"<< " " << "joeyyyyyyy" writes a lot more characters to the output
than << "Bob James" does, so the 23-character-wide field on the second line
starts quite a bit to the left of the same field on the first line.
Stream manipulators affect the next input/output value being streamed, and then some manipulators (including setw()) reset afterwards. So you need to set the width and alignment BEFORE you output a text string, not afterwards.
Try something more like this:
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
void outputStudent(const string &firstName, const string &lastName,
int finalExam, float finalAvg, int letterGrade)
{
cout << setw(40) << left << (firstName + " " + lastName) << " "
<< setw(6) << right << finalExam << " "
<< setw(6) << right << fixed << setprecision(2) << finalAvg << " "
<< setw(7) << right << letterGrade << "\n";
}
int main()
{
cout << "Student Grade Summary\n";
cout << "---------------------\n\n";
cout << "BIOLOGY CLASS\n\n";
cout << "Student Final Final Letter\n";
cout << "Name Exam Avg Grade\n";
cout << "--------------------------------------------------------------\n";
outputStudent("bill", "joeyyyyyyy", 89, 21.00, 43);
outputStudent("Bob", "James", 89, 21.00, 43);
cin.get();
return 0;
}
Output:
Student Grade Summary
---------------------
BIOLOGY CLASS
Student Final Final Letter
Name Exam Avg Grade
--------------------------------------------------------------
bill joeyyyyyyy 89 21.00 43
Bob James 89 21.00 43
The program works my only problem is that I don't know how to line up the output. When ran using the .txt file it prints the names, boxes, and name of cookies but not aligned. Also, I have to calculate the amount due for each person and display it, but i only can figure out how to do the total. Thanks for help
#include <iomanip>
#include <string>
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
ifstream inFile;
//Declare Variables
string firstName;
string cookieName;
int boxesSold;
int numCustomers = 0;
double amountDue;
int totalCustomers;
int totalBoxesSold = 0;
double totalAmount = 0;
cout << "Girl Scout Cookies" << endl;
cout << "Created By Aaron Roberts" << endl;
inFile.open("cookie.txt");
if(inFile)
{
cout << "Customer Number Cookie" << endl;
cout << "Name Of Boxes Name" << endl;
while(inFile >>firstName>>boxesSold>>cookieName)
{
totalBoxesSold += boxesSold;
totalAmount += boxesSold * 3.50;
cout << setprecision(2) << fixed << showpoint;
cout << setw(2) << firstName
<< right << setw(7) << boxesSold
<< setw(20) << cookieName
<< endl;
numCustomers += 1;
}
cout << "\nNumber of Customers: "<< numCustomers << endl;
cout << "Total Boxes Sold: " << totalBoxesSold << endl;
cout << "Total Amount: $" << totalAmount << endl;
inFile.close();
}
else
{
cout << "Could not open file " << endl;
}
system("pause");
return 0;
}
Given you've allocated 12 characters in the header for the "Customer Name" and "Number Of Boxes" columns, you probably want to allocate 11 characters for their data, leaving one character for a trailing space.
For clarity and maintainability, I recommend you create constants for these:
int const name_column_width = 11;
int const boxes_column_width = 11;
Then you can write:
std::cout << std::setw(name_column_width) << std::left << "Customer" << ' '
<< std::setw(boxes_column_width) << std::left << "Number" << ' '
<< "Cookie"
<< std:: endl;
std::cout << std::setw(name_column_width) << std::left << "Name" << ' '
<< std::setw(boxes_column_width) << std::left << "Of Boxes" << ' '
<< "Name"
<< std:: endl;
while (inFile >> firstName >> boxesSold >> cookieName)
{
totalBoxesSold += boxesSold;
totalAmount += boxesSold * 3.50;
std::cout << std::setw(name_column_width) << std::left << firstName << ' '
<< std::setw(boxes_column_width) << std::right << boxesSold << ' '
<< cookieName
<< std::endl;
++numCustomers;
}
Resizing these columns then becomes a simple matter of changing the constant.
This question already has answers here:
Restore the state of std::cout after manipulating it
(9 answers)
Closed 4 years ago.
I've got a line of code that sets the fill value to a '-' character in my output, but need to reset the setfill flag to its default whitespace character. How do I do that?
cout << setw(14) << " CHARGE/ROOM" << endl;
cout << setfill('-') << setw(11) << '-' << " " << setw(15) << '-' << " " << setw(11) << '-' << endl;
I thought this might work:
cout.unsetf(ios::manipulatorname) // Howerver I dont see a manipulator called setfill
Am I on the wrong track?
Have a look at the Boost.IO_State_Savers, providing RAII-style scope guards for the flags of an iostream.
Example:
#include <boost/io/ios_state.hpp>
{
boost::io::ios_all_saver guard(cout); // Saves current flags and format
cout << setw(14) << " CHARGE/ROOM" << endl;
cout << setfill('-') << setw(11) << '-' << " " << setw(15) << '-' << " " << setw(11) << '-' << endl;
// dtor of guard here restores flags and formats
}
More specialized guards (for only fill, or width, or precision, etc... are also in the library. See the docs for details.
You can use copyfmt to save cout's initial formatting. Once finished with formatted output you can use it again to restore the default settings (including fill character).
{
// save default formatting
ios init(NULL);
init.copyfmt(cout);
// change formatting...
cout << setfill('-') << setw(11) << '-' << " ";
cout << setw(15) << '-' << " ";
cout << setw(11) << '-' << endl;
// restore default formatting
cout.copyfmt(init);
}
You can use the ios::fill() function to set and restore the fill character instead.
http://www.cplusplus.com/reference/iostream/ios/fill/
#include <iostream>
using namespace std;
int main () {
char prev;
cout.width (10);
cout << 40 << endl;
prev = cout.fill ('x');
cout.width (10);
cout << 40 << endl;
cout.fill(prev);
return 0;
}
You can manually change the setfill flag to whatever you need it to be:
float number = 4.5;
cout << setfill('-');
cout << setw(11) << number << endl; // --------4.5
cout << setfill(' ');
cout << setw(11) << number << endl; // 4.5
The null character will reset it back to the original state:
setfill('\0')