Usando cadenas, vectores y estructuras con la STL

La STL (Standard Template Library) http://www.sgi.com/tech/stl/ es una de las grandes ventajas que C++ tiene con respecto a C.

Invertir una cadena en C++ es algo muy simple; sólo hay que recorrer cada uno de los elementos del vector desde el último hasta el primero.

El código podría ser el siguiente:


#include <iostream>
#include <string>

using namespace std;

int main()
{
    string cadena = "Hola mundo!";
    string aux_cadena = "";

    for (int i = cadena.size(); i >=0 ; i--)
         aux_cadena += cadena[i];

    cout<<"El texto normal es: "<<cadena<<endl;
    cout<<"El texto invertido es: "<<aux_cadena<<endl;
    return 0;
}
&#91;/sourcecode&#93;

Entre otras cosas, la STL contiene muchos algoritmos ya programados que podemos usar y que nos facilitan mucho trabajo.

Como ejemplo, a continuación muestro como podríamos hacer un programa para invertir una cadena usando la STL, para ello utilizaremos el algoritmo "reverse". Para utilizar los algoritmos de la STL, debemos poner #include &lt;algorithm&gt; en nuestro programa.

&#91;sourcecode language='cpp'&#93;

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

int main()
{
    string cadena = "Hola mundo!";
    string aux_cadena(cadena.begin(), cadena.end());
    reverse(aux_cadena.begin(), aux_cadena.end());

    cout<<"El texto normal es: "<<cadena<<endl;
    cout<<"El texto invertido es: "<<aux_cadena<<endl;
    return 0;
}
&#91;/sourcecode&#93;

Con la STL también podemos crear arreglos (vectores) sin indicar su tamaño, esto es útil porque probablemente no sepamos de antemano el número de elementos que vaya a contener el arreglo y queremos ir agregando elementos en tiempo de ejecución.
Para usar vectores debemos poner #include &lt;vector&gt; en nuestro programa.

El siguiente programa pide al usuario que introduzca números y los va almacenando en un vector, el programa termina cuando el usuario introduce el número cero.
Al final se recorre el vector y se muestran los números que el usuario introdujo.

&#91;sourcecode language='cpp'&#93;
#include <iostream>
#include <vector>

using namespace std;

int main()
{
    int i_numero=1;
    vector<int> v_enteros;
    vector<int>::iterator v_enteros_it;

    cout << "Teclee un número, (0 para terminar):" << endl;
    // Mientras el usuario teclee números diferentes de cero, guardamos en el vector los números que el usuario va tecleando
    while (i_numero != 0)
          {
              cin >> i_numero;
              if (i_numero != 0)
                  v_enteros.push_back(i_numero);
          }

    cout << endl << "Estos son los números que Ud. introdujo:" << endl;
    // Muestra los valores de los enteros almacenados en el vector
    for ( v_enteros_it = v_enteros.begin(); v_enteros_it != v_enteros.end(); v_enteros_it++)
         cout << *v_enteros_it << endl;        

    return 0;
}
&#91;/sourcecode&#93;

La forma adecuada de recorrer un vector es utilizando un iterador, tal y como se muestra en el programa anterior, aunque podemos recorrerlo como si se tratase de un arreglo.
El programa anterior modificado para no usar un iterador quedaría asi:

&#91;sourcecode language='cpp'&#93;
#include <iostream>
#include <vector>

using namespace std;

int main()
{
    int i_numero=1;
    vector<int> v_enteros;    

    cout << "Teclee un número, (0 para terminar):" << endl;
    // Mientras el usuario teclee números diferentes de cero, guardamos en el vector los números que el usuario va tecleando
    while (i_numero != 0)
          {
              cin >> i_numero;
              if (i_numero != 0)
                  v_enteros.push_back(i_numero);
          }

    cout << endl << "Estos son los números que Ud. introdujo:" << endl;
    // Muestra los valores de los enteros almacenados en el vector
    for (unsigned int i = 0; i < v_enteros.size(); i++)
         cout << v_enteros&#91;i&#93; << endl;

    return 0;
}
&#91;/sourcecode&#93;

<strong>Vector de objetos</strong>

Podemos crear también vectores de objetos, como ejemplo utilizaremos una clase muy sencilla que podría ser utilizada para guardar información de los diferentes departamentos en una empresa.
En el archivo de cabecera (el archivo .hpp) pondríamos algo como lo siguiente:


