Home > Net >  Finding the max lengths of strings to format a table output
Finding the max lengths of strings to format a table output

Time:01-26

I want to find the max length of specific attributes from a vector of Person objects.

Below is an example of a Person object:

Person::Person(string first_name, string last_name, int the_age){
     first = first_name;
     last = last_name;
     age = the_age;
} 

I have a vector that stores Person objects, and I must print all the people out in a table, like so:

First Name  Last Name     Age
----------  ------------  ----
John        Cool-Johnson  15
Paul        Bob           1000
2 people

I need to find the max length of each attribute of a Person in order to grow each column according to the maximum length of name or age. How can I do this?

So far, I have tried lambdas using this code:

unsigned int max_name = *max_element(generate(people.begin(),people.end(), [](Person a){return a.getFirstName()})).size();

But I am not sure if this even works at all.

I must use <iomanip>, but I have no clue how it works.

Is there a better way?

CodePudding user response:

Your use of std::max_element() is wrong. It takes 2 iterators for input, which you are not providing to it. It would need to look more like this:

auto max_name = max_element(
    people.begin(), people.end(),
    [](const Person &a, const Person &b){
        return a.getFirstName().size() < b.getFirstName().size();
    }
)->getFirstName().size();

Online Demo

Alternatively:

vector<string> names;
names.reserve(people.size());

for(const Person &p : people) {
    names.push_back(p.getFirstName());
}

auto max_name = max_element(
    names.begin(), names.end(),
    [](const string &a, const string &b){
        return a.size() < b.size();
    }
)->size();

Online Demo

However, since you will probably also want to do the same thing for the Last Name and Age columns, I would suggest simply looping though the people vector manually, keeping track of the max lengths as you go along, eg:

string::size_type max_fname = 10;
string::size_type max_lname = 9;
string::size_type max_age = 3;

for(const Person &p : people)
{
    max_fname = max(max_fname, p.getFirstName().size());
    max_lname = max(max_lname, p.getLastName().size());
    max_age = max(max_age, to_string(p.getAge()).size());
}

Then you can output everything in a table, eg:

cout << left << setfill(' ');
cout << setw(max_fname) << "First Name" << "  " << setw(max_lname) << "Last Name" << "  " << setw(max_age) << "Age" << "\n";
cout << setfill('-');
cout << setw(max_fname) << "" << "  " << setw(max_lname) << "" << "  " << setw(max_age) << "" << "\n";
cout << setfill(' ');

for(const Person &p : people)
{
    cout << setw(max_fname) << p.getFirstName() << "  " << setw(max_lname) << p.getLastName() << "  " << setw(max_age) << p.getAge() << "\n";
}

cout << people.size() << " people\n";

Online Demo

  •  Tags:  
  • Related