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

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"

Related

Cpp/C++ Output allingment in one line from right AND left

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

How to repeat char input using setw and setfill? the first part repeats but the second doesn't

I need the following output by setw and setfill:
aaa______aaa (These underscores represent spacing)
(No spaces allowed in code)
Link also attached
#include<iostream>
#include<iomanip>
using namespace std;
int main()
{ char input=0;
cout << "Enter the desired character for pattern : "<<endl;
cin >> input;
cout << setw(3) << setfill(input) << input
<<setw(10) << setfill(' ') setw(2)
<< setfill(input)<< input<<endl;
}
By the above mentioned code I do not get my desired output. The setfill works for the first time and then doesnt work for spaces and the next repitition. Output by this code is:
aaaaaa
(No spaces are outputted)
If we consider the following code:
#include<iostream>
#include<iomanip>
using namespace std;
int main()
{
char input=0;
cout << "Enter the desired character for pattern : "<<endl;
cin >> input;
cout << setw(3) << setfill(input) << input
<<setw(10) << setfill(' ')
<< input << input <<input <<endl;
}
This works perfectly but I don't want to repeat input 3 times at the end by writing it three times, I want to use setfill. What to do?
The required output if input is *
You need to actually print something for the width and fill to be used:
#include <iomanip>
#include <iostream>
int main()
{
char input = 'a';
std::cout << std::setw(3) << std::setfill(input) << ""
<< std::setw(10) << std::setfill(' ') << ""
<< std::setw(2) << std::setfill(input) << ""
<< '\n';
}
aaa aa
Note that the empty string here counts as "something" to be formatted.
Your problem is in this line 2 of cout: <<setw(10) << setfill(' ') setw(2), notice that you are using two times setw() without printing anything to screen.
You can use something like this for second line:
<< setw(10) << setfill(' ') << "" << setw(3)
this make cout like:
cout << setw(3) << setfill(input) << input
<< setw(10) << setfill(' ') << "" << setw(3)
<< setfill(input) << input << endl;

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.

Having trouble with iomanip, columns not lining up the way I expect

finishing up a long project and the final step is to make sure my data lines up in the proper column. easy. Only I am having trouble with this and have been at it for longer than i wish to admit watching many videos and can't really grasp what the heck to do So here is a little snippet of the code that I'm having trouble with:
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
cout << "Student Grade Summary\n";
cout << "---------------------\n\n";
cout << "BIOLOGY CLASS\n\n";
cout << "Student Final Final Letter\n";
cout << "Name Exam Avg Grade\n";
cout << "----------------------------------------------------------------\n";
cout << "bill"<< " " << "joeyyyyyyy" << right << setw(23)
<< "89" << " " << "21.00" << " "
<< "43" << "\n";
cout << "Bob James" << right << setw(23)
<< "89" << " " << "21.00" << " "
<< "43" << "\n";
}
which works for the first entry but the bob james entry has the numbers all askew. I thought setw was supposed to allow you to ignore that? What am i missing?
Thanks
It doesn't work as you think. std::setw sets the width of the field only for the next insertion (i.e., it is not "sticky").
Try something like this instead:
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
cout << "Student Grade Summary\n";
cout << "---------------------\n\n";
cout << "BIOLOGY CLASS\n\n";
cout << left << setw(42) << "Student" // left is a sticky manipulator
<< setw(8) << "Final" << setw(6) << "Final"
<< "Letter" << "\n";
cout << setw(42) << "Name"
<< setw(8) << "Exam" << setw(6) << "Avg"
<< "Grade" << "\n";
cout << setw(62) << setfill('-') << "";
cout << setfill(' ') << "\n";
cout << setw(42) << "bill joeyyyyyyy"
<< setw(8) << "89" << setw(6) << "21.00"
<< "43" << "\n";
cout << setw(42) << "Bob James"
<< setw(8) << "89" << setw(6) << "21.00"
<< "43" << "\n";
}
Also related: What's the deal with setw()?
The manipulators << right << setw(23) are telling the ostream that you want
the string "89" set in the right-hand edge of a 23-character-wide field.
There is nothing to tell the ostream where you want that field to start,
however, except for the width of the strings that are output since the
last newline.
And << "bill"<< " " << "joeyyyyyyy" writes a lot more characters to the output
than << "Bob James" does, so the 23-character-wide field on the second line
starts quite a bit to the left of the same field on the first line.
Stream manipulators affect the next input/output value being streamed, and then some manipulators (including setw()) reset afterwards. So you need to set the width and alignment BEFORE you output a text string, not afterwards.
Try something more like this:
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
void outputStudent(const string &firstName, const string &lastName,
int finalExam, float finalAvg, int letterGrade)
{
cout << setw(40) << left << (firstName + " " + lastName) << " "
<< setw(6) << right << finalExam << " "
<< setw(6) << right << fixed << setprecision(2) << finalAvg << " "
<< setw(7) << right << letterGrade << "\n";
}
int main()
{
cout << "Student Grade Summary\n";
cout << "---------------------\n\n";
cout << "BIOLOGY CLASS\n\n";
cout << "Student Final Final Letter\n";
cout << "Name Exam Avg Grade\n";
cout << "--------------------------------------------------------------\n";
outputStudent("bill", "joeyyyyyyy", 89, 21.00, 43);
outputStudent("Bob", "James", 89, 21.00, 43);
cin.get();
return 0;
}
Output:
Student Grade Summary
---------------------
BIOLOGY CLASS
Student Final Final Letter
Name Exam Avg Grade
--------------------------------------------------------------
bill joeyyyyyyy 89 21.00 43
Bob James 89 21.00 43

Align cout format as table's columns

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