Dynamic alignment issue - c++

When I try to list details of all items, each on a different line
with line numbering, there is alignment issue on it. I want instantly put the close bracket after the line numbering. Thanks.
cout << left
<< setw(20) << " Item Code"
<< setw(50) << "Description"
<< setw(20) << "Quantity on hand"
<< setw(20) << "Cost price"
<< setw(20) << "Selling price(RM)"
<< setw(20) << "Status"
<< setw(20) << "Discount(%)" << endl;
for (int i = 0; i <= 100; i++)//counter - 1; i++)
{
cout << left
<< setw(2) << i + 1 << ")"
<< setw(20) << item[i].getItemCode()
<< setw(50) << item[i].getDescription()
<< setw(20) << item[i].getQuantity()
<< setw(20) << item[i].getCostPrice()
<< setw(20) << item[i].getSellPrice()
<< setw(20) << item[i].getStatus()
<< setw(20) << item[i].getDiscount() << endl;
}

The only way of doing this, as far as I can see, is to walk through the list and find out "how long does this get" for each of the columns, and track what the largest is for each of the columns. Then use those values in the column width.
Strings are easy to find the length of, since they have a length as such. Numbers are harder - basically, you have to either take the approach of dividing it by ten down until it's zero (this means the integer part of floating point numbers - presumably for something like this, you have a fixed number of decimals or use "integeer to represent prices in cents" or some such). You may be able to use the std::tostring to produce as string that has a length too. Or you can use stringstream to output to a string - either individual items, or the whole lot and then count the number of characters between some separator character [that doesn't occur in the normal output, or things go wrong pretty easily!]
Example, using a simple struct:
struct Data
{
int x;
string y;
float z;
}
...
Data d[10];
int maxLen[3] = { 0 };
... // code fills in data with stuff.
for(int i = 0; i < 10; i++)
{
stringstream ss;
ss << left << d[i].x << " " << d[i].y << " " << fixed << setprecision(2) << d[i].z;
// Number of elements = 3.
for(int j = 0; j < 3; j++)
{
string s;
ss >> s;
if (s.length() > maxLen[j])
maxLen[j] = s.legnth;
}
}
...
for(int i = 0; i < 10; i++)
{
cout << left << setw(3) i << ": "
<< setw(maxLen[0]+1) << d[i].x
<< setw(maxLen[1]+1) << d[i].y
<< setw(maxLen[2]+1) << fixed << setprecision(2) << d[i].z << endl;
}

Related

Input for one line is messing up, code is similar all throughout

