Display data in two columns c++ - c++

I am trying to display the same data but in two columns, so after school week 19, the data should be displayed in the columns to the right of the table until the total school weeks is reached i.e. 36. Below is the code:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
int const schoolWeeks = 37;
string week[] = { "A", "B", "C", "D" };
int num = 0;
int main()
{
cout << left << setw(9) << setfill(' ') << "Week " << left << setw(9) << setfill(' ')<< "Menu" << left << setw(9) << setfill(' ') << "Week " << "Menu" << endl;
for (int i = 1; i < 20; i++)
{
cout << left << setw(9) << setfill(' ')<< i << week[num] << endl;
num = num + 1;
if (num == 4)
{
num = 0;
}
}
for (int i = 20; i < schoolWeeks; i++)
{
cout << left << setw(9) << setfill(' ') << i << week[num] << endl;
num = num + 1;
if (num == 4)
{
num = 0;
}
}
}

Standard output with std::cout is based on the idea of a stream of data. Remember, it's called "iostream" for a reason. This means once you have written something to std::cout, you simply cannot "go back" a few lines and add something.
Consider piping in a Linux shell or on the Windows command line. It's possible to redirect the output of your program to be the input of another program, which could then do any imaginable thing with it, e.g. sending it over the internet:
myprogram.exe > otherprogram.exe
How could you possibly add something to an already written line in such a scenario?
Considering all of this, it becomes clear that the only viable solution is to know in advance the contents of every line. You cannot wait until line 19 before thinking about the second column, you must do it right away. In other words, first print week 1 and week 19, then week 2 and week 20, then week 3 and week 21, and so on. See the pattern? It's always "week X in column one, week X+18 in column two". And that's pretty much the solution.
Here's a quickly written loop adhering to the style of your existing code:
for (int i = 1; i < 19; i++)
{
cout << left << setw(9) << setfill(' ')<< i << week[num]
<< left << setw(9) << setfill(' ') << " " << (i + 18) << " "
<< left << setw(9) << setfill(' ') << " " << week[num]
<< endl;
num = num + 1;
if (num == 4)
{
num = 0;
}
}
The manipulators like std::setw or std::setfill could probably use some improvement, but the point is that:
The loop only counts from 1 to 18.
The body performs the output for i and for i + 18.

Related

How can I add horizontal space between two functions in C++?

So I want to output a list of the names and randomly generated numbers. I already did everything else it is just that I do not know how to output it the way I want it to.
I want it to output like this:
ID #: Names:
1 bob
23 rob
44 kanye
Here is what I have so far:
cout << "Would you like to view the archived names and IDs? (Y/N)" << endl;
string archiveInput;
cin >> archiveInput;
if(tolower(archiveInput[0]) == 'y')
{
cout << "ID #: Names: " << endl;
output(ids, names);
}
Here are my functions I used.
void output(const vector<int>& ids)
{
for(int i = 0; i < ids.size(); i++)
{
cout << ids[i] << endl;
}
cout << endl;
}
void output(const vector<string>& names)
{
for(int i = 0; i < names.size(); i++)
{
cout << names[i] << endl; //might have to use endl for list format
}
cout << endl;
}
void output(const vector<int>& ids, const vector<string>& names)
{
cout << output(ids) << " " << output(names); //I thought this would work, im new :(
}
Try to using this method
#include <iostream>
#include <iomanip>
using namespace std;
class Student
{
public:
string studentName;
int studentAge;
int studentMarks;
int admissionYear;
Student(string name, int age, int marks, int year)
{
studentName = name;
studentAge = age;
studentMarks = marks;
admissionYear = year;
}
};
int main()
{
Student studentArray[4] = {Student("Alex", 20, 80, 2018), Student("Bob", 21, 82, 2018), Student("Chandler", 23, 85, 2017), Student("Rose", 18, 89, 2019)};
cout
<< left
<< setw(10)
<< "Name"
<< left
<< setw(5)
<< "Age"
<< left
<< setw(8)
<< "Marks"
<< left
<< setw(5)
<< "Year"
<< endl;
for (int i = 0; i < 4; i++)
{
cout
<< left
<< setw(10)
<< studentArray[i].studentName
<< left
<< setw(5)
<< studentArray[i].studentAge
<< left
<< setw(8)
<< studentArray[i].studentMarks
<< left
<< setw(5)
<< studentArray[i].admissionYear
<< endl;
}
return 0;
}
It will print the below output :
Name Age Marks Year
Alex 20 80 2018
Bob 21 82 2018
Chandler 23 85 2017
Rose 18 89 2019
We have set different widths for each column. The first column width is 10, the second column width is 5, the third column width is 8, and the last column width is 5.
The width is important here. If it is less than the size of its content, the content will overflow.
cout << output(ids) << " " << output(names);
First runs the function output overloaded with ids argument, and afterwards runs the version with the names like so:
for(int i = 0; i < ids.size(); i++)
{
cout << ids[i] << endl;
}
cout << endl;
// returns from first function call
cout << " ";
// enters second function call
for(int i = 0; i < names.size(); i++)
{
cout << names[i] << endl; //might have to use endl for list format
}
cout << endl;
Is how the compiler will run it, which is why your output is underneath each other.
This code is what you want inside the overload with the two arguments:
for(int i = 0; i < ids.size(); i++)
{
cout << ids[i] << " " << names[i] << endl;
}
cout << endl;
However your output will still not quite look like how you want. You have to apply other tricks for that.
This is the reason why your current code behave like that. Look at M Khaidar's answer for the correct way to solve your problem.

