Align cout format as table's columns - c++

I'm pretty sure this is a simple question in regards to formatting but here's what I want to accomplish:
I want to output data onto the screen using cout. I want to output this in the form of a table format. What I mean by this is the columns and rows should be properly aligned. Example:
Test 1
Test2 2
Iamlongverylongblah 2
Etc 1
I am only concerned with the individual line so my line to output now (not working) is
cout << var1 << "\t\t" << var2 << endl;
Which gives me something like:
Test 1
Test2 2
Iamlongverylongblah 2
Etc 1

setw.
#include <iostream>
#include <iomanip>
using namespace std;
int main () {
cout << setw(21) << left << "Test" << 1 << endl;
cout << setw(21) << left << "Test2" << 2 << endl;
cout << setw(21) << left << "Iamlongverylongblah" << 2 << endl;
cout << setw(21) << left << "Etc" << 1 << endl;
return 0;
}

I advise using Boost Format. Use something like this:
cout << format("%|1$30| %2%") % var1 % var2;

You must find the length of the longest string in the first column. Then you need to output each string in the first column in a field with the length being that of that longest string. This necessarily means you can't write anything until you've read each and every string.

you can do it with
string str = "somthing";
printf ("%10s",str);
printf ("%10s\n",str);
printf ("%10s",str);
printf ("%10s\n",str);

Related

How can you use std::setw() with array output?

I am making a blackjack game in C++, and I am trying to print out the players and dealers cards in addition to their sums, capital and so on. However I'm running into an issue with std::setw() when printing out the vector of cards. Here is a code snippet:
int width = 18;
std::cout << std::left << std::setw(width) << "Your cards:";
std::cout << std::left << std::setw(width * 2) << "arr";
std::cout << std::left << std::setw(width) << "Dealers cards:";
std::cout << "arr2" << std::endl;
std::cout << std::left << std::setw(width) << "Your sum:";
std::cout << std::left << std::setw(width*2) << player.sum();
std::cout << std::left << std::setw(width) << "Dealers sum:";
std::cout << dealer.sum() << std::endl;
Where arr and arr2 is there should be number values like 5 2 6 1, but if I print each element separately the with alignment will break. I think for setw() to work it needs to be one block or string, or else the vertical alignment will mess up once the values change. I tried myString.push_back() for each vector value and then printing that, with no luck. I assume I need to find a way to print the string into one element.
This is what it should look like:
Your cards: 5 7 1 2 Dealers cards: 2 1 7 5
Your sum: 21 Dealers sum: 21
Your capital: 100 Dealers capital: 100
I have found a solution. You can use stringstream to add int values to a string with no errors in conversion, this is how I fixed my code:
#include <sstream>
std::stringstream playerCards{};
for (int i{}; i < player.cards.size(); i++) {
playerCards << player.cards[i] << " ";
}
int width = 18;
std::cout << std::left << std::setw(width) << "Your cards:";
std::cout << std::left << std::setw(width * 2) << playerCards.str();
This way the array will get put into a string and will count as one block, which is what I was looking for.

C++: setw() only working on first row, in loop

I am trying to parse through a text file and have it output the contents onto the console with formatting by using setw(). My problem is that only the first row is formatted correctly, with the rest defaulting back to the left.
while (test)
{
cout << setw(20) << right;
string menu;
price = 0;
getline(test, menu, ',');
test >> price;
cout << setw(20) << right << menu;;
if (price)
cout << right << setw(10) << price;
}
My goal is to get the output to align to the longest word (which is 20 spaces in length) on the right, but my output is ending up like this:
WordThatAlignsRight
notAligning
my longest sentence goal align
notAligning
I am wanting each sentence to right align 20 spaces throughout the loop. Any help is appreciated, thanks!
std::setw only works on the next element, after that there is no effect. For further information pls follow this link..
The code on the linked site will show you very clearly how std::setw works.
#include <sstream>
#include <iostream>
#include <iomanip>
int main()
{
std::cout << "no setw:" << 42 << '\n'
<< "setw(6):" << std::setw(6) << 42 << '\n'
<< "setw(6), several elements: " << 89 << std::setw(6) << 12 << 34 << '\n';
std::istringstream is("hello, world");
char arr[10];
is >> std::setw(6) >> arr;
std::cout << "Input from \"" << is.str() << "\" with setw(6) gave \""
<< arr << "\"\n";
}
Output:
no setw:42
setw(6): 42
setw(6), several elements: 89 1234
Input from "hello, world" with setw(6) gave "hello"

controlling the number of digits being displayed c++

I want to display the values (in hex) of these certain registers and counters but I want to limit the number of digits being displayed.
cout << "Acc register : " << hex << Acc << ","; //display 2 digits
cout << " X register : " << hex << X << ","; //display 3 digits
cout << " Program counter : " << hex << PC << ","; //display 3 digits
I also want to display preceding zeros if the value was only 1 digit long, for example if
program counter = 4
PC should display as Program counter : 004
I have searched the internet to try and find a solution but I can not seem to find something that works. Can anybody explain how to do this please. Many thanks.
The STL comes with a header called iomanip, which can modify in the way you want and even more.
A short example would be:
#include <iomanip>
#include <iostream>
int main() {
std::cout << std::setfill ('x');
std::cout << "PC" << std::setw(3) << 4 << std::endl;
}
An additional example can be found here:
http://www.cplusplus.com/reference/iomanip/setfill/
An overview over all options here:
http://www.cplusplus.com/reference/iomanip/

Working with GPS Output using C++

Hi I'm working with GPS output. To be more accurate I'm working using the $GPRMC output. Now the output that I get is in the following form:
$GPRMC,225446,A,4916.45 N,12311.12 W,000.5,054.7,191194,020.3 E,*68"
This output constitutes of time, lats, longs, speed in knots, info about course, date, magnetic variation and mandatory checksum.
The image that I have attached shows the current result I'm getting as I'm taking out the sub strings from the string.
Now I'm getting the time in the hhmmss format. I want it in hh:mm:ss format.
Plus I'm getting the longitude as 4916.45 N. I want to get it as 49 degrees 16' 45".
And the latitude as 123 degrees 11' 12". I'm a beginner so I really don't know how to convert the format. I have also attached my code below.
#include<iostream>
#include<string>
#include<sstream>
#include<stdio.h>
#include<conio.h>
using namespace std;
int main()
{
std::string input = "$GPRMC,225446,A,4916.45 N,12311.12 W,000.5,054.7,191194,020.3 E,*68";
std::istringstream ss(input);
std::string token;
string a[10];
int n = 0;
while (std::getline(ss, token, ','))
{
//std::cout << token << '\n';
a[n] = token;
n++;
}
cout << a[0] << endl << endl;
cout << "Time=" << a[1] << endl << endl;
cout << "Navigation receiver status:" << a[2] << endl << endl;
cout << "Latitude=" << a[3] << endl << endl;
cout << "Longitude=" << a[4] << endl << endl;
cout << "Speed over ground knots:" << a[5] << endl << endl;
cout << "Course made good,True:" << a[6] << endl << endl;
cout << "Date of Fix:" << a[7] << endl << endl;
cout << "Magnetic variation:" << a[8] << endl << endl;
cout << "Mandatory Checksum:" << a[9] << endl << endl;
_getch();
return 0;
}
First thing is that your NMEA sentence is wrong, there should be commas ',' before N and W, so you will actually have to parse "12311.12" and not "12311.12 W". You can check it on this site: http://aprs.gids.nl/nmea/#rmc, you should also always check checksum of sentence - for online checks use: http://www.hhhh.org/wiml/proj/nmeaxor.html.
To parse longitude and latitude I suggest regexps, I am notsaying this is regexp is correct - it only parses data you have provided:
#include <iostream>
#include <string>
#include <regex>
#include <iostream>
std::tuple<int,int,int> parseLonLat(const std::string& s) {
std::regex pattern("(\\d{2,3})(\\d+{2})\\.(\\d+{2})" );
// Matching single string
std::smatch sm;
if (std::regex_match(s, sm, pattern)) {
return std::make_tuple(std::stoi(sm[1]), std::stoi(sm[2]), std::stoi(sm[3]));
}
return std::make_tuple(-1,-1,-1);
}
int main (int argc, char** argv) {
auto loc1 = parseLonLat("4916.45");
std::cout << std::get<0>(loc1) << ", " << std::get<1>(loc1) << ", " << std::get<2>(loc1) << "\n";
// output: 49, 16, 45
auto loc2 = parseLonLat("12311.12");
std::cout << std::get<0>(loc2) << ", " << std::get<1>(loc2) << ", " << std::get<2>(loc2) << "\n";
// output: 123, 11, 12
}
http://coliru.stacked-crooked.com/a/ce6bdb1e551df8b5
You'll have to parse that yourself; there's no GPS parsing in standard C++.
You may want to write your own Angle class in order to have 49 degrees 16' 45" as possible output. You'll want to overload operator<< for that.