Hello this program i made is supposed to obtain a height in inches (age 1-18) from the user and based off the amount, produce the an estimated height when the individual becomes an adult. The program works as inteded except when I input womens height it does not come out properly. It shows up as the numbers 1-18, compared to the mens height which shows whatever was input. This issue also messes up the equation because instead of calculating using the input number it uses 1-18. I get the error
Warning C6385 Reading invalid data from 'growthChart[x]': the readable size is '40' bytes, but '48' bytes may be read.
but it only shows under the line cin >> growthChart[x][5];. Not sure how i should go about fixing this becuase i see no issue with it and the other similar problems I looked up were in different cases.
int main()
{
double growthChart[19][5] = { {0,28.6,30.9},{1,42.2,44.7},{2,49.5,52.8},{3,53.8,57},{4,58,61.8}, {5,61.8,66.2},{6,65.2,70.3},
{7,69,74},{8,72,77.5},{9,75,80.7},{10,78,84.4},{11,81.1,88.4},{12,84.2,92.9},{13,87.3,96.5}, {14,91.5,98.3},
{15,96.1,99.1},{16,98.3,99.6},{17,99.3,100},{18,99.8,100} };
char choice;
bool runAgain = true;
int x;
while (runAgain)
{
for (x = 0; x < 19; x++)
{
cout << "\nAge in Years " << x;
growthChart[x][0] = x;
cout << "\nEnter Boys height in inches:: ";
cin >> growthChart[x][4];
cout << "\nEnter Girls height in inches :: ";
cin >> growthChart[x][5];
}
cout << "\n\n" << "The displayed height shows feet as a whole number and the decimal as inches.";
cout << "\n\n" << setw(10) << "Age" << setw(25) << "Boys height(inches)" << setw(25)<< "Growth percentage" << setw(25) << "Boys height(feet/inches)"
<< setw(25) << "Girls height(inches)" << setw(25) << "Growth percentage" << setw(25) << "Girls height(feet/inches)";
for (x = 0; x < 19; x++)
{
cout << "\n" << setw(10) << growthChart[x][0] << setw(25) << growthChart[x][4] << setw(25) << growthChart[x][1]<< "%" << setw(25) << ((growthChart[x][4]*(100 / growthChart[x] [1]))/12)
<< setw(25) << growthChart[x][5] << setw(25) << growthChart[x][2] << "%" << setw(25) << ((growthChart[x][5]*(100 / growthChart[x][2]))/12);
}

How do I properly format this table?

I'm trying to properly format a table so that it prints out values below each column, beginning with the first character of that column. I've had success formatting three columns, but I'm unable to figure out how to format the K Count and LM Count columns so that they are printed out in a neat fashion.
What are some corrections I can make to the while loop portion of the code so that the K count and LM count columns are printed out neatly?
void printTable(const vector<int>& z, const vector<long>& x, const
vector<long>& y,
const vector<int>& a, const vector<int>& b)
{
ostringstream ss;
ss << "\n\n\n" << setw(10) << left << "Digits" << "Input Numbers "
<< setw(11) << right << "K Output " << setw(6)
<< right << "K Count " << setw(10) << right << "LM Output " << setw(6)
<< right << "LM Count" << endl;
int i = 0, n = 0;
while (i < 5)
{
string q = to_string(z[2*n]) + " x " + to_string(z[abs(2*n + 1)]);
string r = to_string(x[i]);
string s = to_string(a[i]);
string t = to_string(y[i]);
string u = to_string(b[i]);
ss << setw(10) << left << (i+1) << q
<< setw(16) << right << r
<< setw(11) << right << s
<< setw(12) << right << t
<< setw(10) << right << u << endl;
i++;
n++;
}
string r = ss.str();
cout << r;
}
You're printing the following:
- Digits left aligned over 10 chars
- Directly followed by the input number without specifying the width
- K output right aligned over 16 chars
You should instead specify the width of the input numbers as well.
Try this:
ss << setw(10) << left << (i+1) <<
setw(16) << left << q <<
setw(10) << right << s <<
setw(12) << right << t <<
...
The exact width of each column may not be correct. Try it out yourself.
To fix K Count output, you should reset the cursor to align left after setting the width for the previous result, then shift back right. Something like this should do what you want.
ss << setw(10) << left << (i+1) << right
setw(16) << left << q << right <<
setw(11) << left << r << right <<
setw(12) << left << s << right <<
setw(12) << left << t << right <<
setw(10) << left << u << right << endl;

How do I find the sum using a loop function?

I was able to loop a file that gave me the miles driven, gallons used, and gasoline cost at a certain day successfully. Now I'm trying to figure out how to get the sum of miles driven, gallons used, and gasoline cost by using loops
int main()
{
ifstream inputFile;
int x = 1;
int milesDriven = 0;
double gallonsUsed = 0,
gasolineCost = 0;
int truckNumber,
numberOfTrips,
sumMilesDriven = 0;
double sumGallonsUsed = 0,
sumGasolineCost = 0;
int avgMilesDriven;
double avgGallonsUsed,
avgGasolineCost;
/* Display Truck Information
Get Number of Trips
Get Truck Information
Process Each Trip
Display Averages
*/
inputFile.open("100.txt");
//Display Truck Information
cout << " " << setw(35) << "Red-Rig Trucking" << endl << endl;
cout << " " << setw(40) << "Summary of Truck Operations" << endl << endl;
inputFile >> truckNumber;
cout << "Truck: " << truckNumber << endl << endl;
inputFile.close( );
inputFile.open("truck.txt");
//Get Number of Trips
inputFile >> numberOfTrips;
//Get Truck Information
cout << "Day" << " " <<setw(16) << "Miles" << " " << setw(16) << "Gallons"
<< " " << setw(16) << "Gasoline" << endl << setw(20) << "Driven" << " "
<< setw(16) << "Used" << " " << setw(16) << "Cost" << endl << endl;
while(!inputFile.eof()){
inputFile >> milesDriven >> gallonsUsed >> gasolineCost;
cout << x << " " << setw(17) << milesDriven << " " << setw(17)
<< fixed << setprecision(2) << gallonsUsed << " " << setw(12) << fixed
<< setprecision << gasolineCost << endl ;
x++;
}
//Process Each Trip
/*while(inputFile)
{ sumMilesDriven = sumMilesDriven + milesDriven;
inputFile >> milesDriven;
}*/
for (; milesDriven--;)
sumMilesDriven += milesDriven;
cout << endl << "Sum" << " " << setw(15) << sumMilesDriven ;
for (;gallonsUsed;)
sumGallonsUsed += gallonsUsed;
cout << " " << setw(17) << sumGallonsUsed;
for (;gasolineCost--;)
sumGasolineCost += gasolineCost;
inputFile.close( );
return 0;
}
I've gotten this far and I can't figure out what's wrong. I've taken out the milesDriven >=10 from the for loop parenthesis. When the code runs I get an incorrect sum amount. The sum is either too big or too small.
Your code:
for (sumGasolineCost += gasolineCost; gasolineCost >= 1; gasolineCost--);{
cout << " " << setw(17) << sumGasolineCost;
}
My first advice is, do not write confusing code. Whenever you're programming, you have better things to do than tie your shoelaces together. I think you know the above is equivalent to:
for (sumGasolineCost += gasolineCost; gasolineCost >= 1; gasolineCost--);
cout << " " << setw(17) << sumGasolineCost;
That lets us discuss the loop itself. Go back and consult your textbook. The for loop has three components:
for( init ; test ; incr )
init is executed once, usually to initialize what will be tested
test is executed on each iteration, including the first, to determine if the loop body will be executed
incr is executed after the loop body, usually to update the tested value
In your case, sumGasolineCost += gasolineCost is in init. It is executed once. It should be in the loop body. There are other errors, too. I can't be much more specific because you don't indicate where the array or input is that you're looping over.
Once you get your loop doing what it should, you might find the standard std::accumulate function interesting to compare to.

Seg fault while outputting 2-d array of strings

So i have been working on this code for a while, and I am not very skilled. I have created two classes one defines an item for a shopping list, and the other creates an array of the objects and outputs them as a list. The program works in my windows command prompt, but segfaults on GNU command line when I am outputting the array using cout statements.
void List::createList(Item ** itemPtr, int size)
{
string** list1 = new string*[size];
for(int i = 0; i < 5; i++)
{
list1[i] = new string[5];
}
for (int i = 0; i < size; i++)
{
list1[i][0] = itemPtr[i]->getName();
list1[i][1] = itemPtr[i]->getUnit();
list1[i][2] = itemPtr[i]->getSTRnumToBuy();
list1[i][3] = itemPtr[i]->getSTRcost();
list1[i][4] = itemPtr[i]->getSTRextCost();
}
cout << endl << left << fixed << setw(15) << setprecision(2) << "Name";
cout << fixed << left << setw(15) << setprecision(2) << "Unit Type";
cout << fixed << left << setw(15) << setprecision(2) << "# of units";
cout << fixed << left << setw(15) << setprecision(2) << "Cost/Unit";
cout << fixed << left << setw(15) << setprecision(2) << "Total" << endl;
for (int i = 0; i < size; i++)
{
cout << fixed << left << setw(15) <<setprecision(2)<<endl<< list1[i][0];
cout << fixed << left << setw(15) << setprecision(2) << list1[i][1];
cout << fixed << left << setw(15) << setprecision(2) << list1[i][2];
cout << fixed << left << setw(15) << setprecision(2) << list1[i][3];
cout << fixed << left << setw(15) << setprecision(2) << list1[i][4];
}
}
Your 1st loop should be :
for(int i = 0; i < size; i++)
{
list1[i] = new string[5];
}
That is, loop till size, not till 5.
string** list1 = new string*[size];
for(int i = 0; i < 5; i++)
Looks like a bug to me: if size < 5 then you will be reading out of bounds of the array you have created.
list1[i][0] = itemPtr[i]->getName();
list1[i][1] = itemPtr[i]->getUnit();
list1[i][2] = itemPtr[i]->getSTRnumToBuy();
list1[i][3] = itemPtr[i]->getSTRcost();
list1[i][4] = itemPtr[i]->getSTRextCost();
This could fail if the size of the itemPtr array is less than size.
Another point, though not related to the crash you're seeing, you are leaking memory here. list1 is a local variable that's not stored somewhere in your class. You are allocating memory for it on the heap, but do not free that memory (delete) it anywhere.
Your using C++ not C so use the power of the vector
void List::createList(Item ** itemPtr, int size) {
vector<vector<string>> list1;
list1.resize(size);
for (int i = 0; i < size; i++) {
list1[i].resize(5);
list1[i][0] = itemPtr[i]->getName();
list1[i][1] = itemPtr[i]->getUnit();
list1[i][2] = itemPtr[i]->getSTRnumToBuy();
list1[i][3] = itemPtr[i]->getSTRcost();
list1[i][4] = itemPtr[i]->getSTRextCost();
}
cout << endl << left << fixed << setw(15) << setprecision(2) << "Name";
cout << fixed << left << setw(15) << setprecision(2) << "Unit Type";
cout << fixed << left << setw(15) << setprecision(2) << "# of units";
cout << fixed << left << setw(15) << setprecision(2) << "Cost/Unit";
cout << fixed << left << setw(15) << setprecision(2) << "Total" << endl;
for (int i = 0; i < size; i++)
{
cout << fixed << left << setw(15) <<setprecision(2)<<endl<< list1[i][0];
cout << fixed << left << setw(15) << setprecision(2) << list1[i][1];
cout << fixed << left << setw(15) << setprecision(2) << list1[i][2];
cout << fixed << left << setw(15) << setprecision(2) << list1[i][3];
cout << fixed << left << setw(15) << setprecision(2) << list1[i][4];
}
}
Look Ma, no news nor deletes.

can't get setw to line up

I'm not sure how to go about lining this up better. I thought by using L = name.length(); and subtracting that from the setw it would line up better but nope. I have name and ID set correctly but I can't seem to get the rest to line up. These are floats btw.
for (int z=0; z<i ;z++){
if( EInfo[z].valid >0){
string name = employee[z].getName();
int L = name.length();
payReportObj << fixed << setprecision (2) << endl;
payReportObj << setw(3) << employee[z].getID()
<< setw(36)
<< employee[z].getName()
<< setw(30-L) << "$" << setw(4) << EInfo[z].grossPaySE
<< setw(25) << "$" << setw(4) << EInfo[z].taxSE
<< setw(15) << "$" << setw(4) << EInfo[z].insuranceSE
<< setw(25) << "$" << setw(4) << EInfo[z].netPaySE;
I'm attempting to get it more like this...
This is what I have...
Replace setw(30-L) with setw(30). And this:
int L = name.length();
is not needed. If you want to right-align numbers, use std::right.
It seams that you opened your output file in nodepad with proportional font. You won't see columns aligned with proportional font even if they are. Change font to fixed or type in your terminal type output.txt.