c++ vector iterator output display vertically in columns
c++ vector iterator output display vertically in columns
I am trying to output my strings column-wise using the vector iterator as shown in the attached image.
For now I am just displaying a test case using the names and the cider order after which I want to replicate the same for others.
Below is my current code:
// values for controlling format
const int name_width = 15 ;
const int int_width = 7 ;
const int dbl_width = 12 ;
const int num_flds = 7 ;
const std::string sep = " |" ;
auto total_width = name_width*2 + int_width*2 + dbl_width*3 + sep.size() * num_flds ;
const std::string line = sep + std::string( total_width-1, '-' ) + '|' ;
cout<<"How many people ordered? ";
cin>>odrs; // Store number of orders
for(int i=1; i<=odrs; i++)
cout<<"Enter the name of person #"<<i<<":"<<endl;;
cin>>names; // Store names of users
odrNames.push_back(names); // Store names as entered as
cout<<"How many orders of cider did "<<names<<" have? ";
cout<<endl;
cin>>odrciderjuice; // Store Cider order item
sbCider = odrciderjuice * 5.5; // Calculate Cider order per price
odrCider.push_back(odrciderjuice); // Store Cider order item based on entry
SbCider.push_back(sbCider); // Store calculated Cider order per price
cout<<"How many orders of apple juice did "<<names<<" have? ";
cout<<endl;
cin>>odrapplejuice; // Store Juice order item
sbJuice = odrapplejuice * 4.5; // Calculate Juice order per price
odrApple.push_back(odrapplejuice); // Store Juice order item based on entry
SbJuice.push_back(sbJuice); // Store calculated Juice order per price
cout<<endl;
total = sbCider + sbJuice; // Calculate total between Cider and Juice
GTotal.push_back(total); // Store total values after calculation
cout<<endl;
for(vector<string>::iterator naming = odrNames.begin(); naming!= odrNames.end(); ++naming)
cout << sep << std::setw(name_width) << *naming<<"v";
for(vector<int>::iterator ciderOdr = odrCider.begin(); ciderOdr!= odrCider.end(); ++ciderOdr)
cout <<*ciderOdr;
2 Answers
2
Using iterator is indeed the idiomatic way to browse a collection. Simply, you need a collection of objects, instead of a bunch of unrelated collections!
In addition, you should be more consistent in your names, and only capitalizing a name between a single value and its collection is a future maintenance nightmare...
C++ is an OO language, and OO programming is a way to split a complex program in smaller units (the classes), which are responsable for only one small part of a larger program. This is intended to lead to code that is both simpler to test and to maintain.
Here the Order
class could contain:
Order
As your formatting is not trivial, I would use an alternate class to handle it. That class would contain:
vector<Order>
ostream
The main would then simply contain code to load the orders.
Code could be:
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
using namespace std;
struct Order
static constexpr double ciderPrice = 5.5;
static constexpr double juicePrice = 4.5;
std::string name;
int cider;
int juice;
double sbCider() const
return cider * ciderPrice;
double sbJuice() const
return juice * juicePrice;
double total() const
return sbCider() + sbJuice();
;
class Bill
// values for controlling format
static const int name_width = 10 ;
static const int int_width = 6 ;
static const int dbl_width = 17 ;
const std::vector<Order>& orders;
std::ostream& out;
...
public:
Bill(const std::vector<Order>& orders, std::ostream& out):orders(orders),out(out)
Bill& show_line()
...
return *this;
Bill& show_header()
...
return *this;
Bill& show_order(const Order &order)
...
return *this
Bill& show_total()
return *this
Bill &show_average()
...
return *this;
Bill& show()
...
show_header().show_line();
for (const Order& order: orders)
show_order(order);
return show_line().show_total().show_average().show_line();
;
int main()
Order order;
vector<Order> orders;
int odrs;
cout<<"How many people ordered? ";
cin>>odrs; // Store number of orders
for(int i=1; i<=odrs; i++)
cout<<"Enter the name of person #"<<i<<":"<<endl;;
cin>>order.name; // Store names of users
cout<<"How many orders of cider did "<<order.name<<" have? "<<endl;
cin>>order.cider; // Store Cider order item
cout<<"How many orders of apple juice did "<<order.name<<" have? "<<endl;
cin>>order.juice; // Store Juice order item
orders.push_back(order);
Bill bill(orders, std::cout);
bill.show();
return 0;
Many thanks Serge for the input. However, i am getting some errors when i try to run your code: 1. the Contructor Bill gives the error Expected member name or ';' after declaration 2. No matching constructor for initialization of Bill
– Nii1
Aug 22 at 23:17
@Nii1: the ... are markers that the
Bill
class is not complete. This code only intends to show you how you could change the general design, but it is not working code.– Serge Ballesta
Aug 23 at 7:57
Bill
After determining the length of each vector and ensuring they are the same length, simply use a regular for loop with an integer index. Then use that index to retrieve an element from each vector in turn.
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Consider storing each order in a struct or class and then store instances of that object in your vector. Once you have that it's much simpler to format each line.
– Retired Ninja
Aug 22 at 1:17