class Departamento
{
public:

Departamento(string, string, double); // constructor con parámetros para inicialización
Departamento();                 // constructor
~Departamento();                // destructor

void asignarID(string);
string obtenerID();
void asignarNombre(string);
string obtenerNombre();
void asignarPresupuesto(double);
double obtenerPresupuesto();

private:

string str_id;
string str_nombre;
double dbl_presupuesto;
};

El archivo que contendrá la implementación de los métodos (el archivo .cpp) podría contener un código como el mostrado a continuación:

//=============== CLASE Departamento ===============

void Departamento::asignarID(string id)
{
    str_id = id;
};

string Departamento::obtenerID()
{
    return str_id;
};

void Departamento::asignarNombre(string nombre)
{
    str_nombre = nombre;
};

string Departamento::obtenerNombre()
{
    return str_nombre;
};

void Departamento::asignarPresupuesto(double presupuesto)
{
    dbl_presupuesto = presupuesto;
};

double Departamento::obtenerPresupuesto()
{
    return dbl_presupuesto;
};

//--------------------------------------------------------------------------
// Constructor con parámetros para inicialización
Departamento::Departamento(string id_depto, string nombre_depto, double presupuesto)
{
 str_id = id_depto;
 str_nombre = nombre_depto;
 dbl_presupuesto = presupuesto;
}

//--------------------------------------------------------------------------
// Constructor vacío (default)
Departamento::Departamento()
{ }

//--------------------------------------------------------------------------
// Destructor
Departamento::~Departamento()
{ }

En un programa en el que quisiéramos crear objetos de la clase Departamento, deberíamos hacer el include del archivo .hpp que contiene la definición de la clase y para hacer un vector con objetos de esa clase, debemos hacer también #include <vector>.
Podríamos usar un código como el siguiente para crear un vector con 3 objetos de la clase Departamento:

vector<Departamento> v_deptos;

// Objeto de la clase Departamento
Departamento aux_depto;

// Variables auxiliares para capturar departamento
string aux_iddepto="";
string aux_nombredepto="";
double aux_presupuesto=0;

// Capturamos 3 departamentos y los agregamos al vector v_deptos
    for (int i = 0; i < 3; i++)
        {
            cout << "ID departamento " << i+1 << " : ";
            cin >> aux_iddepto;
            cout << "Nombre departamento " << i+1 << " : ";
            cin >> aux_nombredepto;
            cout << "Presupuesto departamento " << i+1 << " : ";
            cin >> aux_presupuesto;

            aux_depto.asignarID(aux_iddepto);
            aux_depto.asignarNombre(aux_nombredepto);
            aux_depto.asignarPresupuesto(aux_presupuesto);
            v_deptos.push_back(aux_depto);
        }

Para mostrar en pantalla los datos de todos los objetos almacenados en el vector podemos hacer una función que reciba como parámetro el vector:

//--------------------------------------------------------------------------
// Muestra los valores de los objetos almacenados en el vector de departamentos
void MuestraVectorDeptos(vector<Departamento> &tmp_deptos)
{
    vector<Departamento>::iterator tmp_iterator;

    cout << "****** Vector de departamentos ******" << endl;
    for ( tmp_iterator = tmp_deptos.begin(); tmp_iterator != tmp_deptos.end(); tmp_iterator++)
        {
         cout << "ID departamento: " << tmp_iterator->obtenerID() << "\t";
         cout << "Nombre departamento: " << tmp_iterator->obtenerNombre() << "\t";
         cout << "Presupuesto departamento: " << tmp_iterator->obtenerPresupuesto() << endl;
        }
    cout << "Total de Departamentos: " << tmp_deptos.size() << endl;
    cout << endl;
}
&#91;/sourcecode&#93;

<strong>Estructuras con campos tipo vector</strong>

Podemos crear estructuras que contengan algún campo de tipo vector.
Para entenderlo mejor, imaginemos que deseamos tener almacenados en un vector los datos de todos los departamentos de la empresa (para lo cual utilizaremos el código anterior), pero además queremos tener en otro vector, los datos de los empleados de la empresa y saber a que departamento pertenece cada empleado.
Además queremos poder obtener de una forma sencilla, un listado de los departamentos indicando que empleados están asignados a cada departamento.

Utilizaremos la clase Departamento que ya definimos y crearemos otra clase llamada Empleado.

Pondré en un archivo llamado cl_empresa.hpp la definición de las clases (Departamento y Empleado)


