Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Orubatosu en 1 Diciembre 2014, 11:06 am



Título: ¿Esto se puede hacer mejor? (C++ iteradores)
Publicado por: Orubatosu en 1 Diciembre 2014, 11:06 am
Estoy trasteando con iteradores para conseguir aprender como funcionan, o mejor dicho: estoy intentando "soltarme" con su manejo y coger soltura.

Entre otras cosillas, he montado una función que devuelve un iterador indicando el valor mas alto de un vector, y funciona eso está claro, pero no se porque lo veo "feo" y pienso que tiene que haber algún modo mas elegante de hacerlo.

A ver si me podéis decir si esto se puede hacer de algún modo mas simple

Código:
#include <iostream>
#include <vector>
using namespace std;

vector<double>::iterator maximo(vector<double>& v){
    vector<double>::iterator it = v.begin();
    vector<double>::iterator ret = it;
    if (v.empty()){
        it= v.end();
        return it;
    }
    double max=*it;
    for (it++; it!=v.end(); it++){
        if (*it > max){
        max=*it;
        ret = it;
       }
    }
    return ret;
    }

int main(){
    vector<double> Datos = {1.1, 2.2, 300.3, 5.5, 98.5, -12.5};
    vector<double>::iterator itd;
    itd = maximo (Datos);
    cout << *itd;
}



Título: Re: ¿Esto se puede hacer mejor? (C++ iteradores)
Publicado por: eferion en 1 Diciembre 2014, 11:21 am
Algo así:

Código
  1. vector<double>::iterator maximo(vector<double>& v)
  2. {
  3.  vector<double>::iterator it;
  4.  vector<double>::iterator to_return = v.begin( );
  5.  
  6.  double max = numeric_limits<double>::min( );
  7.  
  8.  for ( it = v.begin( ) ; it != v.end( ); ++it )
  9.  {
  10.    if ( *it > max )
  11.    {
  12.      to_return = it;
  13.      max = *it;
  14.    }
  15.  }
  16.  
  17.  return to_return;
  18. }

O, usando C++11

Código
  1. vector<double>::iterator maximo(vector<double>& v)
  2. {
  3.  auto to_return = v.begin( );
  4.  
  5.  double max = numeric_limits<double>::min( );
  6.  
  7.  for ( it = v.begin( ) ; it != v.end( ); ++it )
  8.  {
  9.    if ( *it > max )
  10.    {
  11.      to_return = it;
  12.      max = *it;
  13.    }
  14.  }
  15.  
  16.  return to_return;
  17. }



V2.0:

Código
  1. vector<double>::iterator maximo(vector<double>& v)
  2. {
  3.   return std::max_element( v.begin( ), v.end( ) );
  4. }

Vale que con esta última versión no vas a practicar demasiado con los iteradores... pero nunca hay que perder de vista que la stl tiene infinidad de herramientas que hacen que no tengamos que reinventar la rueda cada dos por tres.

Un saludo.


Título: Re: ¿Esto se puede hacer mejor? (C++ iteradores)
Publicado por: Orubatosu en 1 Diciembre 2014, 12:04 pm
Aha... voy a estudiarme esto a ver que ideas saco.

Si bueno, se que la stl tiene dentro de la librería <algorithm> autenticas filigranas, pero como funcionan en su mayoría a golpe de iteradores antes de meterme ahi quiero tener el tema de los iteradores "mascado" a consciencia. De nada me sirve ponerme a correr si antes no ando correctamente, ya me entiendes.


Título: Re: ¿Esto se puede hacer mejor? (C++ iteradores)
Publicado por: eferion en 1 Diciembre 2014, 12:09 pm
Lo cierto es que, pensando un poco más, no hace falta usar "max":

Código
  1. vector<double>::iterator maximo(vector<double>& v)
  2. {
  3.  auto it = v.begin( );
  4.  auto to_return = it;
  5.  
  6.  for ( ++it ; it != v.end( ); ++it )
  7.  {
  8.    if ( *it > *to_return )
  9.      to_return = it;
  10.  }
  11.  
  12.  return to_return;
  13. }


Título: Re: ¿Esto se puede hacer mejor? (C++ iteradores)
Publicado por: Orubatosu en 1 Diciembre 2014, 13:31 pm
"Auto" es un tipo nuevo de C++11 ¿no?

Tengo entendido que asume el "tipo correcto" para la expresión con la que se pretende inicializar la variable.

¿Podrías decirme donde está en http://www.cplusplus.com/ la referencia a este tipo?

Aprender a usarlo me ahorraría montones de dolores de cabeza, por no hablar de claridad de código. Cuando empiezas a liarla con iteradores constantes ya la longitud de algunas líneas se dispara con una facilidad pasmosa

Por ejemplo, dejar algo como

Código:
vector<Usuario>::const_iterator it = v.begin();

así

Código:
auto it = v.begin();

Ya sería la monda, porque dejarte sin querer cualquier pijadita por en medio a veces da unos dolores de cabeza tremendos


Título: Re: ¿Esto se puede hacer mejor? (C++ iteradores)
Publicado por: eferion en 1 Diciembre 2014, 13:44 pm
Desde mi punto de vista, "auto" no debe usarse indiscriminadamente, solo en aquellos casos en los que el código quede más claro (por ejemplo en el caso de iteradores... todos conocemos los iteradores y no hace falta decir... esto es un iterador). Sin embargo, si de un vistazo rápido no consigues adivinar el tipo al que va a equivaler "auto" entonces es mejor usar el nombrado tradicional. Eso sí, es mi punto de vista, no intento que nadie piense igual.

Por otro lado, no se si cplusplus tiene documentación dedicada de forma exclusiva a la palabra "auto", no obstante, si buscas en google puedes encontrar bastante documentación:

http://en.cppreference.com/w/cpp/language/auto (http://en.cppreference.com/w/cpp/language/auto)

Un saludo.


Título: Re: ¿Esto se puede hacer mejor? (C++ iteradores)
Publicado por: Orubatosu en 1 Diciembre 2014, 14:46 pm
Esa es precisamente la idea, ya que cuando empiezas a jugar con vectores normales, constantes, iteradores, tuplas, vectores de tuplas, interadores constantes o no de vectores de tuplas... es bastante fácil dejarte algo por el camino, pero de momento voy a seguir con el método "tradicional"

El porque es simplemente porque "la letra con sangre entra"... cuando tenga el tema dominado desde luego tiraré por el auto, pero no hasta entonces.

Gracias por todo  ;-)