elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Guía actualizada para evitar que un ransomware ataque tu empresa


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Aporte C++: Utilidades de la STL que tal vez no conoces
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Aporte C++: Utilidades de la STL que tal vez no conoces  (Leído 2,378 veces)
eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Aporte C++: Utilidades de la STL que tal vez no conoces
« en: 2 Julio 2014, 13:29 pm »

Muchas veces, al hacer programas nos dedicamos a reinventar la rueda. Unas veces es para aprender, pero otras muchas es por simple desconocimiento de las herramientas de las que disponemos.

He aquí algunos ejemplos, aunque hay que tener en cuenta lo siguiente:

  • Algunos ejemplos solo funcionarán con compiladores compatibles con C++11.
  • Para entender los ejemplos es necesario tener una base mínima ( familiarizarse con contenedores e iteradores, por ejemplo )
  • Los ejemplos no intentan hacer uso del algoritmo más óptimo o más rápido o más ... son simplemente ilustrativos. La opción más óptima dependerá de los requisitos propios de cada aplicación.

Si el aporte os resulta interesante intentaré ampliarlo conforme tenga tiempo libre.

Ordenar un vector:

std::sort es el primero de los grandes desconocidos. Esta función, bien utilizada, nos permite ordenar con facilidad casi cualquier tipo de vector, lista, arreglo, ... para ello nos apoyamos en las funciones std::begin y std::end, nuevas en C++11, que permiten obtener iteradores incluso para arreglos.

Si usamos C++11, podemos también diseñar nuestras propias funciones de ordenación basándonos en funciones lambda, como se verá más adelante.

Apoyándonos en las funciones std::begin y std::end podemos
Código
  1. #include <algorithm>
  2. #include <functional>
  3. #include <iostream>
  4.  
  5. int main( )
  6. {
  7.  int numeros[] = {3, 5, 7, 2, 9, 1, 4, 8, 6 };
  8.  
  9.  std::cout << "Orden de mayor a menor" << std::endl;
  10.  std::sort ( std::begin(numeros), std::end(numeros), std::greater< int >( ) );
  11.  for ( auto it = std::begin( numeros ); it != std::end( numeros ); ++it )
  12.    std::cout << *it << ' ';
  13.  std::cout << std::endl;
  14.  
  15.  std::cout << "Orden de menor a mayor" << std::endl;
  16.  std::sort ( std::begin(numeros), std::end(numeros), std::less< int >( ) );
  17.  for ( auto it = std::begin( numeros ); it != std::end( numeros ); ++it )
  18.    std::cout << *it << ' ';
  19.  std::cout << std::endl;
  20.  return 0;
  21. }

Conteo de elementos en un vector

En el foro suele ser habitual que alguien pida ayuda saber cuántos elementos de un arreglo cumplen una serie de características...

Normalmente las soluciones pasan por poner un for con uno o varios ifs en su interior... con lo limpio que puede llegar a quedar usando las instrucciones adecuadas.

greater_equal es un template que implementa el operador función. Dicho operador requiere 2 parámetros... el primero es el valor a comprobar y el segundo el valor de referencia. El operador devuelve true si el primer parámetro es mayor o igual al segundo. Debido a que el parámetro que sirve de referencia es el segundo, se hace necesario usar la funcion bind2nd "bind second", que permite asignar un valor fijo al segundo parámetro a lo largo de todas las llamadas.

finalmente count_if se encarga de recorrer los iteradores y realiza un conteno de todas las comprobaciones que arrojan un resultado positivo.

El resultado es una comparación programada en un par de líneas.

Para comparaciones más complejas se puede usar una expresión lambda, una función propia o una clase que implemente el operador función, como puede verse en los ejemplos.