/* Archivo: cl_empresa.hpp            */

#include <string>

using namespace std;

//--------------------------------------------------------------------------
// Clase Departamento
class Departamento
{
    public:

     Departamento(string, string, double); // constructor con parámetros para inicialización
     Departamento();                 // constructor
     ~Departamento();                // destructor

     void asignarID(string);
     string obtenerID();
     void asignarNombre(string);
     string obtenerNombre();
     void asignarPresupuesto(double);
     double obtenerPresupuesto();

    private:

     string str_id;
     string str_nombre;
     double dbl_presupuesto;
};

//--------------------------------------------------------------------------
// Clase Empleado
class Empleado
{
    public:

     Empleado(int, string, double, string); // constructor con parámetros para inicialización
     Empleado();                 // constructor
     ~Empleado();                // destructor

     void asignarNumero(int);
     int obtenerNumero();
     void asignarNombre(string);
     string obtenerNombre();
     void asignarSueldo(double);
     double obtenerSueldo();
     void asignarIDdepa(string);
     string obtenerIDdepa();

    private:

     int i_numemp;
     string str_nombre;
     double dbl_sueldo;
     string str_iddepa;
};

La implementación de los métodos así como los constructuroes, etc. de ambas clases los pondré en un archivo cl_empresa.cpp

/* Archivo: cl_empresa.cpp            */

#include <string>
#include "cl_empresa.hpp"

//=============== CLASE Departamento ===============

void Departamento::asignarID(string id)
{
    str_id = id;
};

string Departamento::obtenerID()
{
    return str_id;
};

void Departamento::asignarNombre(string nombre)
{
    str_nombre = nombre;
};

string Departamento::obtenerNombre()
{
    return str_nombre;
};

void Departamento::asignarPresupuesto(double presupuesto)
{
    dbl_presupuesto = presupuesto;
};

double Departamento::obtenerPresupuesto()
{
    return dbl_presupuesto;
};

//--------------------------------------------------------------------------
// Constructor con parámetros para inicialización
Departamento::Departamento(string id_depto, string nombre_depto, double presupuesto)
{
 str_id = id_depto;
 str_nombre = nombre_depto;
 dbl_presupuesto = presupuesto;
}

//--------------------------------------------------------------------------
// Constructor vacío (default)
Departamento::Departamento()
{ }

//--------------------------------------------------------------------------
// Destructor
Departamento::~Departamento()
{ }

//=============== CLASE Empleado ===============

void Empleado::asignarNumero(int numero)
{
    i_numemp = numero;
};

int Empleado::obtenerNumero()
{
    return i_numemp;
};

void Empleado::asignarNombre(string nombre)
{
    str_nombre = nombre;
};

string Empleado::obtenerNombre()
{
    return str_nombre;
};

void Empleado::asignarSueldo(double sueldo)
{
    dbl_sueldo = sueldo;
};

double Empleado::obtenerSueldo()
{
    return dbl_sueldo;
};

void Empleado::asignarIDdepa(string id)
{
    str_iddepa = id;
};

string Empleado::obtenerIDdepa()
{
    return str_iddepa;
};

//--------------------------------------------------------------------------
// Constructor con parámetros para inicialización
Empleado::Empleado(int nempleado, string nombre_emp, double sueldo, string departamento)
{
 i_numemp = nempleado;
 str_nombre = nombre_emp;
 dbl_sueldo = sueldo;
 str_iddepa = departamento;
}

//--------------------------------------------------------------------------
// Constructor vacío (default)
Empleado::Empleado()
{ }

//--------------------------------------------------------------------------
// Destructor
Empleado::~Empleado()
{ }

Necesitaremos una estructura con 2 campos, uno para guardar el identificador del departamento y el otro será un vector que contendrá los números de empleado de todos los empleados que pertenezcan al departamento.

typedef struct empleadosxdepto_s
{
 string str_iddepto;
 vector<int> v_numerosemp;
} empleadosxdepto_t;

El programa principal contendrá una lista (en lugar de un vector) en donde almacenaremos las estructuras correspondientes a cada departamento.

Crearemos una función que nos permita agregar un empleado a un departamento; la función recibirá el código de departamento, el número de empleado y la lista que contiene las estructuras del tipo empleadosxdepto_t. Primero buscará en la lista de estructuras la que corresponda al código de departamento que recibe como parámetro, si la encuentra agrega al vector v_numerosemp de dicha estructura el número de empleado que recibe como parámetro, si no la encuentra, agrega primero la estructura y después el número de empleado a su vector v_numerosemp.

