C++ cout decimal alignment

YelizavetaYR picture YelizavetaYR · Sep 19, 2014 · Viewed 12.3k times · Source

I'm having a hard time aligning decimal values. I am pretty sure its a combination of right alignment and setprecision/fixed but it doesn't seem to be working. I know other questions have been asked on the topic but I haven't found a clear solution to getting a bunch of columns (unique cout statements to align).

This is a chunk of my code:

double total_collect, sales, country_tax, state_tax, total_tax;
const double STATE_TAX_RATE = 0.04, COUNTRY_TAX_RATE = 0.02; 

// Compute taxes
total_collect = 100;
sales = 100 / 1.06 ;
country_tax = sales * COUNTRY_TAX_RATE;
state_tax = sales * STATE_TAX_RATE;
total_tax = country_tax + state_tax;

//Display

cout << setiosflags(std::ios::right) ;

cout << "Totla Collected: " << setw(7) << "$ " << fixed << setprecision(2) << right << total_collect << endl;
cout << "Sales: " << setw(17) << "$ "  << fixed << setprecision(2) << right << sales  << endl;
cout << "Country Sales Tax: " << setw(5) << "$ " << fixed << setprecision(2) << right << country_tax  << endl;
cout << "State Sales Tax: " << setw(7) << "$ "  << fixed << setprecision(2) << right << state_tax << endl;
cout << "Total Sales Tax: " << setw(7) << "$ " << fixed << setprecision(2) << left  << total_tax << endl << endl; 

This is what it looks like:
enter image description here

This is what I would like it too like:
enter image description here

Answer

Fred Larson picture Fred Larson · Sep 19, 2014

You're setting the width on the "$", which aligns them nicely. But you also need to set it for the values themselves. I added a setw(8) before each fixed and that aligned them nicely, except for the last one which has a left instead of a right. You might want a different width value, but it should be the same for each line.

The ideal solution would be to use std::put_money (I see by your comment that you can't, but perhaps this will help someone else reading this answer). I've increased the dollar amounts to illustrate the thousands separator and fixed a bug or two:

#include <locale>
#include <iostream>
#include <iomanip>

int main()
{
    double total_collect, sales, country_tax, state_tax, total_tax;
    const double STATE_TAX_RATE = 0.04, COUNTRY_TAX_RATE = 0.02;
    const auto TAX_WIDTH = 10;
    const auto LABEL_WIDTH = 19;

    // Compute taxes
    total_collect = 10000;
    sales = total_collect / 1.06 ;
    country_tax = sales * COUNTRY_TAX_RATE;
    state_tax = sales * STATE_TAX_RATE;
    total_tax = country_tax + state_tax;

    //Display
    std::cout.imbue(std::locale("en_US.utf8"));
    std::cout << std::setw(LABEL_WIDTH) << std::left << "Total Collected: "
        << std::setw(TAX_WIDTH) << std::right << std::showbase
        << std::put_money(total_collect * 100.0) << std::endl;
    std::cout << std::setw(LABEL_WIDTH) << std::left << "Sales: "
        << std::setw(TAX_WIDTH) << std::right << std::showbase
        << std::put_money(sales * 100.0) << std::endl;
    std::cout << std::setw(LABEL_WIDTH) << std::left << "Country Sales Tax: "
        << std::setw(TAX_WIDTH) << std::right << std::showbase
        << std::put_money(country_tax * 100.0) << std::endl;
    std::cout << std::setw(LABEL_WIDTH) << std::left << "State Sales Tax: "
        << std::setw(TAX_WIDTH) << std::right << std::showbase
        << std::put_money(state_tax * 100.0) << std::endl;
    std::cout << std::setw(LABEL_WIDTH) << std::left << "Total Sales Tax: "
        << std::setw(TAX_WIDTH) << std::right << std::showbase
        << std::put_money(total_tax * 100.0) << std::endl << std::endl;
}

I get this output:

Total Collected:   $10,000.00
Sales:              $9,433.96
Country Sales Tax:    $188.68
State Sales Tax:      $377.36
Total Sales Tax:      $566.04