Código
  1. #include <algorithm>
  2. #include <functional>
  3. #include <iostream>
  4.  
  5. bool pares( int num )
  6. {
  7.  return num % 2 == 0;
  8. }
  9.  
  10. class DivisiblePorN
  11. {
  12.  public:
  13.  
  14.    DivisiblePorN( int divisor )
  15.      : _divisor( divisor )
  16.    { }
  17.  
  18.    bool operator( )( int numero )
  19.    {
  20.      return ( numero % _divisor == 0 );
  21.    }
  22.  
  23.  private:
  24.  
  25.    int _divisor;
  26. };
  27.  
  28. int main( )
  29. {
  30.  int numeros[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
  31.  int resultado = std::count_if( std::begin( numeros ), std::end( numeros ),
  32.                                 std::bind2nd( std::greater_equal< int >( ), 7 ) );
  33.  std::cout << "Numeros mayores o iguales a 7: " << resultado << std::endl;
  34.  
  35.  resultado = std::count_if( std::begin( numeros ), std::end( numeros ),
  36.                             []( int num ){ return num%2; } );
  37.  std::cout << "Numeros impares: " << resultado << std::endl;
  38.  
  39.  resultado = std::count_if( std::begin( numeros ), std::end( numeros ), pares );
  40.  std::cout << "Numeros pares: " << resultado << std::endl;
  41.  
  42.  DivisiblePorN divisible3( 3 );
  43.  resultado = std::count_if( std::begin( numeros ), std::end( numeros ), divisible3 );
  44.  std::cout << "Numeros divisibles entre 3: " << resultado << std::endl;
  45.  
  46.  return 0;
  47. }

Intercambiar el valor de dos variables

El titular lo dice todo... podemos hacer uso la opción larga que todo el mundo conoce ( en cualquiera de sus variantes ) o dejar que la stl haga el "trabajo sucio:

Código
  1. #include <algorithm>
  2. #include <iostream>
  3. #include <utility>
  4. #include <vector>
  5.  
  6. int main( )
  7. {
  8.  int x = 1;
  9.  int y = 2;
  10.  
  11.  std::swap( x, y );
  12.  
  13.  std::cout << "X = " << x << "; Y = " << y << std::endl << std::endl;
  14.  
  15.  int v1[] = { 1, 2, 3, 4 };
  16.  int v2[] = { 5, 6, 7, 8 };
  17.  std::swap( v1, v2 );
  18.  
  19.  std::cout << "v1 = {";
  20.  for ( auto i : v1 )
  21.    std::cout << " " << i;
  22.  std::cout << " }" << std::endl;
  23.  std::cout << "v2 = {";
  24.  for ( auto i : v2 )
  25.    std::cout << " " << i;
  26.  std::cout << " }" << std::endl << std::endl;
  27.  
  28.  std::vector< int > vector1 = { 10, 20, 30, 40 };
  29.  std::vector< int > vector2 = { 50, 60, 70, 80 };
  30.  std::swap( vector1, vector2 );
  31.  
  32.  std::cout << "vector1 = {";
  33.  for_each( vector1.begin( ), vector1.end( ), []( int num ){ std::cout << " " << num; } );
  34.  std::cout << " }" << std::endl;
  35.  
  36.  std::cout << "vector2 = {";
  37.  for_each( vector2.begin( ), vector2.end( ), []( int num ){ std::cout << " " << num; } );
  38.  std::cout << " }" << std::endl;
  39.  
  40.  return 0;
  41. }

Sumar valores

"Tengo que devolver la suma de todos los valores del arreglo"... ¿te suena esta frase? La primera solución que aparece en la mente de más de uno pasa por inicializar un contador, poner un bucle for e ir acumulando valores... no hace falta:

Código
  1. #include <functional>
  2. #include <iostream>
  3. #include <numeric>
  4.  
  5. int main( )
  6. {
  7.  int numeros[] = { 20, 45, 86, 91, 10, 25, 4, 17, 62 };
  8.  
  9.  std::cout << "Suma total: ";
  10.  std::cout << std::accumulate(std::begin( numeros ), std::end( numeros ), 0 );
  11.  std::cout << std::endl;
  12. }

¿Y si sólo queremos saber la suma de aquellos que cumplan una condición determinada? Sin problemas, únicamente tenemos que aplicar lo que hemos visto en apartados anteriores:

Código
  1. #include <functional>
  2. #include <iostream>
  3. #include <numeric>
  4.  
  5. class AddLessThanN
  6. {
  7.  public:
  8.  
  9.    AddLessThanN( int n )
  10.      : _limit( n )
  11.    {
  12.  
  13.    }
  14.  
  15.    int operator( )( int accum, int x )
  16.    {
  17.      if ( x < _limit )
  18.        accum += x;
  19.  
  20.      return accum;
  21.    }
  22.  
  23.  private:
  24.  
  25.    int _limit;
  26. };
  27.  
  28. int main( )
  29. {
  30.  int numeros[] = { 20, 45, 86, 91, 10, 25, 4, 17, 62 };
  31.  
  32.  AddLessThanN lessThan( 20 );
  33.  std::cout << "Sumar elementos menores que 20: ";
  34.  std::cout << std::accumulate(std::begin( numeros ), std::end( numeros ), 0, lessThan );
  35.  std::cout << std::endl;
  36. }

Eliminar elementos de un vector

La opciónes tradicionales pasan todas por usar un bucle for y luego, o hacer malabares con los iteradores, añadir los elementos a eliminar en una lista... o crear una lista nuevo con los elementos válidos...

Código
  1. #include <algorithm>
  2. #include <iostream>
  3. #include <vector>
  4.  
  5. int main( )
  6. {
  7.  std::vector< int > numeros = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
  8.  
  9.  std::vector< int >::iterator it = std::remove_if ( numeros.begin( ), numeros.end( ), [](int num){ return num%2; } );
  10.  numeros.erase( it, numeros.end( ) );
  11.  
  12.  std::cout << "Solo pares: ";
  13.  for_each( numeros.begin( ), numeros.end( ), []( int num){ std::cout << num << " "; } );
  14.  std::cout << std::endl;
  15.  
  16.  return 0;
  17. }

PD.: también funciona con arreglos:

Código
  1. #include <algorithm>
  2. #include <iostream>
  3. #include <vector>
  4.  
  5. int main( )
  6. {
  7.  int numeros[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
  8.  
  9.  int* itEnd = std::remove_if ( std::begin( numeros ), std::end( numeros ), [](int num){ return num%2 == 0; } );
  10.  
  11.  std::cout << "Solo impares: ";
  12.  for_each( std::begin( numeros ), itEnd, []( int num){ std::cout << num << " "; } );
  13.  std::cout << std::endl;
  14.  
  15.  return 0;
  16. }



En línea

vangodp


Desconectado Desconectado

Mensajes: 455



Ver Perfil
Re: Aporte C++: Utilidades de la STL que tal vez no conoces
« Respuesta #1 en: 2 Julio 2014, 18:30 pm »

 ;-) Gracias man. Que artista eres =D
Voy a estudiarlo.
Suerte!


En línea

nolasco281


Desconectado Desconectado

Mensajes: 319


Ver Perfil
Re: Aporte C++: Utilidades de la STL que tal vez no conoces
« Respuesta #2 en: 4 Julio 2014, 00:18 am »

Genial muchas gracias por los ejemplos solo tengo una pregunta:

En que parte de los ejemplos se utilizan estas librerias y para que? muchas gracias por compartir y suga aumentadolo si queda tiempo

Código
  1. #include <algorithm>
  2. #include <utility>

PD:Ya investique que son pero tal vez me puede dar  un concepto mas general de como las uso.

Saludos y gracias.
En línea

Lo que se puede imaginar... se puede programar.
leosansan


Desconectado Desconectado

Mensajes: 1.314


Ver Perfil
Re: Aporte C++: Utilidades de la STL que tal vez no conoces
« Respuesta #3 en: 4 Julio 2014, 07:40 am »

.........................................................
En que parte de los ejemplos se utilizan estas librerias y para que? muchas gracias por compartir y suga aumentadolo si queda tiempo

Código
  1. #include <algorithm>
  2. #include <utility>
....................................................






En línea

eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: Aporte C++: Utilidades de la STL que tal vez no conoces
« Respuesta #4 en: 4 Julio 2014, 08:24 am »

Genial muchas gracias por los ejemplos solo tengo una pregunta:

En que parte de los ejemplos se utilizan estas librerias y para que? muchas gracias por compartir y suga aumentadolo si queda tiempo

Código
  1. #include <algorithm>
  2. #include <utility>

PD:Ya investique que son pero tal vez me puede dar  un concepto mas general de como las uso.

Saludos y gracias.

algorithm tiene una colección de clases y funciones para trabajar con rangos de datos ( vectores, matrices, arreglos, ... ).

utility permite, por ejemplo trabajar con el template "pair". En un principio se podría decir que "utility" sirve de saco para aquellas utilidades que no han sabido ubicar en una librería más apropiada.
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
pequeño aporte(proxy),pero aporte al fin.:D
Programación Visual Basic
Tengu 0 2,411 Último mensaje 22 Julio 2007, 17:33 pm
por Tengu
¿Conoces la red social N-1?
Noticias
wolfbcn 1 2,911 Último mensaje 2 Junio 2011, 22:23 pm
por Foxy Rider
¿Conoces la distribución Mozillux?
Noticias
wolfbcn 0 1,321 Último mensaje 21 Septiembre 2012, 22:03 pm
por wolfbcn
Conoces Contre Jour? De App del año a la web
Juegos y Consolas
Arwen_123 0 1,633 Último mensaje 12 Noviembre 2012, 22:10 pm
por Arwen_123
No la conoces, pero Crystal sí te conoce
Noticias
wolfbcn 1 974 Último mensaje 4 Septiembre 2015, 18:51 pm
por DeMoNcRaZy
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines