[ Foro de C# ]

declarar un array de enteros en una estructura que después se declara como array de estructuras en un objeto

16-Jan-2011 09:05
Jos Antonio Pla
5 Respuestas

Hola a todos.
Estoy intentando realizar un programa que gestione los datos de los clubes de una Olimpiada. Un club sólo tiene como atributos propios su id y su nombre pero almacena los datos de tres atletas y cada atleta tiene id, nombre y los tres mejores lanzamientos de cada atleta.
He creado la clase club y la estructura atleta pero da error al intentar declarar el array de los tres lanzamientos dentro de la estructura atleta.
Mis preguntas son:
¿Cómo declaro el array de enteros dentro de la estructura atleta?
¿Cómo declaro luego el array de tres estructuras atleta dentro de la clase club?
¿Cómo accedo a los atributos que pertenecen a la estructura en cualquier método posterior?

PD.Ya he mirado el manual de esta página.

Muchas gracias


21-Jan-2011 11:07
Nacho Cabanes (+30)

Hola, José Antonio.

En estos casos, ayudaría que incluyeras el fuente que ya has hecho, para ver dónde está el problema. Vamos con las dos partes básicas:

En el ejemplo 40 del curso (apartado 4.3.2) tienes cómo crear un array de structs.

 
/*---------------------------*/
/*  Ejemplo en C# nº 40:     */
/*  ejemplo40.cs             */
/*                           */
/*  Array de struct          */
/*                           */
/*  Introduccion a C#,       */
/*    Nacho Cabanes          */
/*---------------------------*/
 
using System;
 
public class Ejemplo40
{
 
  struct tipoPersona
  {
    public string nombre;
    public char   inicial;
    public int    edad;
    public float  nota;
  } 
 
  public static void Main()
  {
    tipoPersona[] persona = new tipoPersona[100];
 
    persona[0].nombre = "Juan";
    persona[0].inicial = 'J';
    persona[0].edad = 20;
    persona[0].nota = 7.5f;
    Console.WriteLine("La edad de {0} es {1}", 
      persona[0].nombre, persona[0].edad);
 
    persona[1].nombre = "Pedro";
    Console.WriteLine("La edad de {0} es {1}", 
      persona[1].nombre, persona[1].edad);
    }
}
 



Para crear un struct que contenga un array, es igual que un struct normal, pero acordándote de usar "new" para reservar espacio para el array cuando vas a dar valores. Por ejemplo, se podría partir del ejemplo 39 y ampliarlo así:

 
/*---------------------------*/
/*  Ejemplo en C# nº 40b:    */
/*  ejemplo40b.cs            */
/*                           */
/*  Struct que contiene un   */
/*  array                    */
/*                           */
/*  Introduccion a C#,       */
/*    Nacho Cabanes          */
/*---------------------------*/
 
using System;
 
public class Ejemplo39
{
 
  struct tipoPersona
  {
    public string nombre;
    public char   inicial;
    public int    edad;
    public float[]  nota;
  }
 
  public static void Main()
  {
    tipoPersona persona;
 
    persona.nombre = "Juan";
    persona.inicial = 'J';
    persona.edad = 20;
 
    persona.nota = new float[3];
    persona.nota[0] = 7.5f;
    persona.nota[1] = 8.2f;
    persona.nota[2] = 9;
 
    Console.WriteLine("La edad de {0} es {1}",
      persona.nombre, persona.edad);
    }
}
 


Si sigues ese mismo esquema de forma ordenada, lo podrías aplicar a un ejemplo de varios niveles, como el que propones.


28-Jan-2011 20:21
Jos Antonio Pla

Muchas gracias por tu respuesta pero al final me he decidido por crear una clase atleta y otra clase club y declaro 3  atletas en la clase club. He creado un método para sobrecargar y otro para mostrar por pantalla los datos. Me compila pero al ejecutar da un error que no soy capaz de depurar. ¿Me podrías echar una mano?.

 
 
using System;
 
public class Atleta
{
    public int id_atleta;
	public string nombre_atleta;
	public int[] metros = new int[3];
}
 
 
public class Club:Atleta
{
	protected int id_club;
	protected string nombre_club; 
 
	Atleta[] misAtletas=new Atleta[3];
 
	public void SobrecargarClub (int id_club, string nombre_club, int id_atleta1, int id_atleta2, int id_atleta3, string nombre_atleta1, string nombre_atleta2, string nombre_atleta3, int metros1, int metros2, int metros3, int metros4, int metros5, int metros6, int metros7, int metros8, int metros9)
	{
		this.id_club=id_club;
		this.nombre_club=nombre_club;
		this.misAtletas[0].id_atleta=id_atleta1;
		this.misAtletas[1].id_atleta=id_atleta2;
		this.misAtletas[2].id_atleta=id_atleta3;
		this.misAtletas[0].nombre_atleta=nombre_atleta1;
		this.misAtletas[1].nombre_atleta=nombre_atleta2;
		this.misAtletas[2].nombre_atleta=nombre_atleta3;
		this.misAtletas[0].metros[0]=metros1;
		this.misAtletas[0].metros[1]=metros2;
		this.misAtletas[0].metros[2]=metros3;
		this.misAtletas[1].metros[0]=metros4;
		this.misAtletas[1].metros[1]=metros5;
		this.misAtletas[1].metros[2]=metros6;
		this.misAtletas[2].metros[0]=metros7;
		this.misAtletas[2].metros[1]=metros8;
		this.misAtletas[2].metros[2]=metros9;
	}
 
	public void Menu()
	{
		Console.WriteLine("* * * * * * * * * * * * * * * * * * * * * * *");
		Console.WriteLine("* 1. Modificar datos                        *");
		Console.WriteLine("* 2. Mostrar lista de club/atleta por pais  *");
		Console.WriteLine("* 3. Atletas con lanzamiento superior a     *");
		Console.WriteLine("* 4. Promedio de tres lanzamientos          *");
		Console.WriteLine("* 5. Datos del mejor atleta de cada club    *");
		Console.WriteLine("* 6. 10 mejores atletas de la Olimpiada     *");
		Console.WriteLine("* 0. Salir                                  *");
		Console.WriteLine("* * * * * * * * * * * * * * * * * * * * * * *");
		Console.WriteLine();
		Console.WriteLine("Opcion?: ");
	}
 
	public void MostrarDatosClubes()
	{
		Console.WriteLine("Id del club: {0} ", id_club);
		Console.WriteLine("Nombre del club: {0} ", nombre_club);
		Console.WriteLine("Id primer atleta: {0} ", misAtletas[0].id_atleta);
		Console.WriteLine("Id segundo atleta: {0} ", misAtletas[1].id_atleta);
		Console.WriteLine("Id tercer atleta: {0} ", misAtletas[3].id_atleta);
		Console.WriteLine("Id primer atleta: {0} ", misAtletas[0].id_atleta);
		Console.WriteLine("Nombre del primer atleta: {0} ", misAtletas[0].nombre_atleta);
		Console.WriteLine("Nombre del segundo atleta: {0} ", misAtletas[1].nombre_atleta);
		Console.WriteLine("Nombre del tercer atleta: {0} ", misAtletas[2].nombre_atleta);
		Console.WriteLine("Primer salto del primer atleta: {0} ", misAtletas[0].metros[0]);
		Console.WriteLine("Segundo salto del primer atleta: {0} ", misAtletas[0].metros[1]);
		Console.WriteLine("Tercer salto del primer atleta: {0} ", misAtletas[0].metros[2]);
		Console.WriteLine("Primer salto del segundo atleta: {0} ", misAtletas[1].metros[0]);
		Console.WriteLine("Primer salto del segundo atleta: {0} ", misAtletas[1].metros[1]);
		Console.WriteLine("Primer salto del segundo atleta: {0} ", misAtletas[1].metros[2]);
		Console.WriteLine("Primer salto del tercer atleta: {0} ", misAtletas[2].metros[0]);
		Console.WriteLine("Primer salto del tercer atleta: {0} ", misAtletas[2].metros[1]);
		Console.WriteLine("Primer salto del tercer atleta: {0} ", misAtletas[2].metros[2]);
		Console.WriteLine();
	}
}
 
 
public class Ejemplo59
{
	public static void Main()
	{	
		//Array de objetos
		Club[,] misClubes=new Club[2,2];//Asi se declara un array bidimensional de objetos
 
		misClubes[0,0].SobrecargarClub(1, "Colivenc", 1, 2, 3, "Federico", "Pablo", "Roberto", 67, 64, 68, 61, 62, 63, 69, 60, 58);	
		misClubes[0,1].SobrecargarClub(1, "Sant Joan", 4, 5, 6, "Alberto", "Rodrigo", "Jose", 70, 65, 66, 45, 46, 63, 55, 60, 62);	
		misClubes[1,0].SobrecargarClub(1, "Alcoi", 7, 8, 9, "Norberto", "Juan", "Pedro", 49, 57, 64, 50, 57, 65, 69, 60, 58);	
		misClubes[1,1].SobrecargarClub(1, "Amigos de las montanyas", 10, 11, 12, "Teodorico", "Alfredo", "Francisco", 65, 36, 72, 42, 59, 66, 64, 72, 73);	
 
		misClubes[0,0].MostrarDatosClubes();
	}
}
 



29-Jan-2011 13:51
Nacho Cabanes (+30)

En primer lugar, si dices cual es el error que te da, será más fácil ayudarte y que la respuesta sea concreta. Aun así, con ese fuente, veo que tendrás al menos un error en ejecución y varios errores de concepto:

- El error en tiempo de ejecución será que te falta un "new" para cada objeto: cuando un array no es de estructuras (struct) sino de objetos (class), debes usar "new" para el array y también para cada objeto, como puedes ver en el apartado 6e de la versión online del curso:

http://www.aprendeaprogramar.com/mod/resource/view.php?id=408


- Uno de los errores de concepto está en la línea:

public class Club : Atleta

Esa línea dice que la clase Club es una clase hija de Atleta, es decir, que un Club es un tipo de Atleta, algo que no tiene mucho sentido en el mundo real.


- Otro de los errores de concepto está en la línea:

public void SobrecargarClub (int id_club, ...

Eso no es sobrecargar, sino introducir datos. La palabra "sobrecargar" se refiere a cuando tienes dos funciones que se llaman igual pero se aplican a objetos de distinto tipo.


- Y algunas cosas están hechas de forma que funciona pero que es muy engorrosa. Por ejemplo, las 9 líneas

Console.WriteLine("Primer salto del primer atleta: {0} ", misAtletas[0].metros[0]);
Console.WriteLine("Segundo salto del primer atleta: {0} ", misAtletas[0].metros[1]);
Console.WriteLine("Tercer salto del primer atleta: {0} ", misAtletas[0].metros[2]);
Console.WriteLine("Primer salto del segundo atleta: {0} ", misAtletas[1].metros[0]);
Console.WriteLine("Primer salto del segundo atleta: {0} ", misAtletas[1].metros[1]);
Console.WriteLine("Primer salto del segundo atleta: {0} ", misAtletas[1].metros[2]);
Console.WriteLine("Primer salto del tercer atleta: {0} ", misAtletas[2].metros[0]);
Console.WriteLine("Primer salto del tercer atleta: {0} ", misAtletas[2].metros[1]);
Console.WriteLine("Primer salto del tercer atleta: {0} ", misAtletas[2].metros[2]);

se podrían hacer en 3 líneas, usando dos bucles "for", algo como

for (int atleta = 0; atleta < 3; atleta ++)
   for (int salto = 0; salto < 3; salto ++)
       Console.WriteLine("´Salto {0} del atleta {1}: {2} ",
          salto+1, atleta+1, misAtletas[atleta].metros[salto]);


- Otra mejora deseable son los nombres de los métodos (las funciones): algo como

misClubes[0,0].MostrarDatosClubes();

es redundante. Quedaría mejor

misClubes[0,0].MostrarDatos();

(ya se sabe que ese "MostrarDatos" pertenece a la clase Club, no es necesario detallarlo también en el nombre de la función).


02-Feb-2011 10:30
Jos Antonio Pla

Perdón por haber respondido al correo personal, la verdad es que pensaba que estaba respondiendo en el foro. La pregunta era:

Muchas gracias otra vez. Me lío con la POO. Yo lo único que busco es que cada club tenga tres atletas y cada atleta tres saltos. ¿Me podrías indicar conceptualmente cuál es el modo más óptimo?.¿Dos clases (atleta y club) y que atleta herede los atributos de club o una sola clase atleta que contenga los atributos id_club y nombre_club?¿Otra opción?.

Saludos.


03-Feb-2011 13:30
Nacho Cabanes (+30)

En principio, lo más razonable parece:

- Si los saltos son datos numéricos, no haría falta crear una clase, sino que se podría usar un dato "int" si mides en centímetros o un "float" si mides en metros.

- Si un atleta debe tener varios datos (como su nombre o los datos de sus saltos), y realizar alguna operación, debería ser una clase.

- Y si un club debe tener varios datos (como su nombre, su id, o sus saltadores), y realizar alguna operación, debería ser una clase.

- Un club contendría saltadores, pero nadie "hereda" de nadie, porque ni un saltador es un tipo de club, ni un club es un tipo de saltador.

El problema de tu planteamiento (creo) es que estás pensando en bases de datos relacionales, no en clases. Son formas de trabajar distintas.


Si entrar a los detalles de id_club y nombre_club, que no añaden dificultad, y centrándome en los arrays, que es lo que sí tiene algo de complicación, se podría hacer así:

 
// ----------------------
 
using System;
 
public class Club
{
  Saltador[] saltadores;
  int maxSaltadores;
  int numeroSaltadores;
 
  public Club()
  {
    maxSaltadores = 3;
    numeroSaltadores = 0;
    saltadores = new Saltador[ maxSaltadores ];
  }
 
  public void AnyadirSaltador( Saltador s )
  {
    if (numeroSaltadores < maxSaltadores)
    {
      saltadores[ numeroSaltadores ] = s;
      numeroSaltadores ++;
    }
  }
}
 
// ----------------------
 
public class Saltador
{
  int[] saltos;
  int maxSaltos;
  int numeroSaltos;
 
  public Saltador()
  {
    maxSaltos = 3;
    numeroSaltos = 0;
    saltos = new int[ maxSaltos ];
  }
 
  public void AnyadirSalto( int s )
  {
    if (numeroSaltos < maxSaltos)
    {
      saltos[ numeroSaltos ] = s;
      numeroSaltos ++;
    }
  }
 
}
 
// ----------------------
 
public class ClubesDeportivos
{
  public static void Main()
  {
    Club[,] clubes = new Club[2,2];    
 
    Saltador s1 = new Saltador();
    s1.AnyadirSalto( 250 );
    s1.AnyadirSalto( 540 );
    s1.AnyadirSalto( 610 );
 
    clubes[0,0] = new Club();    
    clubes[0,0].AnyadirSaltador( s1 );
 
    Console.WriteLine("Terminado");
  }
}
 







(No se puede continuar esta discusión porque tiene más de dos meses de antigüedad. Si tienes dudas parecidas, abre un nuevo hilo.)