About the Program

I have a program that displays a menu. The menu contains both an array of items (strings), and prices (double type values). The program serves no further purpose but to display a menu.

The Problem

Of course, by default the double type values are displayed with decimals. This is useful in this case because we are listing the prices of items; however, usually prices initially begin with a dollar sign ($). To my knowledge, the iomanip header contains the "put_money" & "put_money" functions, but these do not do what I need them to do. What I need is for each price within to menu to be displayed with a dollar sign alongside the actual value. For example:

My desired output is this:

Please select an item to purchase:

______________________________________________________

 Item:   Prices:   Item:   Prices:   Item:   Prices:
______________________________________________________

 Water     $100     Milk      $200    Juice     $300
  Wine     $400    Bread      $500    Apple     $600
  Tuna     $700    Steak      $800  Bandage     $900
Med-Kit   $1000    Splint    $1100   Thread    $1200

My current program produces this:

Please select an item to purchase:

______________________________________________________

 Item:   Prices:   Item:   Prices:   Item:   Prices:
______________________________________________________

 Water      100     Milk       200    Juice      300
  Wine      400    Bread       500    Apple      600
  Tuna      700    Steak       800  Bandage      900
Med-Kit    1000    Splint     1100   Thread     1200

Is there a more efficient way to add the dollar sign to all my values without having to manually add each individual dollar sign? I just felt manually adding them could be tedious in a large project (certainly not like this, but possibly similar).

My Code

#include <iostream>
#include <iomanip>
#include <string>

int main(void) {


unsigned short int width = 10;
unsigned short int prec = 6;

float prices[12] = {100.00, 200.00, 300.00, 400.00, 500.00, 600.00, 700.00, 800.00, 900.00, 1000.00, 1100.00, 1200.00};

std::string items[12] = {"Water", "Milk", "Juice", "Wine", "Bread", "Apple", "Tuna", "Steak", "Bandage", "Med-Kit", "Splint","Thread"};

std::cout << "\nPlease select an item to purchase:\n\n";

std::cout << "_________________________________________________________________\n\n";

std::cout << std::setw(width) << "Item:" << std::setw(width) << "Prices:" <<std::setw(width) << "Item:" <<std::setw(width) << "Prices;" <<std::setw(width) << "Item:" <<std::setw(width) << "Prices:" << "\n";

std::cout << "_________________________________________________________________\n\n";

std::cout << std::setw(width) <<items[0] <<std::setw(width) << prices[0] <<std::setw(width) << items[1] <<std::setw(width) << prices[1] <<std::setw(width) << items[2] <<std::setw(width) << prices[2] << "\n";
std::cout << std::setw(width) <<items[3] <<std::setw(width) << prices[3] <<std::setw(width) << items[4] <<std::setw(width) << prices[4] <<std::setw(width) << items[5] <<std::setw(width) << prices[5] << "\n";
std::cout << std::setw(width) <<items[6] <<std::setw(width) << prices[6] <<std::setw(width) << items[7] <<std::setw(width) << prices[7] <<std::setw(width) << items[8] <<std::setw(width) << prices[8] << "\n";
std::cout << std::setw(width) <<items[9] <<std::setw(width) << prices[9] <<std::setw(width) << items[10] <<std::setw(width) << prices[10] <<std::setw(width) << items[11] <<std::setw(width) << prices[11] << "\n";

std::cin.get();
std::cin.get();

return 0;



}

Please excuse the excessive length of the code. Thanks to everyone in advance for helping.

有帮助吗?

解决方案

Why don't you create a class to store the items? For example, you can have:

class Item
{
    private:
    double price;
    string item;

    public:
    void display()
    {
        cout << "$" << price;
    }
};

So you call the display function to display the price in monetary value.

其他提示

Actually std::put_money can and will do exactly what you're asking if you use it correctly.

There are two parts to that. First of all, you have to select a locale. The default "C" locale simply doesn't define a currency symbol to use. Typically you'll want to use the nameless locale, something like this:

std::cout.imbue(std::locale(""));

This chooses (and uses) the locale for which the user has configured their environment, so (for example) a typical US user will get some US English locale with a dollar sign as the currency symbol, but a typical German user will get a German locale with a euro sign as the currency symbol1. This will also affect the formatting of the numbers. The example output below shows it using a comma as a thousands separator and a period (full-stop) as a decimal separator. Users in many European countries (for one example) should expect those two to be reversed.

Then you need to set the showbase flag for the stream. For other numbers, this tells the stream to show the base of the number as converted, so (for example) if you print out something in hexadecimal, it'll be preceded by a 0x (or 0X). When you write money, that gets re-purposed to saying whether to show the currency symbol or not.

You normally want to combine that with the advice you've already received about creating a class (or struct) to store the data about an item. Rather than a function named display, I'd create an overload of operator<< to display an item though.

Note that money values are stored as long doubles. In a typical case, it will be stored as an integral number of the smallest denomination of currency in normal use (e.g., in the US, an integral number of pennies). Therefore, initialization to 100.0 would actually mean a value of $1.002.

With that (and leaving out the code for your header), creating and displaying the table might look something like this:

#include <iostream>
#include <iomanip>
#include <string>
#include <vector>

unsigned short int width=10;
unsigned short int prec=6;

class item {
    std::string name;
    long double price;

public:
    item(std::string const &name, double price): name(name), price(price) {}

    friend std::ostream &operator<<(std::ostream &os, item const &i) {
        return os<<std::setw(width) << i.name
                 <<std::setw(width) << std::showbase << std::put_money(i.price);
    }
};

int main(void) {
    std::vector<item> items {
        {"water", 10000},
        {"Milk", 20000},
        {"Juice", 30000},
        {"Wine", 40000},
        {"Bread", 60000},
        {"Apple", 70000},
        {"Tuna", 80000},
        {"Steak", 90000},
        {"Bandage", 100000},
        {"Med-Kit", 110000},
        {"Splint", 120000},
        {"Thread", 130000}
    };

    std::cout.imbue(std::locale(""));

    unsigned count=0;

    for (auto &&item:items) {
        std::cout<<item;
        if (++count==3) {
            std::cout<<"\n";
            count=0;
        }
    }
}

Result:

    water   $100.00      Milk   $200.00     Juice   $300.00
     Wine   $400.00     Bread   $600.00     Apple   $700.00
     Tuna   $800.00     Steak   $900.00   Bandage $1,000.00
  Med-Kit $1,100.00    Splint $1,200.00    Thread $1,300.00

If you decide to do the formatting on your own, be aware that it won't be quite as simple as just inserting a $ before the item to be written. The problem is that you pretty much need to explicitly set a width and precision when you write out the value. When you do that, you'll quickly find that the $ gets inserted before the padding for the number, so (for example) your first entry will end up looking something like this:

    water$    100.00

...instead of putting the currency symbol next to the number where you almost certainly want it. It is possible to prevent that with enough extra work:

std::ostringstream temp;

temp << '$' << std::setprecision(your_precision) << value;

std::cout << std::setw(your_width) << temp.str();

Although it may be open to argument that usingstd::put_money is a little more work than you'd like, by the time you get the formatting even reasonably close to correct on your own, it's quite a bit more work still (and adding even minimal support for internationalization is quite a bit more work again).


  1. Do note, however, that while the symbol is automatically chosen based on the user's locale, no attempt is made to convert the value, so if I enter 1 dollar, and that value is displayed in a German locale, it'll show up as 1 Euro (and vice versa).
  2. Technically, I don't believe the standard actually requires this, but it's how all the compilers I've seen actually do things. The standard does require that get_money and put_money are symmetrical, so if a user enters $100.00 and you read it with get_money, store whatever that produces, and then write it back out with put_money, you should get $100.00 as the result.
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top