C++ user input manipulation

I am very new to C++ and appreciate all the help, so please be patient with me! I was tasked with writing a C++ program which essentially emulates a simple CPU.
My overall goal is to have the user input various 3 digit numbers into an array I have created called "memory". The array "memory" will have 100 available locations and the user is allowed to load their input into any available spots (the array is sized [100][2] because i want the last two digits to be treated as a single number).
The variable "programCounter" will represent the beginning location for where the user input will be stored within the array. So, for example, if the user inputs the value "20" for programCounter, then the user's input will be stored starting from the 21st location in the array and beyond, until their input is finished. What I have written below does not work and the loop for the user input into "memory" never ends. Is there another way to have the user input their values into the array, and then provide some sort of exit code to let the program know that the user is finished inputting?
Here is my code:
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
int main (void)
{
string name;
char inputCardResponse;
ifstream inFile;
ofstream outFile;
int memory [100][2] = {001}; // sets the value of the first memory spot to "001"
int inputCard [16][2];
int outputCard [16][2];
int instructionRegister;
double accumulator;
int programCounter;
cout << "Hello! Welcome to Simple Computer Version 1.0.\nWhat is your name? \n";
getline(cin, name);
cout << "Thank you for using my Simple Comuter "<<name<<"!\n";
cout << "Let's get started!\n";
cout << "Below is the table of Opcodes and their functions:";
cout << endl << endl;
{
cout << setw(9) << "| Opcode" << setw(20) << setfill('-') << "Function" << setw(12) << "|" << endl;
cout << setw(9) << "| ------" << setw(20) << setfill(' ') << "-------" << setw(12) << "|" << endl;
cout << setw(5) << "| 0_ _" << setw(20) << setfill('-') << "Input" << setw(14) << "|" << endl;
cout << setw(5) << "| 1_ _" << setw(21) << setfill('-') << "Output" << setw(13) << "|" << endl;
cout << setw(5) << "| 2_ _" << setw(18) << setfill('-') << "Add" << setw(16) << "|" << endl;
cout << setw(5) << "| 3_ _" << setw(23) << setfill('-') << "Subtract" << setw(11) << "|" << endl;
cout << setw(5) << "| 4_ _" << setw(22) << setfill('-') << "Load AC" << setw(12) << "|" << endl;
cout << setw(5) << "| 5_ _" << setw(23) << setfill('-') << "Store AC" << setw(11) << "|" << endl;
cout << setw(5) << "| 6_ _" << setw(19) << setfill('-') << "Jump" << setw(15) << "|" << endl;
cout << setw(5) << "| 7_ _" << setw(22) << setfill('-') << "Test AC" << setw(12) << "|" << endl;
cout << setw(5) << "| 8_ _" << setw(23) << setfill('-') << "Shift AC" << setw(11) << "|" << endl;
cout << setw(5) << "| 9_ _" << setw(19) << setfill('-') << "Halt" << setw(15) << "|" << endl;
}
cout << endl << endl;
//Input section
cout << "Please plan your program out. This emulator requires the user to enter a starting value";
cout << "for the program counter (typically cell 20 is chosen)\n";
cout << "When you are ready, please enter the starting cell you have chosen for the program counter: ";
cin >> programCounter; // Initializes the program counter value
cout << "Now that you have chosen a starting cell, please start entering your program: \n";
// This loop stores the user's program into the array named "memory". What happens if input<100??
for(;programCounter < 100; programCounter++)
{
cin >> memory[programCounter][2];
}
cout << "Do you have any information to store in the input card?\n";
cout << "(Please input uppercase Y for Yes or N for No \n";
cin.get(inputCardResponse);
if(inputCardResponse == 'Y')
{
cout << "There are 15 input slots available. Please keep this in mind when inputting: \n";
for (int inputCounter=0; inputCounter < 15; inputCounter++)
{
cin >> inputCard[inputCounter][2];
}
}
else{
cout << "Most programs require inputs.\n";
cout << "Please come back when you are ready with a file!\n";
}
return 0;
}
C/C++ arrays are 0-indexed. So if you have array, your indexes will be from 0 to (array size-1)
int a[5]; //You initialized array of 5 integers. You can only access this elements: a[0], a[1], a[2], a[3], a[4]
You are accessing an element out of bounds.
In these lines:
cin >> memory[programCounter][2];
cin >> inputCard[inputCounter][2];
Change 2 to 0 or 1, so you don't access element which is out of bounds.
Also, you don't have any variable which represents you the limit of input. Your limit is 100 so if you input a small number it will require lot of input numbers from you, so maybe that's why you think it will never stop input (but it actually will when it reaches 100). You should make a variable which represents you a limit of input, so you don't have this:
for(;programCounter < 100; programCounter++)
{
cin >> memory[programCounter][2];
}
but this:
for(;programCounter < inputLimit; programCounter++)
{
cin >> memory[programCounter][2];
}
Hope this helps!
This answer will not solve your problem but will get you on the path. Also, this is a response to the following comment:
#crayzeewulf - the user will input a 3 digit number (such as 345). The first
digit "3" will represent an opcode and the remaining digits "45" will represent
either the value to be manipulated, or the location of a spot in the array
"memory". That's why I was thinking of making the array have 100 rows and 2
columns. Is there another way to accomplish this? Thank you!
I now see what you meant in your original question. However, assigning values to or reading values via the >> operator into variables does not work the way you might be expecting. When you declare an array like the following:
int memory[100][2] ;
you are allocating space for 200 integers that you can imagine being arranged in a table with 100 rows and 2 columns. The first row has index 0 and first column has index 0. The last row has an index 99 and last column has index 1:
+------------+------------+
| Column 0 | Column 1 |
+------------+------------+
Row 0 | | |
+------------+------------+
Row 1 | | |
+------------+------------+
...
+------------+------------+
Row 99 | | |
+------------+------------+
Each cell in this table may only store an int value. When you initialize memory[][] using a statement such as the following (I am using 123 instead of 001 for a reason, see more comments later):
int memory[100][2] = {123} ;
the program simply puts the integer 123 in column 0 of row 0:
+------------+------------+
| Column 0 | Column 1 |
+------------+------------+
Row 0 | 123 | 0 |
+------------+------------+
Row 1 | 0 | 0 |
+------------+------------+
...
+------------+------------+
Row 99 | 0 | 0 |
+------------+------------+
The compiler or resulting program has no way of knowing that the number needs to be split into 1 and 23. It does not put 1 in column 0 and 23 in column 1 of the first row, for example. You will have to figure out a way to do this yourselves.
Going back to your original code, it used a value of 001 to initialize the array:
int memory[100][2] = {001} ;
C++ treats integer literals that start with 0 very differently. A leading 0 in literals causes C/C++ compilers to treat them as octal values. So, be very careful when you write literals that have leading zeroes. For example 012 is not equal to 12 in C++.
Finally, if you try to put something in column 2 of this table you are asking for a lot of trouble. The table only contains columns 0 and 1. When you try to place values into the non-existing column 2, the values may end up at unexpected locations in the memory being used by your program. The behavior of the program is unpredictable in this case and will most likely be entirely different from what you expected.
As you are trying to learn C++, I would suggest you read about how arrays and variables work from one or more of the books listed here. Once you have a better handle on the basic concepts, a great way to learn more advanced and application-specific concepts is to look at existing code that does something similar. If you search for similar codes on Google or StackOverflow, you will find several ways of approaching this assignment. Carefully study the codes that you find, make sure you understand them, run them, tweak them if you can and see what happens, etc. Now that you are armed with this additional knowledge, write your own code from scratch. Hope that gets you the answer. I also highly recommend following the suggestions of this answer before you ask your question on SO. :) Cheers!