También agregamos una función para mostrar la información de la lista de estructuras.

El programa principal quedaría como sigue:

/* Archivo: empresa.cpp               */

#include <iostream>
#include <string>
#include <vector>
#include
	<list>
#include "cl_empresa.hpp"

using namespace std;

typedef struct empleadosxdepto_s
{
 string str_iddepto;
 vector<int> v_numerosemp; 
} empleadosxdepto_t;

//--------------------------------------------------------------------------
/* Agrega un empleado al vector que contiene los empleados de un departamento determinado
   Recibe como parámetros el código del departamento, el número de empleado,
   y la lista de empleados por departamento (en donde se va a insertar el número de empleado)
*/
void AgregaEmpleado(string id_depart, int i_empleado, list<empleadosxdepto_t> &lista)
{
    bool bl_encontrado = false;
    list<empleadosxdepto_t>::iterator tmp_iterator;
    /* Creamos una estructura auxiliar de tipo empleadosxdepto_t para almacenar los datos antes de agregar
       la estructura a la lista
    */
    empleadosxdepto_t tmp_sempleados;

    /* Busca en la lista el código de departamento que recibe como parámetro.
       Si lo encuentra, agrega el número de empleado que recibe como parámetro al vector de empleados que le corresponde a dicho departamento
       Si no lo encuentra, primero agrega el departamento y despues el número de empleado a su vector de empleados correspondiente
    */
    for ( tmp_iterator = lista.begin(); tmp_iterator != lista.end(); tmp_iterator++)
        { 
            if( (*tmp_iterator).str_iddepto == id_depart)
              {                  
                (*tmp_iterator).v_numerosemp.push_back(i_empleado);
                bl_encontrado = true;
                break;
              } /* if */
        } /* for */

    if (!bl_encontrado)
       {
           tmp_sempleados.str_iddepto = id_depart;
           tmp_sempleados.v_numerosemp.push_back(i_empleado);
           lista.push_back(tmp_sempleados);
       } /* if */       
}

//--------------------------------------------------------------------------
// Muestra los valores de los objetos almacenados en el vector de departamentos
void MuestraVectorDeptos(vector<Departamento> &tmp_deptos)
{
    vector<Departamento>::iterator tmp_iterator;

    cout << "****** Vector de departamentos ******" << endl;
    for ( tmp_iterator = tmp_deptos.begin(); tmp_iterator != tmp_deptos.end(); tmp_iterator++)
        { 
         cout << "ID departamento: " << tmp_iterator->obtenerID() << "\t";
         cout << "Nombre departamento: " << tmp_iterator->obtenerNombre() << "\t";
         cout << "Presupuesto departamento: " << tmp_iterator->obtenerPresupuesto() << endl;
        } 
    cout << "Total de Departamentos: " << tmp_deptos.size() << endl;
    cout << endl;
}

//--------------------------------------------------------------------------
// Muestra los valores de los objetos almacenados en el vector de empleados
void MuestraVectorEmps(vector<Empleado> &tmp_emps)
{
    vector<Empleado>::iterator tmp_iterator;

    cout << "****** Vector de empleados ******" << endl;
    for ( tmp_iterator = tmp_emps.begin(); tmp_iterator != tmp_emps.end(); tmp_iterator++)
        { 
         cout << "Número empleado: " << tmp_iterator->obtenerNumero() << "\t";
         cout << "Nombre empleado: " << tmp_iterator->obtenerNombre() << "\t";
         cout << "Sueldo empleado: " << tmp_iterator->obtenerSueldo() << "\t";
         cout << "ID departamento: " << tmp_iterator->obtenerIDdepa() << endl;
        } 
    cout << "Total de Empleados: " << tmp_emps.size() << endl;
    cout << endl;
}

