Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Omar_2013 en 16 Octubre 2013, 01:31 am



Título: Problema Con Un Arreglo Dinamico [?]
Publicado por: Omar_2013 en 16 Octubre 2013, 01:31 am
El codigo compila pero el ejecutable no funciona tal como la imagen de el link

Código
  1. #include <cstdlib>
  2. #include <iostream>
  3.  
  4. using namespace std;
  5.  
  6. struct Item{
  7.       int Peso;
  8.       int Volumen;
  9.       string Nombre;
  10. };
  11.  
  12. struct Maleta{
  13.       int Peso;
  14.       int Volumen;
  15.       int Cantidad_Items;
  16.       Item *Items;
  17. };
  18.  
  19. int main(int argc, char *argv[])
  20. {
  21.    Maleta *Mi_Maleta=new Maleta[10];
  22.    Mi_Maleta->Items=new Item[10];
  23.  
  24.    Mi_Maleta[1].Items[0].Nombre="Peras";
  25.    Mi_Maleta[1].Items[0].Volumen=12;
  26.    Mi_Maleta[1].Items[0].Peso=16;
  27.  
  28.  
  29.    system("PAUSE");
  30.    return EXIT_SUCCESS;
  31. }
http://www.subirimagenes.com/imagen-imagen1-8658261.html (http://www.subirimagenes.com/imagen-imagen1-8658261.html)


Título: Re: Problema Con Un Arreglo Dinamico [?]
Publicado por: eferion en 16 Octubre 2013, 08:34 am
Código
  1. Maleta *Mi_Maleta=new Maleta[10];

Creas un array de 10 punteros de tipo Maleta.

Código
  1. Mi_Maleta->Items=new Item[10];

Creas un array de 10 punteros de tipo Item en... donde?? si Mi_Maleta es un array de 10 punteros lo lógico hubiese sido un acceso del tipo:

Código
  1. Mi_Maleta[0]->Items = new Item[10];

Lo que sucede es que esta línea puesta tal cual te va a dar error porque tu únicamente has definido el array de punteros... no has creado ni un solo objeto de tipo Maleta.

Tendrías que haber hecho algo así:

Código
  1. Maleta *Mi_Maleta=new Maleta[10];
  2. for ( int i=0; i<10; i++ )
  3.  Mi_Maleta[ i ] = new MiMaleta( );

Ya que una cosa es crear un array de punteros y otra muy diferente crear los objetos en sí.

En el caso del array de items te pasa exactamente lo mismo, pero con lo que te he dicho ya deberías ser capaz de resolverlo tu mismo.

Un saludo.

 


Título: Re: Problema Con Un Arreglo Dinamico [?]
Publicado por: Omar_2013 en 16 Octubre 2013, 21:15 pm
Gracias por responder....

En realidad lo que trataba de hacer era que para cada posicion del arreglo Mi_Maleta, le correspondiara una arreglo donde se guardara cada item de la maleta.

Pero por lo visto hay que crear los dos arreglos por aparte no? ...

Primero el arreglo de Maletas y despues el arreglo de Items

Código
  1. Maleta *Mi_Maleta=new Maleta[10];
  2. Item *Elementos=new Item[10];


y despues de alguna manera asignarle a cada posicion de Mi_Maleta, el arreglo de Elementos


Título: Re: Problema Con Un Arreglo Dinamico [?]
Publicado por: eferion en 16 Octubre 2013, 23:21 pm
Vale, ahora estoy más tranquilo y creo que puedo darte una respuesta un poco más elaborada.

Vayamos por partes:

1. Clases de c++

Código
  1. Maleta *Mi_Maleta=new Maleta[10];

Estás usando c++. Salvo que sea una práctica de clase o que quieras practicar de forma intensiva con la memoria dinámica, te recomiendo usar la clase "vector", que es bastante más potente que los arreglos "a pelo" que estás intentando programar.

2. Clases de c++ ( 2ª parte )

Código
  1. struct Item{
  2.       int Peso;
  3.       int Volumen;
  4.       string Nombre;
  5. };

Estás usando c++, luego lo lógico y normal es que emplees "class" en vez de "struct". A grandes rasgos, la única diferencia entre ambos es que, por defecto, "class" tiene sus miembros privados mientras que "struct" los mantiene públicos. "class" es más natural en c++ y es altamente recomendado familiarizarse con su uso, ya que está tremendamente extendido.

Aprovechando tu paso a un c++ más normal, aprovecha para dejar las variables de las clases en la parte "private" de la clase y crea métodos que permitan acceder y modificar el valor de dichas variables. Este proceso se conoce como "encapsulación" y es uno de los pilares de la programación orientada a objetos. Familiarízate con ello.

La clase Item debería tener una declaración tal que:

Código
  1. class Item
  2. {
  3.  public:
  4.  
  5.       // Constructor por defecto. Para inicializar las variables de la clase.
  6.       Item( );
  7.  
  8.       // Destructor. En tu caso no hace falta hacer deletes... pero conviene acostumbrarse a ponerlo.
  9.       virtual ~Item( );
  10.  
  11.       int GetPeso( ) const;
  12.  
  13.       void SetPeso( int peso );
  14.  
  15.       int GetVolumen( ) const;
  16.  
  17.       void SetVolumen( int volumen );
  18.  
  19.       const string& GetNombre( ) const;
  20.  
  21.       void SetNombre( const string& nombre );
  22.  
  23.  private:
  24.  
  25.       int Peso;
  26.       int Volumen;
  27.       string Nombre;
  28. };

La implementación te la dejo a tí. Es muy sencilla.

3. Constructores

Hay muchísima documentación en internet al respecto, te aconsejo buscar un poco e informarte.

Lo que deberías saber es que los constructores te permiten inicializar las variables de la clase con el objetivo de que dichas variables no tengan valores inválidos.

En el caso de la clase Maleta, el constructor podría, por su propia cuenta, crear el arreglo de Items de dicha maleta.

4. Arreglos

Código
  1. Maleta *Mi_Maleta=new Maleta[10];

La línea superior crea un arreglo de 10 punteros de tipo Maleta... pero no crea un solo objeto Maleta. Es necesario crear de forma individual los objetos Maleta y almacenar sus punteros en la posición que corresponda del arreglo de maletas. Con los items pasa exactamente lo mismo.

Aprovechando el punto 3, es decir, creando el arreglo de items en el constructor de la clase maleta, te olvidas de tener que crearlo explícitamente cada vez que crees un objeto maleta... aunque como te he comentado en el punto 1, la clase vector da mucha más flexibilidad que los arreglos puros.


Título: Re: Problema Con Un Arreglo Dinamico [?]
Publicado por: Eternal Idol en 16 Octubre 2013, 23:35 pm
Código
  1. Maleta *Mi_Maleta=new Maleta[10];

La línea superior crea un arreglo de 10 punteros de tipo Maleta... pero no crea un solo objeto Maleta.

En realidad eso crea 10 objetos Maleta, se reserva la memoria y se llama al constructor. Se puede comprobar facilmente:

Código
  1. #include <iostream>
  2.  
  3. using namespace std;
  4.  
  5. struct Maleta{
  6.  
  7.       int Peso;
  8.  
  9.       int Volumen;
  10.  
  11.       int Cantidad_Items;
  12.  
  13. //       Item *Items;
  14.  
  15. Maleta()
  16. {
  17.  cout << "Maleta::Maleta " << this << endl;
  18. }
  19. };
  20.  
  21.  
  22.  
  23. void main()
  24. {
  25.  Maleta *Mi_Maleta = new Maleta[10];
  26.  for (int x = 0; x < 10; ++x)
  27.    cout << "Mi_Maleta[" << x << "] = " << &Mi_Maleta[x] << endl;
  28. }
  29.  

Omar_2013: la excepcion no controlada se da por ser Items de Mi_Maleta[1] un valor indeterminado. Nunca le asignaste un puntero valido (solo lo hiciste para Mi_Maleta[0] que es equivalente desreferenciar Mi_Maleta; deberias llamar a la variable en plural), podes hacerlo en el constructor de Maleta asi por ejemplo:

Código
  1. Maleta()
  2. {
  3.  Items = new Item[10];
  4. }

PD. No te olvides de liberarlo en el destructor.