How to show the elements of a stl list of structures?

2

I am beginning to get a little familiar with the stl and my problem is as follows. In all the tutos they tell you the functions, like adding elements and showing them, traversing them, etc. I have this structure:

struct Libro{
string nombre;
int codigo;
bool disp;
};

and this list list <Libro> libro

With this function I add books to the list:

Libro insertarlibro(){
    string nombre;
    int codigo;
    bool disp=true;
    cout<<"\nIngrese el nombre del libro: ";
    getline(cin,nombre);
    cout<<"\nIngrese el codigo: ";
    cin>>codigo;
    return{nombre,codigo,disp};
}

from the main

libro.push_back(insertarlibro())

and it is assumed that books are shown with this function:

void mostrarlibros( list<Libro> & sList )
{
    list<Libro>::iterator pos;
    pos = sList.begin();
    while( pos != sList.end())
    {
        cout<<*pos<<endl;
        pos++;
     }
}

But obviously, if the structure I have consists of three data name, code and availability, *pos will not show the 3, then I want to know what to put in cout<< to be able to show the name, code and disp of each book added. I have searched a lot and I do not get a guide on how to show the elements of an aggregate structure in a container in this case the list

    
asked by Marcel Salazar 30.07.2018 в 16:00
source

1 answer

2

This function trusts that the data passed to std::cout has overloaded the data injection operator ( operator << ).

It is very easy to overload said operator:

std::ostream &operator<<(std::ostream &o, const Libro &l)
{
    return o << l.nombre << ' ' << l.codigo << ' ' << l.disp;
}

The data flow is a generic output stream ( std::ostream ) so you're going to be able to send data of type Libro to any output flow ( std::cout or a file, for example).

Other things to consider.

Your book sample function is semantically incorrect; since you intend to show the data of a container, it is assumed that you do not intend to modify the container, so the parameter should be constant:

void mostrarlibros( const list<Libro> & sList )
//                  ~~~~~ <--- La lista es de solo lectura

On the other hand, the loops for and while are easily interchangeable, so it would be indifferent to use one or the other; but in general a guide is followed to know which one to choose:

  • If you know how many iterations will be necessary: the for loop is used.
  • If you do not know the iterations that will be necessary: the while loop is used.

In your case, what you would expect is a for loop:

void mostrarlibros( const list<Libro> & sList )
//                  ~~~~~ <--- La lista es de solo lectura
{
    for (auto b = sList.begin(), e = sList.end(); b != e; ++b)
//                      ~~~~~              ~~~
//  iteramos tantas veces como elementos existan entre begin y end
    {
        cout<<*b<<endl;
    }
}

But this type of loops are cumbersome and uncomfortable, the usual thing when going through data collections is to use the for range loop:

void mostrarlibros( const list<Libro> & sList )
//                  ~~~~~ <--- La lista es de solo lectura
{
    for (const auto &libro : sList)
//                   ~~~~~~~~~~~~~ <--- por cada Libro en sList...
    {
        cout<<libro<<'\n';
    }
}

I have replaced the std::endl with '\n' since it is usually a better idea, see this thread for know why.

    
answered by 30.07.2018 / 16:03
source