I tried to format output strings in my console application (like a table)
cout << "\n\n-----------------\n";
cout << setw(8) << left << "F\t|";
cout << setw(8) << left << "x\t|";
cout << "\n-----------------\n";
//...
cout.width(8);
cout.setf(ios::left);
cout << fixed << setprecision(3) << F << "\t|";
cout.width(8);
cout.setf(ios::left);
cout << x << "\t|";
cout << "\n-----------------\n\n";
But as result my output looks like this
What's wrong with my upper string formatting?
I used the same code as you did and got the same output until I removed the \t at the end of the line. See the new code:
cout << "\n\n-----------------\n";
cout << setw(8) << left << "F\t|";
cout << setw(8) << left << "x\t|";
cout << "\n-----------------\n";
//...
cout.width(8);
cout.setf(ios::left);
cout << fixed << setprecision(3) << F << "|";
cout.width(8);
cout.setf(ios::left);
cout << x << "|";
cout << "\n-----------------\n\n";
As already noted, it's the tabs that are causing the problem.
I would not stop at just removing the tabs though. As it stands right now, your code is highly repetitive and next to impossible to maintain. I'd do a (nearly) complete rewrite, with a couple of functions to cut down on the repetition. My first cut would probably look something like this:
// format a value in a field of specified width, followed by a separator
template <class T>
string field(T val, int w, char sep = '|') {
stringstream b;
b << setw(w) << left << fixed << setprecision(3) << val << sep;
return b.str();
}
// generate a separator for a specified number of fields,
// each of a specified width
string sep(int c, int w, char val = '-') {
string s(c * (w + 1), val);
return string("\n") + s + "\n";
}
int main() {
static const int w = 8;
double F = 1.234, x = 3.45;
string s = sep(2, w);
cout << "\n" << s;
cout << field("F", w) << field("x", w) << s;
cout << field(F, w) << field(x, w) << s;
}
Seems to me that this makes the code rather more readable and quite a bit more maintainable. For example, if we decided to display an a and b on the next line, it would seem fairly obvious to add something like:
cout << field(a, w) << field(b, w) << s;
...and we wouldn't have to look very hard to be pretty sure it was going to match up with the previous line. Likewise, if we wanted to change a column width, etc.
You may try:
cout << "\n\n-----------------\n";
cout << setw(8) << left << "F\t\t|"; // insert more tab here
cout << setw(8) << left << "x\t|";
cout << "\n-----------------\n";
//...
cout.width(8);
cout.setf(ios::left);
cout << fixed << setprecision(3) << F << "\t|";
cout.width(8);
cout.setf(ios::left);
cout << x << "\t|";
cout << "\n-----------------\n\n";
The console screen looks suspiciously Windows like.
If you are using Windows, you can use the Win32 API to format output more precisely.
In particular, you can use SetConsoleCursorPosition.
COORD position = {x,y};
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut, position);
std::cout<<"This will be printed starting at position x, y"<<std::endl;
Try this:
#include <iostream>
#include <iomanip>
#include <map>
#include <string>
using namespace std;
int main()
{
map< float, float > table =
{
{ 8232.0f, 89.0f },
{ 8232.1f, 89.0f },
{ 8232.2f, 89.0f },
{ 8232.3f, 89.0f },
{ 8232.4f, 89.0f },
{ 8232.5f, 89.0f },
{ 8232.6f, 89.0f },
{ 8232.7f, 89.0f },
{ 8232.8f, 89.0f },
};
const size_t CELL_WIDTH = 25;
const string CELL_LINE( CELL_WIDTH, '=' );
// print the header of table
cout << '|' << CELL_LINE << '|' << CELL_LINE << '|' << endl
<< '|'
<< left << setw( CELL_WIDTH ) << "F" << '|'
<< setw( CELL_WIDTH ) << "R" << "|\n|"
<< CELL_LINE << '|' << CELL_LINE << '|' << endl;
// print the body
// change cout precision
cout << fixed << setprecision( 3 );
for ( auto it : table )
cout << "| " << setw( CELL_WIDTH - 1 ) << it.first
<< "| " << setw( CELL_WIDTH - 1 ) << it.second
<< "|\n";
// print the footer
cout << '|' << CELL_LINE << '|' << CELL_LINE << '|' << endl;
return 0;
}
this is the result:
Related
I need to write ints from the right and strings from the left into a single line and have them line up properly (view output below the code).
Basically I just need a way to write a table only using iostream and iomanip and change the allingment from right for ints to left for strings and back.
Other tips are also appreciated :)
#include <iostream>
#include <iomanip>
using namespace std;
class foo
{
public:
int i;
std::string s;
int j;
foo(int i1,std::string s1,int j1) : i(i1), s(s1),j(j1) {};
};
int main()
{
foo f1(1, "abc",50);
foo f2(100, "abcde",60);
cout << resetiosflags(ios::adjustfield);
cout << setiosflags(ios::right);
cout << setw(6) << "i" << setw(15) << "s" << setw(15) << "j"<<endl;
cout << setw(8) << f1.i << setw(15)
<< resetiosflags(ios::adjustfield) << setiosflags(ios::left) << f1.s <<setw(5)
<< resetiosflags(ios::adjustfield) << setiosflags(ios::right) << setw(15) << f1.j << endl;
cout << setw(8) << f2.i << setw(15)
<< resetiosflags(ios::adjustfield) << setiosflags(ios::left) << f2.s <<setw(5
<< resetiosflags(ios::adjustfield) << setiosflags(ios::right) << setw(15) << f2.j << endl;
/*i s j
1abc 50
100abcde 60*/
return 0;
}
This is the output:
i s j
1abc 50
100abcde 60
And this is what i need:
i s j
1 abc 50
100 abcde 60
Using left and right in the same line isn't a problem. It looks like the issue you have is not allowing for space after the first value. It looks like the setw(5) may have been for that, but since there's nothing printed after it there's no effect. I used 7 to match the 15 total used for the string width.
Maybe something like this would work? Probably best to extract the magic numbers into constants so you can adjust all of them easily in one place. You could also wrap this in an operator<< to contain all the formatting code in one place.
The first line headings offset one to the left looks weird to me, but it matches your example and is easy to adjust if necessary.
#include <iostream>
#include <iomanip>
using namespace std;
class foo
{
public:
int i;
std::string s;
int j;
foo(int i1, std::string s1, int j1) : i(i1), s(s1), j(j1)
{};
};
int main()
{
foo f1(1, "abc", 50);
foo f2(100, "abcde", 60);
cout
<< right << setw(7) << "i" << setw(7) << ' '
<< left << setw(15) << "s"
<< right << "j"
<< endl;
cout
<< right << setw(8) << f1.i << setw(7) << ' '
<< left << setw(15) << f1.s
<< right << f1.j
<< endl;
cout
<< right << setw(8) << f2.i << setw(7) << ' '
<< left << setw(15) << f2.s
<< right << f2.j
<< endl;
return 0;
}
Output:
i s j
1 abc 50
100 abcde 60
I am trying to make a simple program in c++ that takes the price and number of items purchases, stores it in arrays, and then outputs the totals for each item in a tabular format. However, when I multiply the numbers in my code, I get totally strange answers! Can someone please enlighten me as to what's going on?
Code:
#include <iostream>
using namespace std;
int main(int argc, _TCHAR* argv[]) {
float price[4], tot[4];
int amt[4];
cout << "Please enter the price and amount of 4 items:\n";
for (int i = 0; i<4; i++) {
cout << "Price of item " << i + 1 << ": ";
cin >> price[i];
cout << "Amount of item " << i + 1 << ": ";
cin >> amt[i];
if (price[i] <= 0 || amt[i] <= 0) {
cout << "Invalid Input Entry!\n";
break;
}
tot[i] = price[i] * amt[i]; // I can't really see how I could have messed this up...
}
cout << "Total\t\tPrice\t\tAmount\n";
cout << "-----\t\t-----\t\t------\n";
for (int i = 0; i < 4; i++) {
cout << "$" << fixed << cout.precision(2) << tot[i] << "\t\t$" << price[i] << "\t\t" << amt[i] << endl;
}
system("pause");
return 0;
}
Output:
The problem is that you are outputting the return value of cout.precision(2) (which returns the previous precision, in this case 6 initially and then 2 afterwards) in front of each total price.
You need to either:
not pass the return value of cout.precision() to operator<<:
cout << "$" << fixed;
cout.precision(2);
cout << tot[i] << ...
or, call precision() one time before entering the loop:
cout.precision(2);
for (int i = 0; i < 4; i++) {
cout << "$" << fixed << tot[i] << "\t\t$" << price[i] << "\t\t" << amt[i] << endl;
}
use the std::setprecision() stream manipulator instead of calling cout.precision() directly:
#include <iomanip>
for (int i = 0; i < 4; i++) {
cout << "$" << fixed << setprecision(2) << tot[i] << "\t\t$" << price[i] << "\t\t" << amt[i] << endl;
}
or
#include <iomanip>
cout << setprecision(2);
for (int i = 0; i < 4; i++) {
cout << "$" << fixed << tot[i] << "\t\t$" << price[i] << "\t\t" << amt[i] << endl;
}
On a side note, you should not use \t characters to control the formatting of your table. Use stream manipulators like std::setw(), std::left, etc instead:
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstdlib>
using namespace std;
const int maxItems = 4;
string moneyStr(float amount)
{
ostringstream oss;
// in C++11 and later, you can replace this with std::put_money() instead:
// http://en.cppreference.com/w/cpp/io/manip/put_money
//
// oss << showbase << put_money(amount);
oss << "$" << fixed << setprecision(2) << amount;
return oss.str();
}
int main(int argc, _TCHAR* argv[])
{
float price[maxItems], tot[maxItems];
int amt[maxItems];
int cnt = 0;
cout << "Please enter the price and amount of " << maxItems << " items:" << endl;
for (int i = 0; i < maxItems; ++i)
{
cout << "Price of item " << i + 1 << ": ";
cin >> price[i];
cout << "Amount of item " << i + 1 << ": ";
cin >> amt[i];
if (price[i] <= 0 || amt[i] <= 0) {
cout << "Invalid Input Entry!" << endl;
break;
}
tot[i] = price[i] * amt[i];
++cnt;
}
cout << left << setfill(' ');
cout << setw(16) << "Total" << setw(16) << "Price" << setw(16) << "Amount" << endl;
cout << setw(16) << "-----" << setw(16) << "-----" << setw(16) << "------" << endl;
for (int i = 0; i < cnt; i++) {
cout << setw(16) << moneyStr(tot[i]) << setw(16) << moneyStr(price[i]) << setw(16) << amt[i] << endl;
}
system("pause");
return 0;
}
Live Demo
I've tested so many scenarios and it works without the while loop; but I just cant seem to figure out whats messing it up. if I pick an int in the target range 1-3 it passes and then freezes and i have to ctrl c the program out.
And if I pick a number outside that range it lets it pass in to the while loop and call the function. I'm very confused and this is the first program I've written with classes; so I feel like that probably is the issue.
Thanks.
#include <iostream>
using namespace std;
class Elevator
{
public:
void floorControl();
// Outputs floor actions and lets a user pick a floor number
int status();
// outputs floor positon
private:
int floorPosition = 1;
};
int main()
{
Elevator building[3];
int elevatorSelect;
cout << "\tElevator Status\n\tA\tB\tC\n"
<< "\t" << building[0].status() << "\t" << building[1].status()
<< "\t" << building[2].status() << endl
<< "\tWhich elevator do you want (1=A, 2=B, 3=C, or other to exit) ? ";
cin >> elevatorSelect;
cout << "\t" << elevatorSelect << endl;
while((elevatorSelect <= 3) && (elevatorSelect >=1));
{
building[elevatorSelect-1].floorControl();
cout << "\tElevator Status\n\tA\tB\tC\n"
<< "\t" << building[0].status() << "\t" << building[1].status()
<< "\t" << building[2].status() << endl
<< "\tWhich elevator do you want (1=A, 2=B, 3=C, or other to exit) ? ";
cin >> elevatorSelect;
cout << "\t" << elevatorSelect << endl;
}
return 0;
}
void Elevator::floorControl()
{
int floorSelect;
if(floorPosition > 1)
{
cout << "\tStarting at floor " << floorPosition << endl;
for(int i=1; i>floorPosition; floorPosition--)
cout << "\t Going down - now at floor " << floorPosition-1 << endl;
cout << "\tStopping at floor " << floorPosition << endl;
}
cout << "\tWhich floor do you want? ";
cin >> floorSelect;
if ((floorSelect < 1 )|| (floorSelect > 10))
cout << "\t**You pick up some dust off the wall; you missed**\n";
else
{
cout << "\tStarting at floor " << floorPosition << endl;
for (floorSelect; floorSelect > floorPosition; floorPosition++)
cout << "\t Going up - now at floor " << floorPosition+1 << endl;
cout << "\tStopping at floor " << floorPosition << endl;
}
}
int Elevator::status()
{
return floorPosition;
}
The program works my only problem is that I don't know how to line up the output. When ran using the .txt file it prints the names, boxes, and name of cookies but not aligned. Also, I have to calculate the amount due for each person and display it, but i only can figure out how to do the total. Thanks for help
#include <iomanip>
#include <string>
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
ifstream inFile;
//Declare Variables
string firstName;
string cookieName;
int boxesSold;
int numCustomers = 0;
double amountDue;
int totalCustomers;
int totalBoxesSold = 0;
double totalAmount = 0;
cout << "Girl Scout Cookies" << endl;
cout << "Created By Aaron Roberts" << endl;
inFile.open("cookie.txt");
if(inFile)
{
cout << "Customer Number Cookie" << endl;
cout << "Name Of Boxes Name" << endl;
while(inFile >>firstName>>boxesSold>>cookieName)
{
totalBoxesSold += boxesSold;
totalAmount += boxesSold * 3.50;
cout << setprecision(2) << fixed << showpoint;
cout << setw(2) << firstName
<< right << setw(7) << boxesSold
<< setw(20) << cookieName
<< endl;
numCustomers += 1;
}
cout << "\nNumber of Customers: "<< numCustomers << endl;
cout << "Total Boxes Sold: " << totalBoxesSold << endl;
cout << "Total Amount: $" << totalAmount << endl;
inFile.close();
}
else
{
cout << "Could not open file " << endl;
}
system("pause");
return 0;
}
Given you've allocated 12 characters in the header for the "Customer Name" and "Number Of Boxes" columns, you probably want to allocate 11 characters for their data, leaving one character for a trailing space.
For clarity and maintainability, I recommend you create constants for these:
int const name_column_width = 11;
int const boxes_column_width = 11;
Then you can write:
std::cout << std::setw(name_column_width) << std::left << "Customer" << ' '
<< std::setw(boxes_column_width) << std::left << "Number" << ' '
<< "Cookie"
<< std:: endl;
std::cout << std::setw(name_column_width) << std::left << "Name" << ' '
<< std::setw(boxes_column_width) << std::left << "Of Boxes" << ' '
<< "Name"
<< std:: endl;
while (inFile >> firstName >> boxesSold >> cookieName)
{
totalBoxesSold += boxesSold;
totalAmount += boxesSold * 3.50;
std::cout << std::setw(name_column_width) << std::left << firstName << ' '
<< std::setw(boxes_column_width) << std::right << boxesSold << ' '
<< cookieName
<< std::endl;
++numCustomers;
}
Resizing these columns then becomes a simple matter of changing the constant.
I want to input data from txt file.
the file contains 2-d array [5][5]
how can i print out the any value i want?
i don't want to print out the whole 5*5 data
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
double distance[5][5] ;
string line;
ifstream ratefile;
ratefile.open("a.txt");
ofstream file;
if (ratefile.is_open())
{
while (! ratefile.eof() )
{
getline (ratefile,line);
ratefile.getline(distance, 25, '*');
cout << "\nDistance [0][0]" << ": " << distance[0][0];
cout << "\nDistance [0][1]" << ": " << distance[0][1];
cout << "\nDistance [0][2]" << ": " << distance[0][2];
cout << "\nDistance [0][3]" << ": " << distance[0][3];
cout << "\nDistance [1][0]" << ": " << distance[1][0];
cout << "\nDistance [1][1]" << ": " << distance[1][1];
cout << "\nDistance [1][2]" << ": " << distance[1][2];
cout << "\nDistance [1][3]" << ": " << distance[1][3];
cout << endl;
cin.get();
return 0;
}
If you only want to output one value and the user should be able to choose a value, you can do something like this:
int x, y;
cin >> x;
cin >> y;
cout << "\nDistance [" << x << "][" << y << "]" << ": " << distance[x][y];
But you should check if the user enter valid numbers (0 <= x < 4 and 0 <= y < 4)
There is part of the code missing, but you are printing values you want. Simply remove the lines you don't want to print.
Of course you can also use variables:
int x = 2,y = 2;
cout << endl << "Distance [" << x << "][" << y << "] : " << distance[x][y];