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

[SOLUCIONADO] ¿Cómo fijar un dato de una estructura a la hora de introducirlo?

Estas en el tema de ¿Cómo fijar un dato de una estructura a la hora de introducirlo? en el foro de C/C++ en Foros del Web. Bueno, después de éste título tan farragoso, explico mi duda. Son de esas cosas que no pensé que me daría la lata por su sencillez...y ...
  #1 (permalink)  
Antiguo 17/10/2014, 02:16
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 13 años, 7 meses
Puntos: 10
¿Cómo fijar un dato de una estructura a la hora de introducirlo?

Bueno, después de éste título tan farragoso, explico mi duda.
Son de esas cosas que no pensé que me daría la lata por su sencillez...y llevo dos días atascado.
Bueno, explico lo que quiero hacer:
Imaginad una estructura de datos:
Código C++:
Ver original
  1. struct poligono
  2. {
  3.     int n_lados;
  4.     char[20] color;
  5. };

En un momento dado, me interesa crear y definir varias instancias de la estructura, pero por comodidad quiero que algun dato quede fijado. Es como cuando en un entorno visual alguna columna ya aparece con un valor predefinido, pero éste puede ser modificado en cualquier momento.

Por ejemplo, tengo que meter 50 objetos polígono en una lista.
Si tengo 8 de ellos cuyo color es "verde", pues me gustaría que la función que crea e inserta los objetos en la lista no me pregunte por el color del mismo, y lo defina como "verde". Igualmente, que se pueda cambiar ese valor a otro, o que directamente me pida el dato del color a la hora de crear el objeto, si no hay ninguno predefinido.

En fin, espero haber sido claro con mi problema. Si no es así, por favor, preguntadme.

Y como siempre, gracias por adelantado!
  #2 (permalink)  
Antiguo 17/10/2014, 02:33
Avatar de Profesor_Falken  
Fecha de Ingreso: agosto-2014
Ubicación: Mountain View
Mensajes: 1.323
Antigüedad: 9 años, 8 meses
Puntos: 182
Respuesta: ¿Cómo fijar un dato de una estructura a la hora de introducirlo?

Si no me equivoco puedes declarar una macro:

Código C:
Ver original
  1. struct poligono
  2. {
  3.     int n_lados;
  4.     char[20] color;
  5. };
  6.  
  7. #define NEW_POLIGONO(P) struct poligono P = {.n_lados = 4, .color ="verde"}
  8.  
  9. [...]
  10. /*Cuando quieras crear una estructura:*/
  11. NEW_POLIGONO(miPoligono);

Un saludo
__________________
If to err is human, then programmers are the most human of us
  #3 (permalink)  
Antiguo 17/10/2014, 02:49
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: ¿Cómo fijar un dato de una estructura a la hora de introducirlo?

Para eso inventaron los constructores de C++:

Código C++:
Ver original
  1. struct poligono
  2. {
  3.     int n_lados;
  4.     char[20] color;
  5.  
  6.     poligono( )
  7.     {
  8.       n_lados = 5;
  9.       strcpy( color, "verde" );
  10.     }
  11. };
  12.  
  13. int main( )
  14. {
  15.   poligono poli; // este objeto tiene 5 lados y es de color verde
  16. }
  #4 (permalink)  
Antiguo 17/10/2014, 03:03
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 13 años, 7 meses
Puntos: 10
Respuesta: ¿Cómo fijar un dato de una estructura a la hora de introducirlo?

Hola Profesor_Falken:

No estoy seguro de entender tu planteamiento.
He desarrollado el constructor de la estructura en función de la solución que me propones:

Código C++:
Ver original
  1. #include <iostream>
  2. #define NEW_POLIGONO(P) struct poligono P = {.n_lados = 4, .color ="verde"}
  3.  
  4. using namespace std;
  5.  
  6. struct poligono
  7. {
  8.     int n_lados;
  9.     char color[20];
  10.     poligono(int n, const char* c)
  11.     {
  12.         n_lados=n;
  13.         strcpy (color,c);
  14.     }
  15. };
  16.  
  17. int main()
  18. {
  19.     NEW_POLIGONO(mipoligono);
  20.     cout<<mipoligono.n_lados<<" - "<<mipoligono.color<<endl;
  21.     return 0;
  22. }

Y (obviamente) funciona. (Me apunto aprender a sacarle partido a las macros)
Pero no me da la flexibilidad que necesito o que quiero.
Sería algo así:

