Search code examples
c++coutoutline

Formatting output (inputted by the user) in columns


I am working on a shopping cart project, and I want to print out the user input like the following output. I don't know how to use setW and right/left keywords, when it comes to the user decides what the output is going to be like. So when they enter different inputs in length, for example setW(20) does not work for them all.

Here is your order:
----------------------------------------------------------------
Name                     Unit_Price                  Quantity
T-shirt                    $19.99                       2

Sweater                    $39.99                       1

iphone_case                $25.5                        3

Towel                      $9.99                        5

The total charge is $206.42
----------------------------------------------------------------

This is the display function:

ostream& operator <<(ostream& os, Item& source) {
    os << source.getName() << setw(18)
       << source.getPrice() << setw(20) << source.getQuantity() << endl;
    return os;
}

And this is the output I get with this:

Here is your order:
----------------------------------------
NAME             PRICE            QUANTITY
tshirt           19.99               2
sweater           39.99               1
iphone_case            25.5               3
towel            9.99               5

The total price of the order is 206.42
----------------------------------------

And here is my main.cpp

#include "ShoppingCart.h"
#include "Item.h"

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

    using namespace std;


    int main()
    {
        cout << endl << endl << "Welcome to XXX SHOPPING CENTER" << endl;

        Item items[10];
        ShoppingCart<Item> cart;
        char userAnswer;

        cout << "Enter the item you selected as the following order:\nname unitPrice quantity\n"
             << "(Name can not contain any space. Otherwise errors happen!)" << endl;
        cin >> items[0];
        cart.add(items[0]);

        cout << "Want to continue? y/n" << endl;
        cin >> userAnswer;

        int index = 1;
        while(userAnswer == 'y' || userAnswer == 'Y') {

            cout << "Enter the next item:" << endl;
            cin >> items[index];
            cart.add(items[index]);
            cout << "Want to continue? y/n" << endl;
            cin >> userAnswer;
            index++;
        }


        // Display the summary of the orders
        cout << endl << "Here is your order:" << endl;
        // "--------------------------------------------------------------------"
        for(int i=0; i < 40; i++)
            cout << "-";

        cout << endl << "NAME" << setw(18) << "PRICE" << setw(20) << "QUANTITY" << endl;

        for(int i=0; i < cart.getCurrentSize(); i++) {
            cout << items[i];
        }

        cout << endl << "The total price of the order is " << cart.getTotalPrice() << endl;
        // "---------------------------------------------------------------------"
        for(int i=0; i < 40; i++)
            cout << "-";
        cout << endl;

        return 0;
}

Solution

  • The strategy you are using does not make sense to me. Here's one way to get the desired output:

    1. Use 20 characters for the first column and make sure that it is output with left aligned text.
    2. Use 10 characters for the second and third columns, and make sure they are output with right aligned text.
    3. Use std::left and std::right to control text alignment.

    Here's a simplified program that demonstrates the idea.

    #include <iostream>
    #include <iomanip>
    #include <vector>
    #include <string>
    
    struct Item
    {
       std::string name;
       double price;
       int quantity;
    };
    
    std::ostream& operator<<(std::ostream& out, Item const& item)
    {
       // First column
       out << std::left << std::setw(20) << item.name;
    
       // Second and third columns
       out << std::right << std::setw(10) << item.price << std::setw(10) << item.quantity;
    
       return out;
    }
    
    void printLine(std::ostream& out)
    {
       for(int i=0; i < 40; i++)
          out << "-";
       out << std::endl;
    }
    
    int main()
    {
       std::vector<Item> items;
       items.push_back({"tshirt", 19.99, 2});
       items.push_back({"sweater", 39.99, 1});
       items.push_back({"iphone_case", 25.50, 3});
       items.push_back({"towel", 9.99, 5});
    
       printLine(std::cout);
    
       // First column
       std::cout << std::left << std::setw(20) << "NAME"
    
       // Second and third columns
       std::cout << std::right << std::setw(10) << "PRICE" << std::setw(10) << "QUANTITY" << std::endl;
    
       // The items
       for(int i=0; i < 4; i++) {
          std::cout << items[i] << std::endl;
       }
    
       printLine(std::cout);
    }
    

    Output:

    ----------------------------------------
    NAME                     PRICE  QUANTITY
    tshirt                   19.99         2
    sweater                  39.99         1
    iphone_case               25.5         3
    towel                     9.99         5
    ----------------------------------------