//--------------------------------------------------------------------------
// Muestra los valores de las estructuras tipo empleadosxdepto_t almacenadas en la lista de empleados por departamento
void EmpleadosxDepartamento(list<empleadosxdepto_t> &lista)
{
    int i_departementos = 0, i_empleados = 0;
    int i_x = 0;    

    list<empleadosxdepto_t>::iterator tmp_iterator;

    cout << "****** Empleados por departamento ******" << endl;
    for ( tmp_iterator = lista.begin(); tmp_iterator != lista.end(); tmp_iterator++)
        {
         i_departementos++;
         cout << "ID Departamento: "<< (*tmp_iterator).str_iddepto << "\t";
         cout << "Número empleado: " << endl;

         i_x = (*tmp_iterator).v_numerosemp.size();
         for (int i_contador = 0; i_contador < i_x; i_contador++)         
             {
              cout << "\t\t\t\t" << (*tmp_iterator).v_numerosemp&#91;i_contador&#93; << endl;
             } /* for */
         cout << "\t\t\t" << "Total: "<< i_x << endl;
         i_empleados+=i_x;
        } /* for */
    cout << "Departamentos con almenos un empleado: "<< i_departementos << endl;
    cout << "Total de Empleados: "<< i_empleados << endl;
    cout << endl;
}

//--------------------------------------------------------------------------
// Programa principal
int main()
{
    vector<Departamento> v_deptos;    
    vector<Empleado> v_empleados;
    vector<Empleado>::iterator v_empleados_it;
    list<empleadosxdepto_t> l_empleados;    

    // Objeto de la clase Departamento
    Departamento aux_depto;
    // Objeto de la clase Empleado
    Empleado aux_emp;

    // Variables auxiliares para capturar departamento
    string aux_iddepto="";
    string aux_nombredepto="";
    double aux_presupuesto=0;

    // Variables auxiliares para capturar empleado
    int aux_nemp=0;
    string aux_nombreemp="";
    double aux_sueldo=0;    

    // Capturamos 3 departamentos y los agregamos al vector v_deptos
    for (int i = 0; i < 3; i++)
        {
            cout << "ID departamento " << i+1 << " : ";
            cin >> aux_iddepto;
            cout << "Nombre departamento " << i+1 << " : ";
            cin >> aux_nombredepto;
            cout << "Presupuesto departamento " << i+1 << " : ";
            cin >> aux_presupuesto;

            aux_depto.asignarID(aux_iddepto);
            aux_depto.asignarNombre(aux_nombredepto);
            aux_depto.asignarPresupuesto(aux_presupuesto);
            v_deptos.push_back(aux_depto);
        }

    // Capturamos 10 empleados y los agregamos al vector v_empleados
    for (int i = 0; i < 10; i++)
        {
            cout << "Número empleado " << i+1 << " : ";
            cin >> aux_nemp;
            cout << "Nombre empleado " << i+1 << " : ";
            cin >> aux_nombreemp;
            cout << "Sueldo empleado " << i+1 << " : ";
            cin >> aux_sueldo;
            cout << "ID departamento :";
            cin >> aux_iddepto;

            aux_emp.asignarNumero(aux_nemp);
            aux_emp.asignarNombre(aux_nombreemp);
            aux_emp.asignarSueldo(aux_sueldo);
            aux_emp.asignarIDdepa(aux_iddepto);
            v_empleados.push_back(aux_emp);
        }

    // Llena la lista que contiene los códigos de departamento y los números de cada una de sus empleados
    // Recorremos el vector de empleados
    for ( v_empleados_it = v_empleados.begin(); v_empleados_it != v_empleados.end(); v_empleados_it++)
         AgregaEmpleado(v_empleados_it->obtenerIDdepa(), v_empleados_it->obtenerNumero(), l_empleados);

    MuestraVectorDeptos(v_deptos);
    MuestraVectorEmps(v_empleados);
    EmpleadosxDepartamento(l_empleados);

    return 0;
}

Etiquetas: , , , ,

8 comentarios to “Usando cadenas, vectores y estructuras con la STL”

  1. O.O Says:

    Eso fue un super hiper mega archi aporte!!!!!!!!!!!!!
    Muuuuuuuuuuuuuchas gracias!!
    Que sencillo lo explicas =)

  2. Martin Says:

    Muchas gracias de verdad un aporte excelente me canse de buscar en internet
    muy bien explicado.

  3. aderly_agua08@hotmail.com Says:

    gracias!!!!

  4. gobi07 Says:

    ¡Excelente! Me has ayudado mucho con esta entrada, mil gracias.

  5. Francisco Says:

    Muchas gracias. Estupendos ejemplos.

  6. Samoth Says:

    muy buena explicacion de este tema tan interesante e importante en C++

  7. ebeert Says:

    buenazo tu blog brother …….

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s


A %d blogueros les gusta esto: