Bob Joe
Bob Joe

Reputation: 3

How to output a '$' character in front of my number with setw

#include <iostream>
#include <iomanip>
using std::cout;
using std::fixed;
using std::showpoint;
using std::setprecision;
int main()
{
  double number = 85495.5432334;
  cout << fixed << showpoint << setprecision(2) << setw(15) << 
    "string" << setw(15) << "$" << number;
  return 0;
}

The above code outputs the $ as right justified in 15 characters, but it does not right justify the number. How do I print out the '$' character and the following number together as one item that is right justified in 15 characters without losing my showpoint/setprecision/fixed manipulations?

I tried using "$"+number.toString(), and this makes the result right justified, but this ruins the showpoint/fixed/setprecision(2) manipulations I want. How do I get it all together?

Upvotes: 0

Views: 87

Answers (2)

sweenish
sweenish

Reputation: 5202

Your issue that std::setw() only applies the width to the next thing placed in the stream. You only place the $ after your call to std::setw(), hence it is what's right justified. You need to create the representation of money ahead of time, and place that in the stream.

You simply can't put it all together and have your std::setw() cake, too.

One way of creating the money representation all at once is std::put_money().

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

int main() {
  // Treated as a number of pennies!
  double number = 85495.5432334 * 100.0;

  std::cout.imbue(std::locale("en_US.UTF-8"));
  std::cout << std::setw(15) << std::setfill('.') << std::showbase
            << std::put_money(number) << '\n';
}

Output:

.....$85,495.54

It is important to set your locale according to the type of currency you want to print.

Locales are nice because you just need to know the locale.

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

int main() {
  // Treated as a number of pennies!
  double number = 85495.5432334 * 100.0;

  std::cout.imbue(std::locale("en_US.UTF-8"));
  std::cout << std::setw(15) << std::setfill('.') << std::showbase
            << std::put_money(number) << '\n';

  std::cout.imbue(std::locale("fr_FR.UTF-8"));
  std::cout << std::setw(15) << std::setfill('.') << std::showbase
            << std::put_money(number) << '\n';
}

Output:

.....$85,495.54
..85 495,54 €

Upvotes: 3

D&#250;thomhas
D&#250;thomhas

Reputation: 10083

If your number is left aligned, just put the dollar sign first.

std::cout 
    << '$' // (the dollar sign is separate from the number)
    << std::left << std::fixed << std::setw(15) << std::setprecision(2) << number;
    << "\n";

If you wish to right-align your output, and you wish the dollar-sign to stick to your number, you have to build a temporary string. This looks a lot like before:

// build the temporary string with both the dollar sign and the number
std::ostringstream dollars;
dollars << '$' << std::fixed << std::left << std::setprecision(2) << number;

// print out the justified temporary string
std::cout << std::setw(16) << std::right << dollars.str() << "\n";

Here they are together so you can play with it:

#include <iomanip>
#include <iostream>
#include <sstream>

int main()
{
    double number = 1235495.5432334;
    
    // Left-justified
    std::cout << '[';
    {
        std::cout 
            << '$' 
            << std::left << std::fixed << std::setw(15) << std::setprecision(2) << number;
    }
    std::cout << "]\n";

    // Right-justified number field only
    std::cout << '[';
    {
        std::cout 
            << '$' 
            << std::right << std::fixed << std::setw(15) << std::setprecision(2) << number;
    }
    std::cout << "]\n";
    
    // Both right-justified
    std::cout << '[';
    {
        std::ostringstream dollars;
        dollars << '$' << std::fixed << std::left << std::setprecision(2) << number;

        std::cout << std::setw(16) << std::right << dollars.str();
    }
    std::cout << "]\n";
}
[$1235495.54     ]
[$     1235495.54]
[     $1235495.54]

Remember, many field formatting constraints (such as width) apply only to a single item being output. Building a temporary string is required when messing with specific field sizes.

Upvotes: 3

Related Questions