1

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

Tyler Kelly
  • 564
  • 5
  • 23

3 Answers3

2

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()?

Community
  • 1
  • 1
vsoftco
  • 55,410
  • 12
  • 139
  • 252
  • aww this works when the name is one string but not if the two are separated. in my actual program I have to get those values and then pump them out, I suppose I could create a new string to hold those two. Is there any way to make sure that '<< "bill"<< " " << "joelyyyyyyyyyyyy"' stays as one when using setw? – Tyler Kelly Apr 07 '15 at 23:02
  • 1
    It's better to concatenate the names, otherwise it's hard to guess what to put for `setw`, since it will depend on the length of the first name. If your names are `std::string` (you should avoid `char*`), then it's a breeze, use the `+` operator to concatenate them when displaying, like `cout << s1 + s2` – vsoftco Apr 07 '15 at 23:04
  • ok yeah I was doing that method earlier but it threw the last name really far away so I didnt try it again , but thank you for the help! I realize what to do now! – Tyler Kelly Apr 07 '15 at 23:06
  • @user3470987 see the updated edit, once you know the desired width of the fields, can use them after – vsoftco Apr 07 '15 at 23:13
  • is setw smarter/quicker to use than hard coding space key? – Tyler Kelly Apr 07 '15 at 23:17
  • @user3470987 it is, since you can then reuse the spacing, and also makes your code much more compact. – vsoftco Apr 07 '15 at 23:19
1

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.

David K
  • 3,147
  • 2
  • 13
  • 19
  • so how do i ensure that no matter the length of the names, the 89 will show up where it needs to be? which is on the final exam spot. keeping in mind that the names are changing in my actual program, I cannot just hardcode the setw in there – Tyler Kelly Apr 07 '15 at 22:58
  • 2
    set the width and alignment BEFORE you output the text that needs to be constrained/aligned. You are doing it afterwards instead, which is too late. – Remy Lebeau Apr 07 '15 at 22:59
  • Usually when I want to use setw to line things up in columns, I insert a setw before each and every string or number that I write to the stream (except for literal strings that insert blanks and separators in the output, because then the name of the literal string defines the width in which it will display). – David K Apr 08 '15 at 00:55
1

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
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770