Foros del Web » Programación para mayores de 30 ;) » C/C++ »

[SOLUCIONADO] Crear una máscara para ver determinados miembros de una estructura

Estas en el tema de Crear una máscara para ver determinados miembros de una estructura en el foro de C/C++ en Foros del Web. Hola: Continuando con temas relacionados con miembros de una estructura , ahora me pregunto si sería posible asociar los datos a una máscara de forma ...
  #1 (permalink)  
Antiguo 29/10/2014, 12:32
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 14 años, 1 mes
Puntos: 10
Crear una máscara para ver determinados miembros de una estructura

Hola:

Continuando con temas relacionados con miembros de una estructura, ahora me pregunto si sería posible asociar los datos a una máscara de forma que ésta última me dijese cuales datos serán visibles y cuales no.

He implementado la idea asociando la máscara (un array de bool) con un array de int.....claro, esto es lo fácil
Código C++:
Ver original
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. void ver(const bool *mascara, const int *secuencia,int numColumnas);
  5.  
  6. const int numColumnas=5;
  7.  
  8. int main()
  9. {
  10.     bool mascara[numColumnas]= {true,true,true,false,false};
  11.     int numeros[numColumnas]= {4,8,6,3,7};
  12.  
  13.     ver(mascara,numeros,numColumnas);
  14.  
  15.     return 0;
  16. }
  17.  
  18. void ver(const bool *mascara, const int *secuencia,int numColumnas)
  19. {
  20.     for (int i=0; i<numColumnas; i++)
  21.     {
  22.         if (mascara[i])
  23.         {
  24.             cout<<secuencia[i]<<" - ";
  25.         }
  26.     }
  27. }

Pero lo que realmente me interesa sería implementar esa idea para los miembros de una estructura:
Algo como:

Código C++:
Ver original
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. struct datos
  5. {
  6.     int dato1;
  7.     float dato2;
  8.     char dato3;
  9.     char dato4[5];
  10.     bool dato5;
  11.     datos():dato1(3),dato2(2.33),dato3('X'),dato5(true)
  12.     {
  13.         strcpy(dato4,"Pepe");
  14.     }
  15. };
  16.  
  17. void ver(const bool *mascara, const datos&D,int numColumnas);
  18.  
  19. const int numColumnas=5;
  20.  
  21. int main()
  22. {
  23.     datos D;
  24.     bool mascara[numColumnas]= {true,true,true,false,false};
  25.     ver(mascara,D,numColumnas);
  26. return 0;
  27. }
  28.  
  29. void ver(const bool *mascara, const datos&D,int numColumnas)
  30. {
  31. //realmente la idea sería intentar que los datos de la estructura se pudieran ligar
  32. //al array que sirve de máscara para poder en un sólo bucle discriminar los datos
  33. //visibles y los que no lo serán...vamos...como si los miembros de la estructura
  34. //fueran un array
  35. }
  #2 (permalink)  
Antiguo 30/10/2014, 09:57
Avatar de leosansan  
Fecha de Ingreso: mayo-2012
Ubicación: GRAN CANARIA
Mensajes: 194
Antigüedad: 12 años, 5 meses
Puntos: 49
Respuesta: Crear una máscara para ver determinados miembros de una estructura

Cita:
Iniciado por dehm Ver Mensaje
Hola:

Continuando con temas relacionados con miembros de una estructura, ahora me pregunto si sería posible asociar los datos a una máscara de forma que ésta última me dijese cuales datos serán visibles y cuales no.
.................................................. .......

Pero lo que realmente me interesa sería implementar esa idea para los miembros de una estructura:
Algo como:
...........................................
Perdona por la tardanza amigo dehm pero es que tiene "miga" tu propuesta.

Después de darle bastantes vueltas al asunto me ha salido lo que sigue , que cumple con el cometido, pero creo que debería de haber alguna solución más sencilla.

