0

Im making a drink machine program and I want all the prices to line up together.

Is there some way to tell the compiler to write the price X number of spaces from the start of the line instead of adding spaces after the drink name is posted?

int main()
{
const int arrsize = 5;
Drinks arr[arrsize] = {
    {"Cola",.75,20},
    {"Root Beer",.75,20},
    {"Lemon-Lime",.75,20},
    {"Grape Soda",.80,20},
    {"Cream Soda",.80,20},
};

for (;;){
    cout << "Please select a drink: "<<endl;
for (int i = 0; i < arrsize; i++){
    cout << (i+1)<<". "<< arr[i].DrinkName;
    cout << setw(10) << setfill(' ')<< right <<fixed << arr[i].DrinkCost<<endl;
}
cout <<"6. Quit";

break;
}

return 0;
}

What I want is for it to look like this:

Please select a drink:
1. Cola            0.75
2. Root Beer       0.75
3. Lemon-Lime      0.75
4. Grape Soda      0.80
5. Cream Soda      0.80
6. Quit

But it comes out looking like this:

Please select a drink:
1. Cola        0.75
2. Root Beer     0.75
3. Lemon-Lime      0.75
4. Grape Soda      0.80
5. Cream Soda      0.80
6. Quit
  • 2
    dunno about c++, but in C you'd use something like `printf('%5.2f', price)` to pad the number (in this case 5 spaces for the integer portion, and 2 decimal places). – Marc B Jul 05 '13 at 16:12
  • 2
    You can use `setw` and `left` for the name. – chris Jul 05 '13 at 16:12

4 Answers4

2

One way to do it is to align the string literals, i.e, adding spaces for padding.

Drinks arr[arrsize] = {
    {"Cola      ",.75,20},
    {"Root Beer ",.75,20},
    {"Lemon-Lime",.75,20},
    {"Grape Soda",.80,20},
    {"Cream Soda",.80,20},
};
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
  • Although this will be good for printing all strings as in the question, what if you want to print the names one by one? – Some programmer dude Jul 05 '13 at 16:26
  • It can definitely be done using stream modifiers (which I don't like because they are hard to read) or printf (which I don't like because it's not safe in C++), I prefer this version if the strings are statically defined. If not (they come from some kind of input), I would use boost::format, which can be used similarly to printf but is safer. – petersohn Jul 05 '13 at 16:28
  • This is good but it would mess up other parts of the code later on when I just need to display the drink name. – user2554341 Jul 05 '13 at 16:36
1

If you look closer at your output you will see that the numbers are justified to ten characters from the text, which is exactly what you requested.

What you should to is format the text instead:

cout << (i+1)<<". " << std::setw(15) << std::left << arr[i].DrinkName
     << std::fixed << arr[i].DrinkCost << std::endl;

Oh and a small tip: Don't use floating point types for monetary values.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    @Pixelchemist The nice things about rounding errors, is that it goes both ways. :) – Some programmer dude Jul 05 '13 at 16:28
  • Of course, in this case, there won't be any rounding errors. (The machine can represent 0.75 exactly.) And as long as he doesn't do any arithmetic, and doesn't output with more precision than he input (and doesn't input with too many digits), there shouldn't be an rounding errors either. – James Kanze Jul 05 '13 at 16:39
0

See the many detailed answers at std::string formatting like sprintf.

C++ can use C function calls easily, but for some you need to take a bit of care. C's printf() or sprintf() calls are two ways to get the format you want.

Community
  • 1
  • 1
CXJ
  • 4,301
  • 3
  • 32
  • 62
0

Try the following:

for (;;){
    cout << "Please select a drink: "<<endl;
for (int i = 0; i < arrsize; i++){
    cout << (i+1) << ". ";
    cout << left << setw(12) << setfill(' ') << arr[i].DrinkName;
    cout << setw(5) << fixed << arr[i].DrinkCost << endl;
}
andre
  • 7,018
  • 4
  • 43
  • 75