Specific Placement of Output

Hi folks. I am looking for a way to control precisely where the output of a cout statement appears, and setw just isn't doing it for me. Here's the synopsis of the program:

It's a payroll program (fairly popular in C++ courses so the searches tell me) that calculates the numbers for various employees given pay, hours worked, hourly wage, etc, and then outputs it. I have all of that working fine and dandy.. save for the fact the output is ugly something harsh.

Employee              Hourly     Hours       Tax     Gross      Net
Name                  Rate       Worked      Rate    Amount     Amount
John Smith            10.45      40.00      15.00    418.00    390.13

Jane Doe            12.50      45.00      15.00    656.25    612.50

Harry Morgan            20.00      40.00      20.00    800.00    760.00

Carmen Martinez            25.00      35.00      25.00    875.00    840.00

Jacintha Washington            50.85      60.00      35.00   4576.50   4445.74


            50.85      60.00      35.00   4576.50   4445.74
Total gross amount: 11902.25
Total net amount: 11494.12


As you can see, works fine and dandy for the first line of output, but from there it's a really ugly snowball effect because of the name lengths and varying output and such.

If you'd like a quick laugh, here's what I've been working with so far:

1
2
3
4
5
6
cout << employeeName;
	cout << setprecision(2) << fixed << showpoint << setw(17) << hourlyRate;
	cout << setprecision(2) << fixed << showpoint << setw(11) << hoursWorked;
	cout << setprecision(2) << fixed << showpoint << setw(11) << taxRate;
	cout << setprecision(2) << fixed << showpoint << setw(10) << grossAmount;
	cout << setprecision(2) << fixed << showpoint << setw(10) << netAmount << endl;


Square wheel, amirite? I just know there's a way to do what I am looking for, to clean up that nasty output and put all the results right beneath the header at the top of the column, but all of my searching has yielded not, so here I am. Advice?

Any help would be appreciated!
- Ghostwish
I can suggest you a very simple way to do it-use " "; and compile to see the output.I think it will take you about 10 minutes to fix it :)
Uhm.. that is what the setw function does. It puts out however many whitespaces you tell it to. Sorry, but that is not what I am looking for.
try to make a little algorithm where you subtract the number of letters in their name from the number of spaces. you can use the strlen function from cstring to do this like so:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <cstring>
#include <iomanip>
using std::setw;
using std::endl;
using std::cout;

int main(void)
{
	char name1[] = "John James";
	char name2[] = "Jeff John";
	char name3[] = "Hello, World!";
	int len1 = strlen(name1);
	int len2 = strlen(name2);
	int len3 = strlen(name3);

	cout << "Name: " << setw(31) << "Random Characters" << endl;
	cout << name1 << setw(30 - len1) << "asdifjiafg" << endl;
	cout << name2 << setw(30 - len2) << "asdfgiadfg" << endl;
	cout << name3 << setw(30 - len3) << "asdigfgafh" << endl;

	return 0;
}


like this the random letters all start at the same spot
Last edited on
Wow!! Great idea! I've never seen this strlen function before, so I gave it a shot. I implemented it as such:

int length = strlen(employeeName);

However, it gave me this error:

c:\users\user\documents\visual studio 2008\projects\lab07\payroll2.cpp(112) : error C2664: 'strlen' : cannot convert parameter 1 from 'std::string' to 'const char *'


Now what did I go and do wrong? I do note that inside of your namespace statements, I just use using namespace std;. I did add in the cstring header file. Everything else is as it is.

And thanks a ton for the suggestion. ;)
strlen() is for c-strings. As you are using (the superior) std::strings, you can just use thestring.length() instead.
Ah ha! That got rid of the error! Thanks! Now let me fiddle with this and see if I can make it work better. :>

Edit - Okay, it's working! Sort of.. Something funky strange is going on, and it's got me scratching my head. Have a look at the (ugly) output:

This payroll program calculates individual employee pay and company totals using
 data from a data file payroll.txt.

A payroll report showing payroll information is displayed.

Employee              Hourly     Hours       Tax     Gross      Net
Name                  Rate       Worked      Rate    Amount     Amount
John Smith            10.45      40.00       15.00   418.00     390.13

Jane Doe             12.50       45.00        15.00    656.25      612.50

Harry Morgan         20.00   40.00    20.00800.00  760.00

Carmen Martinez      25.0035.00 25.00875.00840.00

Jacintha Washington  50.8560.0035.004576.504445.74


                  50.85            60.00             35.00        4576.50
   4445.74
Total gross amount: 11902.25
Total net amount: 11494.12
Press any key to continue . . .


Here's the culprit code:
1
2
3
4
5
6
7
8
9
void displayEmployeeInfo(string employeeName, double hourlyRate, double hoursWorked, double taxRate, double grossAmount, double netAmount)
{
	int length = employeeName.length();
	cout << employeeName;
	cout << setprecision(2) << fixed << showpoint << setw(27-length) << hourlyRate;
	cout << setprecision(2) << fixed << showpoint << setw(21-length) << hoursWorked;
	cout << setprecision(2) << fixed << showpoint << setw(22-length) << taxRate;
	cout << setprecision(2) << fixed << showpoint << setw(19-length) << grossAmount;
	cout << setprecision(2) << fixed << showpoint << setw(21-length) << netAmount << endl;
Last edited on
I don't think you would need different spacing anywhere except for the name.

So just output the name, then however many spaces you need so it lines up, then all the numbers. All of the numbers only need to care about the length to the next number, so you wouldn't need the length of the name there.
yeah just use a consistent number. just use 30-length for all of them. also to answer your question about my namespace std things it doesnt actually change the output, you just have to say exactly what youre using and nothing youre not. it sorta defeats the purpose of a namespace if you just say using namespace std; amirite?
Last edited on
Wow, thanks so much for all the help. That cleared it up quite a bit. The output is nearly perfect, save for a few small imperfections, but let's get one thing out of the way at a time.

Now, this code:
1
2
3
4
5
6
7
	int length = employeeName.length();
	cout << employeeName;
	cout << setprecision(2) << fixed << showpoint << setw(27-length) << hourlyRate;
	cout << setprecision(2) << fixed << showpoint << setw(11) << hoursWorked;
	cout << setprecision(2) << fixed << showpoint << setw(12) << taxRate;
	cout << setprecision(2) << fixed << showpoint << setw(9) << grossAmount;
	cout << setprecision(2) << fixed << showpoint << setw(11) << netAmount;

Produces this output:

This payroll program calculates individual employee pay and company totals using
 data from a data file payroll.txt.

A payroll report showing payroll information is displayed.

Employee              Hourly     Hours       Tax     Gross      Net
Name                  Rate       Worked      Rate    Amount     Amount
John Smith            10.45      40.00       15.00   418.00     390.13
Jane Doe             12.50      45.00       15.00   656.25     612.50
Harry Morgan         20.00      40.00       20.00   800.00     760.00
Carmen Martinez      25.00      35.00       25.00   875.00     840.00
Jacintha Washington  50.85      60.00       35.00  4576.50    4445.74

                  50.85      60.00       35.00  4576.50    4445.74Total gross am
ount: 11902.25
Total net amount: 11494.12
Press any key to continue . . .

Notice how after the first output, everything is off by 1? I'm scratching my head at what is causing that.. Any ideas?
I suggest using "\t" .
just add an extra space before each one xD
Last edited on
Mohamed - Sorry, but a tab is not quite what I'm looking for here. ;)

ascii - I only wish it could be that simple! But, as this is party of a looping reading from file program, that just wouldn't work. Blast. :P
You are basing length on the employee name string only but should be updating the length for every element you are outputting.

Also have a whitespace size for every element in the output and convert your doubles into strings before you output. You can use stringstream to do this.

Something like this:
1
2
3
4
5
6
7
8
9
        int fixedName = 30, fixedHrate = fixedHworked = fixedTrate = fixedGamount = 10;
        
	cout << employeeName;
	cout << setw(fixedName - employeeName.length()) << hourlyRate;
	cout << setw(fixedHrate - hourlyRate.length()) << hoursWorked;
	cout << setw(fixedHworked - hoursWorked.length()) << taxRate;
	cout << setw(fixedTrate - taxRate.length()) << grossAmount;
	cout << setw(fixedGamount - grossAmount.length()) << netAmount << endl;
Last edited on
Unfortunately, iostream formatting is a nightmare.

That's why I often use printf (carefully) for formatting or if I need even more control, ncurses.

Of course most C++ advocates tell you to use iostream - choose your poison.
Topic archived. No new replies allowed.