Divider in a program

I am trying to get a divider in my program, I got it to output however I notice their is a gap on the top. For example my code outputs:
*******************************************************************************************
Broome
CST 113 Y01
LAB
Stan
******************************************************************************************
I just want the code to output like this:
*******************************************************************************************
Broome
CST 113 Y01
LAB
Stan
******************************************************************************************
without that annoying gap. Here is my that outputs the divider:
//Output the divider to the screen
cout << setfill('*') << setw(SCREEN_WIDTH + 1) << " " << setfill(' ')
<< endl;
// Output the course heading to the screen
cout << setw((SCREEN_WIDTH + 11) / 2) << COLLEGE << endl;
cout << setw((SCREEN_WIDTH + 11) / 2) << COURSE << endl;
cout << setw((SCREEN_WIDTH + 5) / 2) << LAB_NAME << endl;
cout << setw((SCREEN_WIDTH + 15) / 2) << PROGRAMMER_NAME << endl;
//Output the divider to the screen
cout << setfill('*') << setw(SCREEN_WIDTH + 1) << " " << setfill(' ') << endl;
I am sure it is something simple I am missing
I duplicated your problem using MinGW and running in a 80 column Windows console with SCREEN_WIDTH set to 80. If the console is wider than SCREEN_WIDTH + 1, the problem is not exhibited.
Your code will print exactly SCREEN_WIDTH asterisks followed by a space. If your console is exactly SCREEN_WIDTH columns wide, that space will actually be printed on the next line (though you can't see it -- it's a space!). Even if you subtract one, the space will still be on the last column of the line, causing the cursor to drop a line. The endl will do that again.
I was able to get results very close to what you're looking for with this:
cout << setfill('*') << setw(SCREEN_WIDTH) << "\n" << setfill(' ');
It's one asterisk short of a full line, but that's about the best you can do. If you know you will always run on the same console type with exactly SCREEN_WIDTH columns, you could use empty quotes instead of the "\n". But that's assuming a lot of the console.
Resulting code I used:
#include <iostream>
#include <iomanip>
using namespace std; // BLECH!!
int main()
{
const auto SCREEN_WIDTH = 80;
const auto COLLEGE = "Broome";
const auto COURSE = "CST 113 Y01";
const auto LAB_NAME = "LAB";
const auto PROGRAMMER_NAME = "Stan";
//Output the divider to the screen
cout << setfill('*') << setw(SCREEN_WIDTH) << "\n" << setfill(' ');
// Output the course heading to the screen
cout << setw((SCREEN_WIDTH + 11) / 2) << COLLEGE << endl;
cout << setw((SCREEN_WIDTH + 11) / 2) << COURSE << endl;
cout << setw((SCREEN_WIDTH + 5) / 2) << LAB_NAME << endl;
cout << setw((SCREEN_WIDTH + 15) / 2) << PROGRAMMER_NAME << endl;
//Output the divider to the screen
cout << setfill('*') << setw(SCREEN_WIDTH) << "\n" << setfill(' ');
}
Output:
*******************************************************************************
Broome
CST 113 Y01
LAB
Stan
*******************************************************************************

formatting vector output using iomanip

I'm having some trouble here. I have a file that looks like this (here's a snippet)
Sophia F 22158
Emma F 20791
Isabella F 18931
Jacob M 18899
Mason M 18856
Ethan M 17547
and I want to put each name, and the name's respective number into seperate vectors. For example, I would have 4 vectors:
1 for women's names and 1 for women's numbers, and the same for men's and men's numbers. (so 4 total)
I have this code, which will go through the file and pull out these elements and put them in vectors.
for (int i = 0; i < numTimes; i++) {
getline (inputFile, inputLine);
ss.str(inputLine); //ss is a string stream
ss >> name >> gender >> popularity;
if (gender == 'M') {
mNames[i] = name;
mFrequency[i] = popularity;
} else if (gender == 'F') {
fNames[i] = name;
fFrequency[i] = popularity;
}
ss.clear();
}
and I use this method to print it out:
cout << counter << " Most Popular Baby Names" << endl << endl;
cout << left << setw(15) << "Girls" ;
cout << right << setw(9) << "Frequency" <<" ";
cout << left << setw(15) << "Boys";
cout << right << setw(9) << "Frequency" << endl;
for (int i = 0; i < counter; i ++) {
cout << left << setw(15) << fNames[i] ;
cout << right << setw(9) << fFreq[i] <<" ";
cout << left << setw(15) << mNames[i];
cout << right << setw(9) << mFreq[i] << endl;
{
but then I get this output:
http://i.stack.imgur.com/2x0ta.png
But I would like for it to be like this:
http://i.stack.imgur.com/OSIX9.png
So I'm thinking I either need to go through before I print and remove all the whitespace/0's in these vectors, or I need to check while I'm printing out. Does anyone have any pointers?
Solved, thanks guys.
I used two separate while loops, one for each set of arrays. In between them I reset the ifstream back to the beginning. This way, it goes through until each vector has 5 non-zero elements.

How to display results in separate columns in C++

I'm writing a program for a number theory proof but I have very little experience in writing code.
What i want to do is display all the results of the formula:
Answer = sqrt [4*n]
where;
n = 1,2,3,4,5,6,7,...50
But I want to display the results in 2 groups of columns, i.e.,
I want the 1st column to be the 1st half of n. So as there are 50 iterations, the 1st column will contain the numbers 0 --> 25.
The 2nd column should display the first 25 Answers from the equation.
The 3rd column has the second half of n. i.e., The numbers 26-->50
The 4th column should display the results from the last 25 values of n.
An example of what I'm trying to display is below*:
*(ignore the dots in the below example, they are only there for display purposes only)
n:............Answer:............n:...........Answer:
So far i have the code working but I just can't figure out how to split and display the n-values and Answer-values as I have shown above.
All I can manage to do is display the values in only 2 columns as follows:
n:...........Answer:
This is what I've got so far:
#include <iostream>
#include <iomanip>
#include <cmath> //preprocesser directives
using namespace std; //avoids having to use std:: with cout/cin
int main (int argc, char* argv[])
{
int n;
float Ans;
cout << setw(4) << "n:" << "\t\t" << setw(4) << "Answer:" << "\n" << endl;
for (int n = 0; n<=50; n++)
{
Ans = sqrt ((4)*(n));
cout << setw(4) << n << "\t\t" << setprecision(4) << setw(4) << Ans << endl;
}
cout << "\n\nPress enter to end" << endl;
cin.get();
}
I really have no idea how to split it into 4 separate columns, but I know the \t function must have something to do with it!??
Any help is appreciated!
Thanks
Change your for loop to:
for (int n = 1; n<=25; n++)
{
Ans = sqrt ((4)*(n));
cout << setw(4) << n << "\t\t" << setprecision(4) << setw(4) << Ans << "\t\t";
Ans = sqrt ((4)*(n + 25));
cout << setw(4) << n + 25 << "\t\t" << setprecision(4) << setw(4) << Ans << endl;
}
Loop from 1 to 25 and in the loop body, calculate two results: the one for n and the one for n + 25.
Here is a very simple compilable and runnable example showing you the basic idea:
#include <iostream>
#include <math.h>
int main()
{
for (int n = 1; n <= 25; ++n)
{
std::cout << n << "\t" << sqrt(n) << "\t"
<< (n + 25) << "\t" << sqrt(n + 25) << "\n";
}
}
This may already be sufficient for your needs. However, notice that I've used tabulators. That's easily written but makes correct output depend on tab size, i.e. you may get incorrectly aligned columns on some displays or editors.
One solution for this problem would be to create HTML output, use the <table> element and let a web browser take care of displaying an actual table:
#include <iostream>
#include <math.h>
int main()
{
std::cout << "<table>\n"; // and other HTML stuff
for (int n = 1; n <= 25; ++n)
{
std::cout << "<tr>";
std::cout << "<td>" << n << "</td><td>" << sqrt(n) << "</td><td>"
<< (n + 25) << "</td><td>" << sqrt(n + 25);
std::cout << "</tr>\n";
}
std::cout << "</table>\n";
}
If you are on Windows, then compile this into, say, output.exe, and call it as follows to create an HTML file:
output.exe >output.html
If you want pure text output, things get harder. You'd have to calculate all results in advance, store them in a std::vector, convert each of them to std::strings, look at the strings' sizes, pick the longest, then output all items with appropriate padding spaces. In fact, you'd have to learn a lot of new things for that, which would probably result in one or two additional, more specific questions on Stack Overflow.
Edit: You are using setw(4). Actually, that's another reasonable solution to the problem if you are happy with a fixed width.
This solution solves your problem and has the advantage of solving similar problems where you have to output (x,y) pairs to a four column table. You aren't locked into inputs increasing 1,2,3 etc.
Add this to top of file, with other includes
#include <vector>
Add this to body
cout << setw(4) << "n:" << "\t\t" << setw(4) << "Answer:" << "\n" << endl;
std::vector<double> inputs;
std::vector<double> answers;
for (int n = 0; n<=50; n++){
inputs.push_back(n);
inputs.push_back(sqrt(4*n));
}
for (int n = 1; n<=25; n++){
cout << setw(4) << Inputs[n] << "\t\t" << setprecision(4) << setw(4) << Answers[n] << "\t\t" << setw(4) << Inputs[n+25] << "\t\t" << setprecision(4) << setw(4) << Answers[n+25] << endl;
}

Dynamic alignment issue

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;
}