How to Align Numbers

I'm trying to line up the cost of the drinks, as well as the number left in the machine, I cant seem to figure it out using setw(), any help would be greatly appreciated


// Question 1.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include<iostream>
#include<string>
#include<fstream>
#include<iomanip>

using namespace std;

struct Names {
string DrinkName;
float Cost;
int NumDrink;
};

int main()
{
Names pop[5];

ifstream file;
file.open("drinks.txt");
if (!file) {
cout << "File Does Not Exist" << endl;
return(0);
}

for (int i = 0; i < 5; i++) {
file >> pop[i].DrinkName >> pop[i].Cost >> pop[i].NumDrink;
}

int x = 1;
string name;
int choice;
float pay;
float profit = 0;

while (x == 1) {
for (int i = 0; i < 5; i++) {
name = pop[i].DrinkName;
cout << left << i << ". "<< name << setw(40) << pop[0].NumDrink << setw(40) << pop[i].Cost << endl;
}
cout << "5. Exit" << endl;
cout << "Please Select one of the above options." << endl;

cin >> choice;

if (choice < 0 || choice>5) {
cout << "Invalid Option" << endl;
}
else if (choice == 5) {
cout << "Goodbye" << endl;
x = 2;
}
else {
cout << "Enter Amount deposited into Machine: $";
cin >> pay;
//cout << "TEST:" << pay << endl;
//cout << "TEST:" << (pay < pop[choice].Cost) << endl;
if (pay < pop[choice].Cost || pay>1) {
cout << "Invalid Amount." << endl;
}
else {
if (pop[choice].NumDrink = 0) {
cout << "Sold Out." << endl;
}
else {
pop[choice].NumDrink--;
cout << "Your Change is: $" << pay - pop[choice].Cost << endl;
profit = pop[choice].Cost + profit;
}
}
}
}
cout << "Total Profit = $" << profit << endl;
system("pause");
return 0;
}
The setw function needs to come before the value that you are printing. Right now you are printing the names of the drinks without any specified width. So, they print, and the stream is ready to start printing again right where the name left off. You give the number and cost fields widths, but not the name. so, if drink "dr1" and "drinkWithALongName" are both in the file, the information for "dr1" will be in 2 40-character columns starting at character 4, while the information for "drinkWithALongName" will be in 2 40-character columns starting at character 19.

Add a setw before printing out the drink name and you will be all right.

By the way, why are you assigning the name variable rather than simply printing pop[i].DrinkName? And check out your code for printing the number remaining--you always print out the number remaining of the first drink.
Last edited on
I tried placing a setw before the name, and it still seems to have no impact, and also i originally had it as pop[i].DrinkName, i was just trying to see if i could isolate each drink name and set them each individually i just forgot to return it back
Maybe like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
struct Names 
{
  string DrinkName;
  float Cost;
  int NumDrink;
};

int main()
{
  Names names[] = 
  {
    {"Coca Cola", 1.25f, 3},
    {"Fanta", 0.99f, 5 },
  };

  char buffer[256] = {0};

  for (auto drink : names)
  {
    sprintf(buffer, "%-15s %.2f %3d", drink.DrinkName.c_str(), drink.Cost, drink.NumDrink);
    cout << buffer << "\n";
  }
}

Output
Coca Cola      61.00  3
Fanta          20.75  5


How should the output actually look like ?
The output should list all of the 5 drink names and then in a separate column the costs and then in a 3rd column the amount remaining kind of like this

0. Cola 0.75 20
1. RootBeer 0.75 20
2. LemonLime 0.75 20
3. GrapeSoda 0.80 20
4. CreamSoda 0.80 20
For some reason that didnt format, but it should be in 3 seperate columns
Try this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <iomanip>
#include <map>
#include <string>
#include <sstream>

using namespace std;

struct Names 
{
  string DrinkName;
  float Cost;
  int NumDrink;
};

int main()
{
  Names names[] = 
  {
    {"Coca Cola", 0.75f, 20},
    {"RootBeer", 0.75f, 20 },
    {"LemonLime", 0.75, 20 },
    {"GrapeSoda", 0.80, 20},
    {"CreamSoda", 0.80, 20}

  };

  char buffer[256] = {0};

  for (int i =0; i < 5; i++)
  {
    sprintf(buffer, "%d. %-15s %.2f %3d", i, names[i].DrinkName.c_str(), names[i].Cost, names[i].NumDrink);
    cout << buffer << "\n";
  }

}

Output

0. Coca Cola       0.75  20
1. RootBeer        0.75  20
2. LemonLime       0.75  20
3. GrapeSoda       0.80  20
4. CreamSoda       0.80  20
Is this what you wanted?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;

struct Names 
{
  string DrinkName;
  float Cost;
  int NumDrink;
};

template<typename iter_t>
void printNames(iter_t begin, iter_t end, std::size_t minSpacing=2, std::ostream& out = std::cout) {
    std::size_t maxName = 0;
    long long maxCost = 0, maxDrink = 0;
    for (auto it = begin; it != end; ++it) {
        maxName = (it->DrinkName.length() > maxName ? it->DrinkName.length() : maxName);
        maxCost = ((it->Cost + .5) > maxCost ? (it->Cost + .5) : maxCost);
        maxDrink = (it->NumDrink > maxDrink ? it->NumDrink : maxDrink);
    }
    maxCost = std::to_string(maxCost).length();
    maxDrink = std::to_string(maxDrink).length();
    
    out << std::setprecision(2) << std::fixed;
    for (std::size_t index = 1; begin != end; ++index, ++begin) {
        out << std::left << index << ") " << std::setw(maxName) << begin->DrinkName;
        out << std::right << std::setw(maxCost + minSpacing + 3) << begin->Cost;
        out << std::setw(maxDrink + minSpacing) << begin->NumDrink;
        out << std::endl;
    }
}

int main()
{
  Names names[] = 
  {
    {"Coca Cola", 99771.f, 3},
    {"Fanta", 0.99f, 555 },
  };

  printNames(std::begin(names), std::end(names));
}
Thank you both for the help i sincerely appreciate it, but yes Thomas1965 i went off of your formatting and it worked!
Topic archived. No new replies allowed.