Código C++:
Ver original
  1. std::list<poligono>listapoligonos;
  2. int num;
  3. char aux[20];
  4. char respuesta='S';
  5. do
  6.    {
  7.     /*en algun momento del bucle de inserción de datos, me gustaría fijar algún dato de la estructura de forma que no tuviera que definirlo  en caso de encontrarme varios repetidos.*/
  8.     /* Igualmente "desbloquear" ese dato cuando no me interese, y que me vuelva a pedir por él*/
  9.  
  10.     std::cin>>num;
  11.     std::cin>>aux;
  12.     poligono P(num,aux);
  13.     listapoligonos.push_back(P);
  14.     std::cout<<"¿Quieres introducir otro poligono?"<<std::endl;
  15.     std::cin>>respuesta;
  16.     }
  17.     while (respuesta=='s' || respuesta=='S');

Gracias por la respuesta y disculpa si no la he entendido correctamente
  #5 (permalink)  
Antiguo 17/10/2014, 03:14
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 13 años, 7 meses
Puntos: 10
Respuesta: ¿Cómo fijar un dato de una estructura a la hora de introducirlo?

Hola eferion:

Mientras escribía la respuesta a Profesor_Falken has escrito la tuya.
Ciertamente la macro del Profe es casi el equivalente al constructor.
Creo que la clave no está en el constructor, sino de cómo pido los datos para alimentar luego al constructor...ufff...es que estoy empanao esta mañana (y ayer, y antes de ayer....)

Mas o menos el psudocódigo podría ser éste:
Código C++:
Ver original
  1. bucle de entrada de datos
  2. {
  3.     //No me interesa prefijar ningun dato:
  4.     entrar num_lados
  5.     entrar color
  6.     crear poligono P(num_lados,color)
  7.     //durante un intervalo quiero fijar el color
  8.     definir color, por ejemplo "verde"
  9.     entrar num_lados
  10.     crear poligono P(num_lados,color="verde")
  11.     //en otro momento del bucle de entrada "desbloqueo" el color verde
  12.     entrar num_lados
  13.     entrar color
  14.     crear poligono P(num_lados,color)
  15.     //es decir, que en cualquier momento de la entrada de datos pueda fijar
  16.     //alguno de ellos y que no me lo pida
  17. }

P.D. Menudo pseudocódigo cutre
  #6 (permalink)  
Antiguo 17/10/2014, 03:35
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: ¿Cómo fijar un dato de una estructura a la hora de introducirlo?

Si lo que quieres es crear varios componentes repetidos puedes optar por varias opciones:

1. Usar constructor copia

Código C++:
Ver original
  1. struct Test
  2. {
  3.   int valor;
  4.  
  5.   Test( )
  6.     : valor( 0 )
  7.   { }
  8.  
  9.   // Constructor copia
  10.   Test( const Test& otro )
  11.     : valor( otro.valor )
  12.   { }
  13. }
  14.  
  15. int main( )
  16. {
  17.   Test test;
  18.  
  19.   // Imprime '0'
  20.   std::cout << test.valor << std::endl;
  21.  
  22.   test.valor = 21;
  23.  
  24.   // Llamamos al constructor copia
  25.   Test test2( test );
  26.  
  27.   // Imprime '1'
  28.   std::cout << test2.valor << std::endl;
  29.  
  30.   // También funciona, como era de esperar, dentro de bucles:
  31.   for ( int i=0; i < 10; i++ )
  32.   {
  33.     Test temp( test );
  34.     std::cout << test.valor << std::endl;
  35.   }
  36. }

2. Guarda los valores que quieres repetir en variables...

Código C++:
Ver original
  1. struct Test
  2. {
  3.   int valor;
  4.  
  5.   Test( )
  6.     : valor( 0 )
  7.   { }
  8. };
  9.  
  10. int main( )
  11. {
  12.   int valor = 0;
  13.  
  14.   for ( int i=0; i < 10; i++ )
  15.   {
  16.     Test test;
  17.     test.valor = valor;
  18.  
  19.     std::cout << test.valor << std::endl;
  20.     std::cout << "Quieres reutilizar el ultimo valor? ";
  21.     char respuesta;
  22.     std::cin >> respuesta;
  23.  
  24.     if ( respuesta == 'n' )
  25.     {
  26.       std::cout << "Introduce el nuevo valor: ";
  27.       std::cin >> valor;
  28.     }
  29.   }
  30. }
  #7 (permalink)  
Antiguo 17/10/2014, 04:53
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 13 años, 7 meses
Puntos: 10
Respuesta: ¿Cómo fijar un dato de una estructura a la hora de introducirlo?

Hola eferion:

Gracias por la respuesta. Se acerca a lo que yo quería simular.
El caso es que he hecho un planteamiento, que aunque funciona, no me gusta demasiado. Se trata de crear una estructura para tratar las respuestas a introducir.
A favor:
1.-Que funciona (o eso parece)
En contra:
1.-Demasiado farragoso
2.-Estas estructuras han de estar íntimamente ligadas a la estructura a la que sirven de soporte, y si ésta cambia hay que ir cambiando la estructuras que recogen las respuestas. Esto puede parecer trivial en este ejemplo, pero si tuviéramos algo más serio o más grande creo que no sería muy viable.

Pero lo pongo a ver qué opináis:

Mi estructura del polígono:
Código C++:
Ver original
  1. struct poligono
  2. {
  3.     int n_lados;
  4.     char color[20];
  5.     poligono(int n, const char* c)
  6.     {
  7.         n_lados=n;
  8.         strcpy (color,c);
  9.     }
  10. };

La estructura que recoge la respuesta al dato n_lados:
Código C++:
Ver original
  1. struct respuesta_num_lados
  2. {
  3.     int numlados;
  4.     bool bloqueado;
  5.     respuesta_num_lados():bloqueado(false) {}
  6.     void fijar (int n)
  7.     {
  8.         bloqueado=true;
  9.         numlados=n;
  10.     }
  11.     void desbloquear()
  12.     {
  13.         bloqueado=false;
  14.     }
  15. };

Idem para el dato color

Código C++:
Ver original
  1. struct respuesta_color
  2. {
  3.     char color[20];
  4.     bool bloqueado;
  5.     respuesta_color():bloqueado(false) {}
  6.     void fijar (char* c)
  7.     {
  8.         strcpy (color,c);
  9.         bloqueado=true;
  10.     }
  11.     void desbloquear()
  12.     {
  13.         bloqueado=false;
  14.     }
  15. };

Y el programa que recoge la introducción de los datos:
Código C++:
Ver original
  1. int main()
  2. {
  3.     std::list<poligono>listapoligonos;
  4.     respuesta_num_lados num;
  5.     respuesta_color col;
  6.     char respuesta='d';
  7.     do
  8.         {
  9.             if (respuesta=='d' || respuesta=='D')
  10.                 {
  11.                     cout<<"(1) Fijar Nº de lados"<<endl<<"(2) Fijar Color"<<endl<<"(3) Desbloq. nº lados"<<endl
  12.                         <<"(4) Desbloq. color"<<endl<<"(5) Desbloq. ambos"<<endl<<"(ENTER) para seguir";
  13.                     string opcion;
  14.                     std::getline (cin,opcion);
  15.                     if (opcion=="1")
  16.                         {
  17.                             int n;
  18.                             cout<<"Numero lados: "<<endl;
  19.                             cin>>n;
  20.                             num.fijar(n);
  21.                         }
  22.                     if (opcion=="2")
  23.                         {
  24.                             char aux[20];
  25.                             cout<<"Color: "<<endl;
  26.                             cin>>aux;
  27.                             col.fijar(aux);
  28.                         }
  29.                     if (opcion=="3")
  30.                         {
  31.                             num.desbloquear();
  32.                         }
  33.                     if (opcion=="4")
  34.                         {
  35.                             col.desbloquear();
  36.                         }
  37.                     if (opcion=="5")
  38.                         {
  39.                             num.desbloquear();
  40.                             col.desbloquear();
  41.                         }
  42.                 }
  43.  
  44.             if (!num.bloqueado)
  45.                 {
  46.                     cout<<"Introduce nº de lados: "<<endl;
  47.                     cin>>num.numlados;
  48.                 }
  49.             if (!col.bloqueado)
  50.                 {
  51.                     cout<<"Introduce color: "<<endl;
  52.                     cin>>col.color;
  53.                 }
  54.             poligono P(num.numlados,col.color);
  55.             listapoligonos.push_back(P);
  56.             cout<<"¿Quieres introducir otro poligono?"<<std::endl;
  57.             cout<<"(S) para introducir (D) para fijar algun valor (N) Salir"<<std::endl;
  58.  
  59.             cin>>respuesta;
  60.             cin.get();
  61.         }
  62.     while (respuesta=='s' || respuesta=='S' || respuesta=='d' || respuesta=='D');
  63.    
  64.     cout<<"Los poligonos son: "<<endl;
  65.     for (auto it=listapoligonos.begin(); it!=listapoligonos.end(); it++)
  66.         {
  67.             cout<<(*it).n_lados<<" - "<<(*it).color<<endl;
  68.         }
  69. }
  #8 (permalink)  
Antiguo 17/10/2014, 05:12
Avatar de Profesor_Falken  
Fecha de Ingreso: agosto-2014
Ubicación: Mountain View
Mensajes: 1.323
Antigüedad: 9 años, 8 meses
Puntos: 182
Respuesta: ¿Cómo fijar un dato de una estructura a la hora de introducirlo?

Buenas,

Disculpa, en mi ejemplo con la macro yo entendia que estabas usando C y no C++.
En C++ efectivamente existen construcciones mas avanzadas como los constructores.

Respecto a tu problema, no se puede resolver de una forma muy sencilla con una variable global?

Puedes crearte una variable global llamada color_fijado. En principio estaria a null pero cuando quieras fijar un valor se lo asignas y la puedes volver a poner a null cuando quieras desactivar (lo mejor aqui seria crear una funcion que active/desactive).

Posteriormente en tu contructor lo podrias comprobar:

Código C++:
Ver original
  1. poligono(int n, const char* c)
  2.     {
  3.         n_lados=n;
  4.         if (color_fijado == NULL) {
  5.         strcpy (color,c);
  6.         else {
  7.          strcpy (color,color_fijado);
  8.        }
  9.     }


O mejor aun, tienes siempre un color_fijado y cuando llamas al constructor sin indicar el color utilizamos el color_fijado

Código C++:
Ver original
  1. struct poligono
  2. {
  3.     int n_lados;
  4.     char color[20];
  5.     poligono(int n, const char* c)
  6.     {
  7.         n_lados=n;
  8.         strcpy (color,c);
  9.     }
  10.  
  11. otro constructor que utilice el color_fijado
  12.      poligono(int n)
  13.     {
  14.         n_lados=n;
  15.         strcpy (color,color_fijado);
  16.     }
  17. };

Un saludo
__________________
If to err is human, then programmers are the most human of us
  #9 (permalink)  
Antiguo 17/10/2014, 05:22
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: ¿Cómo fijar un dato de una estructura a la hora de introducirlo?

Cita:
Iniciado por dehm Ver Mensaje
Hola eferion:
Gracias por la respuesta. Se acerca a lo que yo quería simular.
El caso es que he hecho un planteamiento, que aunque funciona, no me gusta demasiado. Se trata de crear una estructura para tratar las respuestas a introducir.
A favor:
1.-Que funciona (o eso parece)
En contra:
1.-Demasiado farragoso
2.-Estas estructuras han de estar íntimamente ligadas a la estructura a la que sirven de soporte, y si ésta cambia hay que ir cambiando la estructuras que recogen las respuestas. Esto puede parecer trivial en este ejemplo, pero si tuviéramos algo más serio o más grande creo que no sería muy viable.
Creo que para el caso es más factible y limpio hacer uso un "gestor" que controle la generación de nuevos elementos:

Código C++:
Ver original
  1. class GestorPoligonos
  2. {
  3.   public:
  4.  
  5.     GestorPoligonos( )
  6.       : ladosBloqueados( false ),
  7.         colorBloqueado( false )
  8.     {
  9.     }
  10.  
  11.     void BloquearLados( int n )
  12.     {
  13.       ladosBloqueados = true;
  14.       numLados = n;
  15.     }
  16.  
  17.     void BloquearColor( const std::string& c )
  18.     {
  19.       colorBloqueado = true;
  20.       color = c;
  21.     }
  22.  
  23.     void DesbloquearLados( )
  24.     {
  25.       ladosBloqueados = false;
  26.     }
  27.  
  28.     void DesbloquearColor( )
  29.     {
  30.       colorBloqueado = false;
  31.     }
  32.  
  33.     Poligono NuevoPoligono( )
  34.     {
  35.       Poligono poli( numLados, color);
  36.  
  37.       if ( !ladosBloqueados )
  38.       {
  39.         std::cout << "Introduce nº de lados: ";
  40.         std::cin >> poli.n_lados;
  41.       }
  42.  
  43.       if ( !colorBloqueado )
  44.       {
  45.         std::cout << "Introduce color: ";
  46.         std::cin >> poli.color;
  47.       }
  48.  
  49.       return poli;
  50.     }
  51.  
  52.   private:
  53.  
  54.     bool ladosBloqueados;
  55.     bool colorBloqueado;
  56.  
  57.     int numLados;
  58.     std::string color;
  59. };

Con esto el main queda más limpio y despejado:

Código C++:
Ver original
  1. int main()
  2. {
  3.   std::list< Poligono > listapoligonos;
  4.   GestorPoligonos gestor;
  5.   char respuesta='d';
  6.  
  7.   do
  8.   {
  9.     if ( respuesta=='d' || respuesta=='D' )
  10.     {
  11.       std::cout << "(1) Fijar Nº de lados" << std::endl
  12.                 << "(2) Fijar Color" << std::endl
  13.                 << "(3) Desbloq. nº lados" << std::endl
  14.                 << "(4) Desbloq. color" << std::endl
  15.                 << "(5) Desbloq. ambos" << std::endl
  16.                 << "(ENTER) para seguir" << std::endl;
  17.  
  18.       int opcion;
  19.       std::cin >> opcion;
  20.       switch ( opcion )
  21.       {
  22.         case 1:
  23.         {
  24.           int n;
  25.           std::cout << "Numero lados: ";
  26.           std::cin >> n;
  27.           gestor.BloquearLados( n );
  28.           break;
  29.         }
  30.  
  31.         case 2:
  32.         {
  33.           std::string color;
  34.           std::cout << "Color: ";
  35.           std::cin >> color;
  36.           gestor.BloquearColor( color );
  37.           break;
  38.         }
  39.  
  40.         case 3:
  41.         {
  42.           gestor.DesbloquearLados( );
  43.           break;
  44.         }
  45.  
  46.         case 4:
  47.         {
  48.           gestor.DesbloquearColor( );
  49.           break;
  50.         }
  51.  
  52.         case 5:
  53.         {
  54.           gestor.DesbloquearLados( );
  55.           gestor.DesbloquearColor( );
  56.           break;
  57.         }
  58.       }
  59.     }
  60.     Poligono p = gestor.NuevoPoligono( );
  61.     listapoligonos.push_back( p );
  62.  
  63.     std::cout << "¿Quieres introducir otro poligono?" << std::endl;
  64.     std::cout << "(S) para introducir (D) para fijar algun valor (N) Salir" << std::endl;
  65.  
  66.     std::cin >> respuesta;
  67.     std::cin.get( );
  68.   }
  69.   while (respuesta=='s' || respuesta=='S' || respuesta=='d' || respuesta=='D');
  70.  
  71.   std::cout<< "Los poligonos son: " << std::endl;
  72.   std::for_each( listapoligonos.begin( ), listapoligonos.end( ),
  73.                  []( const Poligono& p )
  74.                  { std::cout << p.n_lados << " - " << p.color << std::endl; } );
  75. }

PD.: me he tomado la libertad de cambiar "char[20]" por "std::string" en el poligono para que el diseño quede lo más limpio posible.
  #10 (permalink)  
Antiguo 17/10/2014, 09:03
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 13 años, 7 meses
Puntos: 10
Respuesta: ¿Cómo fijar un dato de una estructura a la hora de introducirlo?

Cita:
Iniciado por Profesor_Falken Ver Mensaje
Buenas,

Disculpa, en mi ejemplo con la macro yo entendia que estabas usando C y no C++.
No hay de qué darlas. No especifiqué el lenguaje y tengo la mala costumbre de usar structs de primeras cuando estoy enredando para no entretenerme en cuestiones de ámbitos públicos o privados e ir a la parte que quiero resolver, así que se presta a confusión. (Al final nadie me salva de convertir los structs en clases -AKA hacer las cosas 2 veces- o sea que no tiene mucha justificación lo que hago)

La solución que me propones era la que yo intuía cuando inicié el post, y que no fui capaz de darle forma, que es jugar con los constructores. Pero también le veo el problema de que debería de definir tantos constructores como miembros tenga la clase y...en definitiva, no me da la flexibilidad que querría.

Saludos y gracias!
  #11 (permalink)  
Antiguo 17/10/2014, 09:11
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 13 años, 7 meses
Puntos: 10
Respuesta: ¿Cómo fijar un dato de una estructura a la hora de introducirlo?

Cita:
Iniciado por eferion Ver Mensaje
Creo que para el caso es más factible y limpio hacer uso un "gestor" que controle la generación de nuevos elementos:
Brillante, esa es la pieza que faltaba para que la cosa funcione como deseaba.
¡Ni en mis próximas 50 vidas se me habría ocurrido crear una clase que gestionase los parámetros y retornase el objeto que quiero crear!

Gracias a ti y al Profe. Da gusto tener a gente así en el foro.
Saludos!

Etiquetas: char, dato, estructura, fijar, int
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 13:33.