Having trouble with iomanip, columns not lining up the way I expect - c++

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

Related

Basic C++ Application has extra output then it should

So I'm writing a basic application and for some reason when I run the program a bunch of numbers pop up before my intended output. It was working fine until I added the "std::cout" lines to have the outputs only be 2 decimals. The general gist of the application is a program acts as a self-checkout register at a store and lets the user buy 2 items. And yes I know the code probably looks really bad, I'm still super new to C++.
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
float price1;
float number1;
float price2;
float number2;
float priceofitemplustax1;
float priceofitemplustax2;
float total;
std::cout << std::fixed;
std::cout << std::setprecision(2);
std::cout << price1;
std::cout << price2;
std::cout << priceofitemplustax1;
std::cout << priceofitemplustax2;
std::cout << total;
cout << endl << "Please scan your first item." <<endl;
cin.get();
cout << endl << "How many of that item are you buying? "<<endl;
cin >> number1;
cout << endl << "How much is that item?"<<endl;
cin >> price1;
priceofitemplustax1 = (number1 * price1) * 1.0875;
cout << endl << "So you want " << number1 << " of this item? Adding tax that will be " << priceofitemplustax1 << "."<<endl;
cin.get();
cout << endl << "Please scan your second item."<<endl;
cin.get();
cout << endl << "How many of that item are you buying? "<<endl;
cin >> number2;
cout << endl << "How much is that item?"<<endl;
cin >> price2;
priceofitemplustax2 = (number2 * price2) * 1.0875;
cout << endl << "So you want " << number2 << " of this item? Adding tax that will be " << priceofitemplustax2 << "."<<endl;
cin.get();
total = priceofitemplustax1 + priceofitemplustax2;
cout << endl << "So your final total for this shopping trip including tax is " << total << "."<<endl;
cin.get();
cout << endl << "Your reciept will print below."<<endl;
cin.get();
cout << setw(14) << right << "Number of Item" << setw(10) << right << "Price" << setw(20) << "Price plus tax" << endl;
cout << setw(14) << right << number1 << setw(10) << right << price1 << setw(20) << priceofitemplustax1 << endl;
cout << setw(14) << right << number2 << setw(10) << right << price2 << setw(20) << priceofitemplustax2 << endl;
cout << endl;
cout << endl;
cout << setw(8) << right << "Total is" << setw(10) << total << price2 << endl;
cin.get();
}
std::cout << std::setprecision(2);
std::cout << price1;
std::cout << price2;
std::cout << priceofitemplustax1;
std::cout << priceofitemplustax2; std::cout << total;
here you write 5 floats
The lines
std::cout << std::fixed; // sets a format
std::cout << std::setprecision(2); // sets a format
set the streams output format.
The lines
std::cout << price1; // outputs a number
std::cout << price2; // outputs a number
std::cout << priceofitemplustax1; // outputs a number
std::cout << priceofitemplustax2; // outputs a number
std::cout << total; // outputs a number
print the variables to the stream.
Just remove the variable output lines. Do not accept this answer - Credit goes to manni66

Can someone tell me why my string is blank after passing the argument?

I cannot seem to get the "full"
to display the concatenation of First and last.
It compiles but when I run it it will appear blank.
Can you tell me why?
Have tried to figure it our for hours.
Here are my declerations
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
#define tax 0.30
#define parking_deductions 10.00
#define overtime_hours 40
#define max_hours 60
#define max_pay 99
string namestring( string first, string last, string full);
I'm attempting to pass this module to my main
string namestring(string first, string last, string full)
{
//input name
cout << "What is your first name? " << endl;
cout << "first name: " << endl;
cin >> first;
cout << "What is your last name? " << endl;
cout << "last name: " << endl;
cin >> last;
//process name
full = last + " " + first;
return full;
}
By calling it like so
namestring(first, last, full );
Where I expect the full name input by the user to be displayed below
cout << left << fixed << " " << "Reg." << " " << " Ovt." << " Hourly" << " Net" << " " << " Gross" << endl;
cout << left << fixed << setprecision(2) << setw(10) << "Name " << " Hours" << " Hours" << " Rate" << " Pay" << " Taxes" << " Deduct" << " Pay" << endl;
cout << left << fixed << setprecision(2) << setw(10) << "====================" << " " << "=====" << " " << "=====" << " " << "=====" << " " << "======" << " " << "======" << " " << " " << "========" << " " << "=======" << endl;
cout << left << setprecision(2) << setw(20) << full << right << " " << right << setw(4) << hours << right << " " << right << overtime << " " << right << pay << " " << right << net_pay << " " << right << taxs << " " << right << parking_deductions << " " << right << gross_pay << right << endl;
cout << endl;
cout << endl;
I'm assuming the goal here is to get the following 3 strings,
First Name
Last Name
Full Name
To do this, you would need to pass the arguments by reference, not by value:
void namestring(string& first, string& last, string& full)
{
//input name
cout << "What is your first name? " << endl;
cout << "first name: " << endl;
cin >> first;
cout << "What is your last name? " << endl;
cout << "last name: " << endl;
cin >> last;
//process name
full = last + " " + first;;
}
There is also no need to return a string if you pass the "full" string by reference, since the function will fill it for you.
string namestring(string first, string last, string& full)
//input name
{
cout << "What is your first name? " << endl;
cout << "first name: " << endl;
cin >> first;
cout << "What is your last name? " << endl;
cout << "last name: " << endl;
cin >> last;
//process name
full = last + " " + first;
return full;
}
You are passing the full by value. So it's the local copy of the function which is modified. You need it to pass by reference.
If you also want the first and last value you also need to pass it by reference.

C++ Iomanip lib setfill and setw issues

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
}

How to use setw and setfill together in C++ to pad with blanks AND chars?

I need to write a program for a homework assignment to calculate tuition costs and the output should be formatted like so with the dot padding and space padding after the dollar sign:
Student Name: Name goes here
Address: Address goes here
Number of credits: .......... 5
Cost per credit hour: ............ $ 50
My code so far is:
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
using namespace std;
double const REG_FEE = 700, STUDENT_ASSEMBLY_FEE = 7.19, LEGAL_FEE = 8.50, STUDGOV_FEE = 1.50,
LATE_FEE_PERCENTAGE = 0.015;
int main()
{ double num_credits, cost_per_credit, tuition_total, late_charge, amount_due;
string student_name;
string student_address;
string student_city_state_ZIP;
ifstream info;
info.open ("info.txt");
getline (info, student_name);
getline (info, student_address);
getline (info, student_city_state_ZIP);
info >> num_credits;
info >> cost_per_credit;
tuition_total = num_credits * cost_per_credit + REG_FEE + STUDENT_ASSEMBLY_FEE + LEGAL_FEE
+ STUDGOV_FEE;
late_charge = tuition_total * LATE_FEE_PERCENTAGE;
amount_due = tuition_total + late_charge;
cout << "Tuition and Billing Program by Neal P." << endl
<< setw(18) << "Student Name:" << student_name << endl
<< setw(18) << "Address:" << student_address << endl
<< left << setfill('.') << endl
<< setfill(18) << "Number of Credits:" << setw(5) << "$" << num_credits << endl
<< setfill(18) << "Cost per Credit Hour:" << setw(5) << "$" << cost_per_credit << endl
<< setfill(18) << "Tuition Cost:" << setw(5) << "$" << tuition_total << endl
<< setfill(18) << "Registration Fee:" << setw(5) << "$" << REG_FEE << endl
<< setfill(18) << "MSA Fee:" << setw(5) << "$" << STUDENT_ASSEMBLY_FEE << endl
<< setfill(18) << "Legal Services Fee:" << setw(5) << "$" << LEGAL_FEE << endl
<< setfill(18) << "Student Government Fee:" << setw(5) << "$" << STUDGOV_FEE << endl;
return 0;
}
When I compile I get a very long error, something like : "In function ‘int main()’:
/Users/nealp/Desktop/machine problem 2.cpp:41: error: no match for ‘operator<<’ in ‘((std::basic_ostream >*)std::operator<< [with _CharT = char, _Traits = std::char_traits](((std::basic_ostream >&)((std::basic_ostream >*)((std::basic_ostream >*)((std::basic_ostream >*)std::operator<<" that continues.
Is this an issue with my use of both setw and setfill together? I know that setfill only has to be declared once and setw is only effective on the next line output, but I defined setfill each time because I was using setw before it.
std::setfill is a function template and it's template argument gets deduced based on the type of the argument you pass it to. It's return type is unspecified - it's some implementation defined proxy type that sets fill character on the stream object and enables further chaining of operator<< calls. It's also dependent on the type that setfill gets instantiated with.
The type of literal 18 is int so setfill returns some unrelated type for which there's no operator<< avaliable.
I'm not sure what you meant with setfill(18), I'm guessing you've mistaken it for setw(18).
Just replace setfill(18) in your code, that is the reason for compilation error.
Here is the improved printing portion to fit the requirements,
cout << "Tuition and Billing Program by Neal P." << endl
<< "Student Name:" << student_name << endl
<< "Address:" << student_address << endl
<<endl<<endl<< "Number of Credits:" << setfill('.') << setw(5) <<"$" << num_credits
<< endl<< "Cost per Credit Hour:"<<setfill('.')<<setw(5)<< "$" << cost_per_credit <<
endl<< "Tuition Cost:" << setfill('.')<<setw(5)<< "$" << tuition_total << endl
<< "Registration Fee:" << setfill('.')<<setw(5) << "$" << REG_FEE << endl
<< "MSA Fee:" << setfill('.')<<setw(5) << "$" << STUDENT_ASSEMBLY_FEE << endl
<< "Legal Services Fee:" << setfill('.')<<setw(5) << "$" << LEGAL_FEE << endl
<< "Student Government Fee:" << setfill('.')<<setw(5) << "$" << STUDGOV_FEE << endl;

C++ setw moving whole line not just the needed part

I am trying to use setw to clean up the output of my program. I want the empty spaces in between "total number of spools to be ordered" and the output.
EDIT this is what im going for:
and this is what I get
here is what I have so far:
UPDATED CODE
/********************************************/
// Name: results /
// Description: Print results /
// Parameters: N/A /
// Reture Value: N/A /
/********************************************/
void results(int spoolnumber, int subtotalspool, float shippingcost, float totalcost)
{
cout << left << setw (45) << "Total number of spools to be ordered is: " << right << spoolnumber << endl << endl;
cout << left << setw (45) << "The subtotal for the spools is:" << right << "$" << subtotalspool << endl << endl;
cout << "The shipping cost is: $" << shippingcost << endl << endl;
cout << "The total cost is: $" << totalcost << endl << endl;
return;
}
You can also do
cout << left << setw (45) << "Total number of spools to be ordered is: " << spoolnumber << endl << endl;
to choose which side the padding goes. The default is left.
EDIT: using stringstream
stringstream ss;
ss << "$" << spoolnumber
I think you can fix the right end by adding another setw. So:
cout << left << setw (45) << "Total number of spools to be ordered is: " << right << setw(5) << ss.str() << endl << endl;