2

I was wondering if there was a way to setw(#) so my couts are aligned AND if I were to change up my wording that they would continue to be aligned. So I guess what I am asking print out the values separate from there indicators, almost like in there own columns??

Example Outputs: (original)

Enter the meal price for the first guest: $45.00
Enter the meal price for the second guest: $50.00
Enter the meal price for the third guest: $100.00

Tax:                             $13.16
Tip:                             $41.63
Total Bill:                      $249.79
Tip Per Person:                  $13.88
Total Per Person:                $83.26
The 3rd guest saved:             $16.74

(changing text)

Enter the meal price for the first guest: $45.00
Enter the meal price for the second guest: $50.00
Enter the meal price for the third guest: $100.00

Tax:                             $13.16
Gratuity:                        $41.63
Total Bill:                      $249.79
Tip Per Person:                  $13.88
Total Per Person:                $83.26
The 3rd guest saved:             $16.74

(My code)

#include <iomanip> //std:setprecision
#include <iostream>

using namespace std;

int main() {

    double ppl1, ppl2, ppl3, meal_total, tax, tip, total, total_bill, per_tip, per_total;

    // Get the cost of the meal
    cout << "Enter the meal price for the first guest: $";
    cin >> ppl1;
    // Get the cost of the meal
    cout << "Enter the meal price for the second guest: $";
    cin >> ppl2;
    // Get the cost of the meal
    cout << "Enter the meal price for the third guest: $";
    cin >> ppl3;
    cout << endl;
    // Caluates the tax & tip & total
    meal_total = ppl1 + ppl2 + ppl3;
    tax = meal_total * 6.75 / 100;
    tip = (tax + meal_total) * 20 / 100;
    total_bill = (tax + meal_total) + tip;
    per_tip = tip / 3;
    per_total = total_bill / 3;

    // I do not have the extra credit in place
    cout << "\nTax:                 $" << setprecision(2) << fixed << tax;
    cout << "\nTip:                 $" << setprecision(2) << fixed << tip;
    cout << "\nTotal bill:          $" << setprecision(2) << fixed << total_bill;
    cout << "\nTip per person:      $" << setprecision(2) << fixed << per_tip;
    cout << "\nTotal per person:    $" << setprecision(2) << fixed << per_total << endl;

    // Additional Lab2A adding starts here:
    // Adding vars to calulate savings on an per User basis
    // then "If" the "Guest total" is greater then 0 we are displaying savings

    double ppl1_Tax = ppl1 * 6.75 / 100;
    ;
    double ppl1_Tip = (tax + ppl1) * 20 / 100;
    double Price_ppl1 = (ppl1 + ppl1_Tax) + ppl1_Tip;
    if ((Price_ppl1 - per_total) > 0) {
        cout << "The 1st guest saved: $" << (Price_ppl1 - per_total) << endl;
    }

    double ppl2_Tax = ppl2 * 6.75 / 100;
    ;
    double ppl2_Tip = (tax + ppl2) * 20 / 100;
    double Price_ppl2 = (ppl2 + ppl2_Tax) + ppl2_Tip;
    if ((Price_ppl2 - per_total) > 0) {
        cout << "The 2nd guest saved: $" << (Price_ppl2 - per_total) << endl;
    }

    double ppl3_Tax = ppl3 * 6.75 / 100;
    ;
    double ppl3_Tip = (tax + ppl3) * 20 / 100;
    double Price_ppl3 = (ppl3 + ppl3_Tax) + ppl3_Tip;
    if ((Price_ppl3 - per_total) > 0) {
        cout << "The 3rd guest saved: $" << (Price_ppl3 - per_total) << endl;
    }

    return 0;
}
sehe
  • 374,641
  • 47
  • 450
  • 633
csiket715
  • 51
  • 7
  • 1
    Have you taken a look at `std::left` and `std::right` manipulators? – WhiZTiM Sep 19 '17 at 12:29
  • As an aside, it's not encouraged to use floating point to represent money. Rather two integers for dollars and cents, with encapsulated logic for manipulating it – AndyG Sep 19 '17 at 12:32
  • Consider stopping the declaration of uninitialized variables at the top of your function. That is a holdover from very old versions of C that required that, and if you miss assigning a variable before using it, your code won't work as intended. [Declare variables at top of function or in separate scopes?](https://stackoverflow.com/a/3773458/1441) – crashmstr Sep 19 '17 at 12:34
  • @AndyG: No need for two integers, just use a single int with a decimal shift. int64 with an implied divisor of 10^8 works perfectly in all world currencies. – John Zwinck Sep 19 '17 at 12:35
  • @JohnZwinck: I stand corrected. I misremembered Martin Fowler's pattern. – AndyG Sep 19 '17 at 12:43
  • Yeah I have and I tried those but when I went to add them and add the new output was still messed up – csiket715 Sep 19 '17 at 12:45

2 Answers2

2

You answered your own question, simply use setw(width), example of a helper function:

void print_padded(const std::string& word, int width) {
    std::cout << std::left << std::setw(width) << std::setfill(' ') << word;
};

Adding a little more info, if you don't know if there are going to be words larger than width, keep track of the largest word and set width to word.length() + 2 or something like that.

Mikael
  • 969
  • 12
  • 24
  • 1
    The challenge of course is finding the correct value for `width`. But `std::cout` can't do it for you. – MSalters Sep 19 '17 at 12:34
  • @MSaltersl he can just set width to the largest string or whatever size he wants it to be, from my perception of his example `width` seemed like a fixed value, having only `word` mutable. – Mikael Sep 19 '17 at 12:35
0

You could take inspiration from my answer yesterday:

How to write in text file by line and column using C++

Likewise you can collect the printable rows before actually printing them. Then you can deduce the minimum required width for the caption column before printing.

Meanwhile, removing repetition in the code and using expressive names can improve it too:

Live On Coliru

#include <iomanip> //std:std::setprecision
#include <iostream>
#include <vector>
#include <algorithm>

struct Pricing {
    double _base;
    static constexpr double tax_rate = 0.0675;
    static constexpr double tip_rate = 0.20;

    double tax() const      { return _base * tax_rate;       } 
    double tip() const      { return with_tax() * tip_rate;         } 

    double with_tax() const { return _base * (1 + tax_rate); } 
    double with_tip() const { return with_tax() * (1 + tip_rate);   } 
};

struct DinnerParty {
    struct Party {
        std::string name;
        double base_price;
    };

    using Parties = std::vector<Party>;

    DinnerParty(Parties parties) : _parties(std::move(parties)) { }

    Parties const& parties() const { return _parties;                      } 
    size_t head_count() const      { return _parties.size();               } 
    Pricing total() const          { return { base_total()              }; } 
    Pricing per_head() const       { return { base_total()/head_count() }; } 

  private:
    Parties const _parties;

    double base_total() const {
        double base = 0;
        for (auto& p : _parties) base += p.base_price;
        return base;
    }
};

template <typename ColDefs>
void printTable(ColDefs const& cols) {
    if (cols.empty())
        return;

    // find widest caption
    std::vector<int> widths;
    for (auto& col : cols)
        widths.push_back(col.caption.length());

    int width = 2 + *std::max_element(widths.begin(), widths.end());

    for (auto& col : cols)
    {
        if (col.caption.empty())
            std::cout << "\n";
        else std::cout 
            << std::left  << std::setw(width) << (col.caption+": ") << "$"
            << std::right << std::setprecision(2) << std::fixed << col.value << "\n";
    }
}

int main() {

    std::cin.exceptions(std::ios::failbit);

    auto promptPrice = [](auto name) { 
        std::cout << "Enter the meal price for " << name << ": $";
        double base_price;
        std::cin >> base_price;

        return DinnerParty::Party { name, base_price };
    };

    DinnerParty dinner({
        promptPrice("first guest"),
        promptPrice("second guest"),
        promptPrice("third guest"),
    });

    struct Row { std::string caption; double value; };

    Pricing total    = dinner.total(),
            per_head = dinner.per_head();

    std::vector<Row> rows {
        {"Tax", total.tax() },
        {"Tip", total.tip() },
        {"Total bill", total.with_tip() },
        {"Tip per person", per_head.tip() },
        {"Total per person", per_head.with_tip() },
        {"", 0}, // empty row
    };

    // Additional Lab2A adding starts here:
    // Adding vars to calulate savings on an per User basis
    // then "If" the "Guest total" is greater then 0 we are displaying savings
    for (auto& party : dinner.parties()) {
        Pricing personal {party.base_price};

        double net_gain = personal.with_tip() - per_head.with_tip();

        if (net_gain > 0)
            rows.push_back({party.name + " saved", net_gain });
    }

    printTable(rows);
}

Prints

Enter the meal price for first guest: $ 17
Enter the meal price for second guest: $ 32
Enter the meal price for third guest: $ 25

Tax:                $5.00
Tip:                $15.80
Total bill:         $94.79
Tip per person:     $5.27
Total per person:   $31.60

second guest saved: $9.39
third guest saved:  $0.43
sehe
  • 374,641
  • 47
  • 450
  • 633