0

I am trying to print the values within a structure as a table. However, one of the names gets printed out into the wrong 'field'.

Here is what I have:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

struct SPlayer {
    string name;
    string team;
    int goalsScored;
    int yellowcards;
    int redcards;
};

void PrintHeader() {
    cout << "name\t\tteam\tgoals\tyellow cards\tred cards\n";
    cout << "--------------------------------------------------------------------" << endl;
}

void PrintTable(SPlayer table) {
    cout << table.name << "\t\t" << table.team << "\t" << table.goalsScored << "\t" << table.yellowcards << "\t\t" << table.redcards << endl;
}

int main()
{
    SPlayer mitchell = { "Mitchell" , "Red" , 4 , 1 , 0 };
    SPlayer smith = { "Smith" , "Blue" , 8 , 0 , 0 };
    SPlayer white = { "White" , "Green" , 0 , 2 , 4 };
    SPlayer doe = { "Doe" , "Yellow" , 2 , 1 , 0 };

    vector<SPlayer> players;
    players.push_back(mitchell);
    players.push_back(smith);
    players.push_back(white);
    players.push_back(doe);
    
    PrintHeader();

    for (int i = 0; i < players.size(); i++) {
        PrintTable(players.at(i));
    }
}

When you run the code, it looks like this:

terminal showing the values within a structure printed as a table

Does anyone know how to fix this?

2
  • 2
    Small note: PrintTable is a weird name for a function that prints a single SPlayer. A single player is not a table. Commented Apr 12, 2024 at 21:57
  • 1
    Just to add some context on why the tab character is the wrong thing. The name Mitchell is long enough that tabbing out does exactly what you're seeing. Try very short names as well. And longer names will also be bad. It's very verbose, but I've taken to putting my table column widths into an enum and then using those. Commented Apr 12, 2024 at 21:58

1 Answer 1

4

Do not use \t characters to format your table columns. It moves the cursor to the next even multiple of the console's tab spacing, which in your case appears to be 8 characters.

Mitchell is already 8 characters long, so the following \t moves the cursor to position 16, and the next \t moves it to position 24. So you output Red in the wrong place.

Whereas Smith is only 5 characters, so the following \t moves the cursor to position 8, and the next \t moved it to position 16. So you output Blue in the expected place.

And so on.

If either the player name or team name exceeds the tab spacing, your table formatting gets messed up, which is exactly what you see happening in your screenshot:

tab spaces

Instead, you should use the std::setw() stream manipulator to specify the exact sizes of your columns. That will reserve space that cout can then fill in with your string values, eg:

...
#include <iomanip>
...

void PrintHeader() {
    cout << left;
    cout << setw(16) << "name"
         << setw(8)  << "team"
         << setw(8)  << "goals"
         << setw(16) << "yellow cards"
         << setw(20) << "red cards"
         << '\n';
    cout << "--------------------------------------------------------------------" << endl;
}

void PrintTable(const SPlayer &table) {
    cout << left;
    cout << setw(16) << table.name
         << setw(8)  << table.team
         << setw(8)  << table.goalsScored
         << setw(16) << table.yellowcards
         << setw(20) << table.redcards
         << '\n';
}

Online Demo

reserved sizes

Just be sure to use column sizes that are large enough to accommodate each column's longest string value.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you so much! This is exactly what I was trying to do :)
Though nothing stops a player or team name (being a std::string from being more than 16 or 8 characters. It may be advisable to scan over the table and calculate the max width and then format accordingly.
@Chris yup, which is exactly what the cppreference example for std::ios_base::width does.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.