Código C++:
Ver original
  1. #include <iostream>
  2.  
  3. using namespace std;
  4.  
  5. struct datos
  6. {
  7.     int dato1 ;
  8.     float dato2 ;
  9.     char dato3 ;
  10.     char dato4 [ 5 ] ;
  11.     bool dato5 ;
  12.     datos():dato1 ( 3 ) , dato2 ( 2.33 ) , dato3 ( 'X' ) ,dato5 ( true )
  13.     {
  14.         strcpy ( dato4 , "Pepe" ) ;
  15.     }
  16. };
  17.  
  18. void ver ( const bool *mascara , const datos&D ,int numColumnas ) ;
  19.  
  20. const int numColumnas = 5 ;
  21.  
  22. int main ( void ) {
  23.     datos D ;
  24.     bool mascara [ numColumnas ]= { true , false , true , true , false } ;
  25.     ver( mascara , D , numColumnas ) ;
  26. return 0 ;
  27. }
  28.  
  29. void ver(const bool *mascara, const datos&D,int numColumnas) {
  30.   if ( mascara [ 0 ] ) cout << D.dato1 << " - " ;
  31.   if ( mascara [ 1 ] ) cout << D.dato2 << " - " ;
  32.   if ( mascara [ 2 ] ) cout << D.dato3 << " - " ;
  33.   if ( mascara [ 3 ] ) cout << D.dato4 << " - " ;
  34.   if ( mascara [ 4 ] ) cout << D.dato5 << " - " ;    
  35. }

La verdad es que aquí echo en falta algo tan elemental en Python como usar arrays cuyos elementos pueden ser de distintos "tipos" y claro todo es mucho más sencillo. Pero en fin, estamos en C/C++ y hay lo que hay.

Espero que te sirva al menos de orientación para otras opciones que se te puedan ocurrir. Y si eso sucede no te olvides de compartirlas aquí.

¡¡¡Saluditos!!!


Última edición por leosansan; 30/10/2014 a las 10:32
  #3 (permalink)  
Antiguo 30/10/2014, 10:34
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 1 mes
Puntos: 204
Respuesta: Crear una máscara para ver determinados miembros de una estructura

Siempre hay soluciones.

En mi caso, yo primero declararía una clase que me permitiese manejar tipos de forma genérica (algo parecido a lo que echa de menos leosansan)

Código C++:
Ver original
  1. class Variant
  2. {
  3.   public:
  4.  
  5.     enum DataType
  6.     {
  7.       DTInt,
  8.       DTChar,
  9.       DTFloat
  10.     };
  11.  
  12.     Variant( )
  13.       : _type( DTInt )
  14.     {
  15.       _data.intData = 0;
  16.     }
  17.  
  18.     explicit Variant( int valor )
  19.       : _type( DTInt )
  20.     {
  21.       _data.intData = valor;
  22.     }
  23.  
  24.     explicit Variant( char valor )
  25.       : _type( DTChar )
  26.     {
  27.       _data.charData = valor;
  28.     }
  29.  
  30.     explicit Variant( float valor )
  31.       : _type( DTFloat )
  32.     {
  33.       _data.floatData = valor;
  34.     }
  35.  
  36.     DataType Type( ) const
  37.     { return _type; }
  38.  
  39.     Variant& operator=( int valor )
  40.     {
  41.       _type = DTInt;
  42.       _data.intData = valor;
  43.  
  44.       return *this;
  45.     }
  46.  
  47.     Variant& operator=( char valor )
  48.     {
  49.       _type = DTChar;
  50.       _data.charData = valor;
  51.  
  52.       return *this;
  53.     }
  54.  
  55.     Variant& operator=( float valor )
  56.     {
  57.       _type = DTFloat;
  58.       _data.floatData = valor;
  59.  
  60.       return *this;
  61.     }
  62.  
  63.     int ToInt( ) const
  64.     {
  65.       int to_return = 0;
  66.       switch ( _type )
  67.       {
  68.         case DTInt:
  69.           to_return = _data.intData;
  70.           break;
  71.  
  72.         case DTFloat:
  73.           to_return = static_cast< int >( _data.floatData );
  74.           break;
  75.       }
  76.  
  77.       return to_return;
  78.     }
  79.  
  80.     float ToFloat( ) const
  81.     {
  82.       float to_return = 0.0;
  83.       switch ( _type )
  84.       {
  85.         case DTFloat:
  86.           to_return = _data.floatData;
  87.           break;
  88.  
  89.         case DTInt:
  90.           to_return = static_cast< float >( _data.intData );
  91.           break;
  92.       }
  93.  
  94.       return to_return;
  95.     }
  96.  
  97.     char ToChar( ) const
  98.     {
  99.       char to_return = 0;
  100.  
  101.       switch ( _type )
  102.       {
  103.         case DTChar:
  104.           to_return = _data.charData;
  105.           break;
  106.       }
  107.  
  108.       return to_return;
  109.     }
  110.  
  111.   private:
  112.  
  113.     union Data
  114.     {
  115.       int intData;
  116.       char charData;
  117.       float floatData;
  118.     };
  119.  
  120.  
  121.     Data _data;
  122.     DataType _type;
  123. };

Se puede preparar para que admita más tipos, pero tampoco quería alargar demasiado el ejemplo.

Ahora necesitamos conectar esta clase con "cout" para poder imprimir el valor almacenado sin tener que andar haciendo cosas raras:

Código C++:
Ver original
  1. std::ostream& operator << ( std::ostream& stream, const Variant& variant )
  2. {
  3.   switch ( variant.Type( ) )
  4.   {
  5.     case Variant::DTInt:
  6.       stream << variant.ToInt( );
  7.       break;
  8.  
  9.     case Variant::DTChar:
  10.       stream << variant.ToChar( );
  11.       break;
  12.  
  13.     case Variant::DTFloat:
  14.       stream << variant.ToFloat( );
  15.       break;
  16.   }
  17.  
  18.   return stream;
  19. }

Ahora, por sencillez, modifico ligeramente la estructura. Prefiero eso a tener una función externa, pero para gustos los colores:

Código C++:
Ver original
  1. enum class Mascara
  2. {
  3.   Campo1,
  4.   Campo2,
  5.   Campo3
  6. };
  7.  
  8. struct datos
  9. {
  10.     int dato1;
  11.     float dato2;
  12.     char dato3;
  13.  
  14.     datos( )
  15.       : dato1( 3 ),
  16.         dato2( 3.85 ),
  17.         dato3( 'X' )
  18.     {
  19.     }
  20.  
  21.     Variant Valor( Mascara mascara ) const
  22.     {
  23.       Variant to_return;
  24.  
  25.       switch ( mascara )
  26.       {
  27.         case Mascara::Campo1:
  28.           to_return = dato1;
  29.           break;
  30.  
  31.         case Mascara::Campo2:
  32.           to_return = dato2;
  33.           break;
  34.  
  35.         case Mascara::Campo3:
  36.           to_return = dato3;
  37.           break;
  38.       }
  39.  
  40.       return to_return;
  41.     }
  42. };

Y ahora ya enlazamos todo esto con la aplicación:

Código C++:
Ver original
  1. void ver(const std::vector< Mascara >& mascara, const datos&D);
  2.  
  3. int main()
  4. {
  5.   datos D;
  6.   std::vector< Mascara > mascara { Mascara::Campo1, Mascara::Campo3 };
  7.   ver( mascara,D );
  8.   return 0;
  9. }
  10.  
  11. void ver(const std::vector< Mascara >& mascara, const datos&D)
  12. {
  13.   for ( auto it = mascara.begin( ); it != mascara.end( ); ++it )
  14.   {
  15.     std::cout << D.Valor( *it ) << " - ";
  16.   }
  17. }

Et voilá. Todo funciona a pedir de boca XD
  #4 (permalink)  
Antiguo 30/10/2014, 15:26
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 14 años, 1 mes
Puntos: 10
Respuesta: Crear una máscara para ver determinados miembros de una estructura

Hola leosansan....muchas gracias por la respuesta. Ciertamente yo también le daba vueltas al tema de cómo "obviar" el tipo. De hecho estaba trasteando con punteros void e intentando colársela al compilador con el nuevo tipo auto...pero no sé por qué siempre que intento hacer esas ñapas el compilador me corta el rollo rápidamente.

eferion....este tipo de respuestas me va a obligar a aprender C++
Ya en serio, muchas gracias. Y fuera de bromas necesito 2-3 horas (mínimo) para entender todas las cosas que has puesto. En cuanto lo tenga todo claro lo comento aquí....espero no tener que dar la lata de nuevo.

Gracias a ambos.
  #5 (permalink)  
Antiguo 30/10/2014, 16:23
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 1 mes
Puntos: 204
Respuesta: Crear una máscara para ver determinados miembros de una estructura

Cita:
Iniciado por dehm Ver Mensaje
De hecho estaba trasteando con punteros void e intentando colársela al compilador con el nuevo tipo auto...pero no sé por qué siempre que intento hacer esas ñapas el compilador me corta el rollo rápidamente.
"auto" es una palabra clave que se sustituye por un tipo concreto (int, float, string) en tiempo de compilación. Para poder hacer esto, el compilador tiene que poder adivinar el tipo de la variable en tiempo de compilación. Por ejemplo:

Código C++:
Ver original
  1. auto variable; // Error de compilación, no se puede determinar el tipo
  2.  
  3. auto var2 = 45; // var2 será de tipo int

Además, dado que el tipo se determina en tiempo de compilación, éste no es mutable. Te lo explico con un ejemplo:

Código C++:
Ver original
  1. auto var1 = 4; // var1 será de tipo int
  2.  
  3. var1 = "Hola"; // Error de compilación, var1 no puede cambiarse a string

Espero que estos comentarios te aclaren los motivos por los que el compilador no aceptaba tus usos de "auto".

Cita:
Iniciado por dehm Ver Mensaje
eferion....este tipo de respuestas me va a obligar a aprender C++
Ya en serio, muchas gracias. Y fuera de bromas necesito 2-3 horas (mínimo) para entender todas las cosas que has puesto. En cuanto lo tenga todo claro lo comento aquí....espero no tener que dar la lata de nuevo.
Lo de aprender C++ es una buena idea :)

Y no, preguntar dudas no es el equivalente a dar la lata.

Un saludo.

EDITADO:

PD.: La clase "Variant" se puede adaptar de forma sencilla para que trabaje también con strings, eso sí, dado que la clase string hace uso de memoria dinámica no es conveniente incluir la instancia de string dentro del union so pena de corromper la memoria:

Código C++:
Ver original
  1. class Variant
  2. {
  3.   public:
  4.  
  5.     enum DataType
  6.     {
  7.       DTInt,
  8.       DTChar,
  9.       DTFloat,
  10.       DTString
  11.     };
  12.  
  13.     explicit Variant( const std::string& valor )
  14.       : _type( DTString )
  15.     {
  16.       _string = valor;
  17.     }
  18.  
  19.     Variant& operator=( const std::string& valor )
  20.     {
  21.       _type = DTString ;
  22.       _string = valor;
  23.  
  24.       return *this;
  25.     }
  26.  
  27.   private:
  28.  
  29.     union Data
  30.     {
  31.       int intData;
  32.       char charData;
  33.       float floatData;
  34.     };
  35.  
  36.     Data _data;
  37.     DataType _type;
  38.     std::string _string;
  39. };

El resto de la implementación os la podéis imaginar :)

Un saludo.

Última edición por eferion; 31/10/2014 a las 03:27
  #6 (permalink)  
Antiguo 29/11/2014, 13:01
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 14 años, 1 mes
Puntos: 10
Respuesta: Crear una máscara para ver determinados miembros de una estructura

Cita:
Y fuera de bromas necesito 2-3 horas (mínimo) para entender todas las cosas que has puesto
Un mes después....

Me he quedado aquí:

Código C++:
Ver original
  1. enum class Mascara
  2. {
  3.   Campo1,
  4.   Campo2,
  5.   Campo3
  6. };

No sé leer ésto
__________________
Mi calculadora en Qt
  #7 (permalink)  
Antiguo 29/11/2014, 13:12
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 1 mes
Puntos: 204
Respuesta: Crear una máscara para ver determinados miembros de una estructura

por partes:

Código C++:
Ver original
  1. enum Mascara
  2. {
  3.   Campo1,
  4.   Campo2,
  5.   Campo3
  6. };

Esto se entiende, no? Un enumerado con varios elementos.

Código C++:
Ver original
  1. enum class Mascara;

Esta es una característica nueva de C++11. "class" hace que para acceder a los miembros del enumerado sea necesario indicar el nombre del enumerado:

Código con enum class
Código C++:
Ver original
  1. enum class Mascara
  2. {
  3.   Campo1
  4. };
  5.  
  6. foo( Mascara::Campo1 );

Código con un enum típico
Código C++:
Ver original
  1. enum Mascara
  2. {
  3.   Campo1
  4. };
  5.  
  6. foo( Campo1 );

Dicho con código, el efecto de "class" sería una estructura como la siguiente:

Código C++:
Ver original
  1. class Mascara
  2. {
  3.   public:
  4.     enum Mascara
  5.     {
  6.       Campo1,
  7.       Campo2,
  8.       Campo3
  9.     };
  10. }
  #8 (permalink)  
Antiguo 29/11/2014, 13:21
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 14 años, 1 mes
Puntos: 10
Respuesta: Crear una máscara para ver determinados miembros de una estructura

Gracias eferion:

Iba a editar el mensaje para decir que ya he leído el significado aqui:
http://www.cprogramming.com/c++11/c+...num-class.html

Pero gracias por tu explicación.
Bueno, pues seguimos estudiando tu código

Edito: Gracias eferion. Con alguna variación es eso lo que buscaba, y además he aprendido un montón con tu código.
Saludos!
__________________
Mi calculadora en Qt

Última edición por dehm; 29/11/2014 a las 14:03
  #9 (permalink)  
Antiguo 29/11/2014, 16:20
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 1 mes
Puntos: 204
Respuesta: Crear una máscara para ver determinados miembros de una estructura

Me alegro, en serio :)

Para cualquier duda que tengas, por aquí andamos

Un saludo.

Etiquetas: char, estructura, int, numero
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 17:43.