Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making a table with printf in c++

I'm trying to make a table like this.... (Just without the dots I used to separate the each item)

Weekly Payroll:

Name.....................Title.......Gross......Tax......Net

Ebenezer Scrooge Partner 250.00 ..62.25 .187.75

Bob Cratchit ..........Clerk ......15.00 ....2.00 ..13.00

This is what my code looks like for this part....

for (int count=0; count < numberOfEmployees; count++)
{
    cout << "Employee: \n";
    cout << "\t Name: ";
    cin.getline (employees[count].name, EMPLOYEESIZE); 

    cout << "\t Title: ";
    cin.getline (employees[count].title, EMPLOYEESIZE);

    cout << "\t SSNum: ";
    cin >> employees[count].SSNum;

    cout << "\t Salary: ";
    cin >> employees[count].Salary;

    cout << "\t Withholding Exemptions: ";
    cin >> employees[count].Withholding_Exemptions; 
    cin.ignore();

    cout << "\n";
}


double gross;
double tax;
double net;
double adjusted_income;

cout << "\n";

cout << "Weekly Payroll: \nName \t \t Title \t Gross \t Tax \t Net \n";


for (int count=0; count < numberOfEmployees; count++)
{
    gross = employees[count].Salary;
    adjusted_income = subtraction_times (employees[count].Salary, employees[count].Withholding_Exemptions);
    tax = adjusted_income * .25;
    net = subtraction (gross, tax);

    printf ("\n%s", employees[count].name); 
}

I have the first part of the table(the name part), but after that I dont know now to do the rest of the table. Can anyone help me?

Thanks

like image 870
Gvegas222 Avatar asked Feb 09 '12 07:02

Gvegas222


3 Answers

You can use printf with left-justify flag (-).

printf("%-10s", "title"); // this will left-align "title" in space of 10 characters

Here is a sample program:

#include <string>
using namespace std;

int main()
{
    string name = "Bob Cratchit";
    string title = "Clerk";
    float gross = 15;
    float tax = 2;
    float net = 13;

    printf("%-25s%-20s%-10s%-10s%-10s\n", "Name", "Title", "Gross", "Tax", "Net"); 
    printf("%-25s%-20s%-10.2f%-10.2f%-10.2f\n", name.c_str(), title.c_str(), gross, tax, net); 
    return 0;
}

Output:

Name                     Title               Gross     Tax       Net
Bob Cratchit             Clerk               15.00     2.00      13.00
like image 83
B Faley Avatar answered Sep 25 '22 21:09

B Faley


The most obvious question is: why use printf, when other tools are more adapt? Another question, often forgotten, is what is the (final) output medium? If the text is going to end up on a printer or in a text box in a windowing system, you may have your work cut out for you. The fonts on such systems are rarely fixed width, so you'll have to take into account the width of the individual characters. For output to a printer, I would suggest outputting LaTeX and then postprocessing it. For outputting to a window, the library you're using probably has some sort of table component which will do the formatting for you.

If you're outputing to some fixed width font device—a teletyp, for example, then you can either use iostream manipulators or user defined types. (There's no way to do this cleanly with printf—you need iostreams.) Abstractly speaking, defining types like Name, Title and MonitaryAmount is the cleanest solution. In which case, you just define an appropriate << operator for the type. Using a user defined type for name and title, instead of just std::string, may be overkill, however, and the manipulator approach may be preferred. (In a very large application, where the separate types would be justified, you're likely to need output in different contexts, and want manipulators to specify them as well.)

In the simplest solution, you could get by with just two manipulators: TextField and MoneyField: each manipulator would take the field width as an argument to the constructor, and set the appropriate format fields in its << operator, e.g.:

class TextField
{
    int myWidth;
public:
    TextField( int width ) : myWidth( width ) {}
    friend std::ostream&
    operator<<( std::ostream& dest, TextField const& manip )
    {
        dest.setf( std::ios_base::left, std::ios_base::adjustfield );
        dest.fill( ' ' );
        dest.width( manip.myWidth );
        return dest;
    }
};

and

class MoneyField
{
    int myWidth;
public:
    MoneyField( int width ) : myWidth( width ) {}
    friend std::ostream&
    operator<<( std::ostream& dest, MoneyField const& manip )
    {
        dest.setf( std::ios_base::right, std::ios_base::adjustfield );
        dest.setf( std::ios_base::fixed, std::ios_base::floatfield );
        dest.fill( ' ' );
        dest.precision( 2 );
        dest.width( manip.myWidth );
        return dest;
    }
};

(Practically speaking, it's probably better to use a class for Money. You'll want special rounding rules for multiplication, for example; if you're calculating tax, in fact, you'll probably need to use some sort of decimal type, rather than double, in order to meet legal requirements as to how it is calculated.)

Anyway, given the above manipulators, you can write something like:

TextField  name( 15 );
TextField  title( 8 );
MoneyField gross( 8 );
MoneyField tax( 6 );
MoneyField net( 8 );
for ( std::vector< Employee >::const_iterator employee = employees.begin();
        employee != employees.end();
        ++ employee ) {
    std::cout << name  << employee->name()
              << title << employee->title()
              << gross << employee->salary()
              << tax   << calculateTax( employee->salary() )
              << net   << calculateNet( employee->salary() )
              << std::endl;
}

(This assumes that you've cleaned up the rest to make it idiomatic and maintainable C++ as well.)

like image 37
James Kanze Avatar answered Sep 23 '22 21:09

James Kanze


Instead of using tabs to position at specific columns, use standard stream I/O manipulators. To be more specific, check out std::setw and std::left.

Something like this:

std::cout << std::left << std::setw(25) << "Name" << std::setw(12) << "Title"
          << std::setw(11) << "Gross" << std::setw(9) << "Tax" << "Net\n";
like image 21
Some programmer dude Avatar answered Sep 23 '22 21:09

Some programmer dude