Funcion que devuelva un tipo [Len. C]

Leunamal

Hola, haber si me podeis echar una mano. Estoy ralladisimo con un ejercicio.

Vereis, tengo que hacer el tres en raya. Y bueno, lo primero de todo es crear las estructuras, pues llevo ya 2 dias intentado hacerlas pero siempre me falla al compilar.

Quiero crear un tipo que se llame Tablero, para que pueda hacer:

Tablero CrearTablero(void);

Tablero deberia ser una matriz del tipo Ficha (da = como este definida el tipo Ficha) de 3x3. Pues buff, no se como hacerlo.

Creo que la solucion puede estar cerca de un puntero a matriz, o un puntero a puntero a matriz. Cerca de esto:
"typedef Ficha (*TTablero)[3][3] Tablero;"

Si alguien sabe por donde podrían ir los tiros que me ayude plz.

Un saludo

cabron

No puedes declarar una estructura usando Tablero CrearTablero(void); aunque hayas definido el tipo con typedef, tienes que usar struct Tablero CrearTablero(void);

Leunamal

pues mmm creo que no.

Fijate por ejemplo en los TAD's de pilas, colas, listas, etc...

En ese tipo de datos, se puede hacer por ejemplo:
" Pila CrearPila(void);" perfectamente, sin poner struct.

Un saludo

cabron

Cierto, si usas typedef no hace falta, es solo si defines la estrucutra sin typedef, así:

struct miestructura{
int a;
int b;
};

Entonces cada vez que quieras declarar una estructura lo tienes que hacer con :

struct miestructura j;

Te lo estoy diciendo todo de memoría y hace bastante que no uso C así que me puedo colar, pero bueno, diría que lo que quieres hacer es así:

typedef ficha* tablero[3][3];

Eso suponiendo que ficha esté también decladara con typedef, si ficha es un tipo de estructura definido sin typedef sería:

typedef struct ficha* tablero [3][3];

Eso te crea un tipo de datos llamado tablero, y cada vez que declares una variable con:

tablero t;

t es ahora un puntero a un array de estrucutras ficha de 3x3

Leunamal

Gracias de nuevo tio, ya va tomando forma la cosa ^. Si comento la linea de :
" Tablero CrearTablero(void); "
ó
" struct Tablero CrearTablero(void); "

pues ya no da fallo de compilación. Pero la tengo que descomentar para hacer el ejercicio. Y da el siguiente el siguiente error de compilacion (muy previsible jeje):

"..\juego.h `CrearTablero' declared as function returning an array "
"..\juego.c [Warning] return makes integer from pointer without a cast "
"..\juego.c [Warning] function returns address of local variable "

Voy a seguir investigando haber como puedo solucionar eso. Es lo que comentaste antes, que se devuelve es la dirección de memoria (o el puntero al array). Lo que no comprendo yo es porque el compilador me avisa de eso, si yo realmente deseo devolver eso.

Un saludo y gracias por dedicar tu tiempo en ayudarme ^^

maRc

"..\juego.h `CrearTablero' declared as function returning an array "
Que devuelves un vector.

"..\juego.c [Warning] return makes integer from pointer without a cast "
Que conviertes un puntero a entero sin hacer un casting.

"..\juego.c [Warning] function returns address of local variable "
Que devuelves la dirección de una variable local, variable que cuando acabe la función, desaparecerá y tendrás un puntero apuntando a Pamplona.

Leunamal

pues si jeje. Ese es el problemilla. Que se queda un puntero apuntando a Pamplona jeje.

Pongo aqui el juego.c (Esta incorrecto, dan los fallos dados anteriormente):

Tablero CrearTablero(void)
{
int i,j;
Tablero t;

for(i=0;i<=3;i++){
for(j=0;j<=3;j++){
*t[0][0]=' '; //<==== AQUI ESTA LA CLAVE
}
}

return t;
}


El problemilla esta en el manejo de punteros, ya podrian haber puestos en las prácticas de clase ejercicios de este tipo y no ejemplos tan tontos.

No se como almacenar datos en la linea seleccionada.

SI quereis ver el .h, pues os lo pongo tmb:
//Fichero de cabecera juego.h

#ifndef JUEGO
#define JUEGO

typedef struct{
int x,y;
} posicion;

struct Ficha{
posicion pos;
char TipoFicha;
};


typedef struct ficha (*TTablero)[3][3];

typedef TTablero *Tablero; //Posible fallo aqui, aunque no detectado por compilación


typedef enum{jugador1,jugador2}jugador;

Tablero CrearTablero(void);

#endif


Saludos

javithelong

Mmmm, creo que hay cosas raras aqui, a ver:

El tablero lo estas creando como una matriz de 3x3 de punteros a fichas, es eso lo que quieres? o una matriz de 3x3 de fichas y punto (mas fácil lo segundo, creo yo)

typedef struct{
int x,y;
} posicion;

typedef struct T_Ficha{
posicion pos;
char TipoFicha;
} Ficha;

typedef Ficha[3][3] tablero;

Esta estructura de datos creo que te funcionará mejor :P

EDIT:
Ah, y en CrearTablero, al rellenar las 9 posiciones, no puedes meter un espacio asi, porque no es un array de caracteres, sino un array de fichas, entonces tendrás que poner t[j].TipoFicha para ponerla vacía

Saludos

Leunamal

ajam, pues ya me diras tu de que tipo es la matriz que has creado ;) lo de llenar los datos en la matriz tienes toda la razon. Eso debe de estar mal fijo. Haber si mezclando ideas se consigue resolver el problema.

Por cierto, que puse en el post anterior, supuestamente es un puntero a una matriz. Pero vamos, que tiene que estar chunguillo. Haber si llega el Miércoles para poder preguntarle al profesor en las prácticas

Si encuentro algo, lo posteo por aqui.

Un saludo

LOc0

Si pones TODO el código a lo mejor podemos dar en el clavo.

Salu2 ;)

javithelong

Lo que yo he creado no es una matriz de punteros a fichas, es una matriz de fichas a secas...

No es lo mismo:

ficha * tabla[3][3]; --> matriz de punteros a fichas (tendras que reservar memoria para cada ficha)

que esto:

ficha tabla[3][3]; --> matriz de fichas, la memoria se reserva en la declaracion de la variable

Suponiendo un tipo de dato ficha.
Para rellenar un dato, tienes que poner (con la segunda implementacion) tabla[j].TipoFicha = 'x';
Si tienes la 1º implementacion, despues de reservar memoria para la ficha, será
tabla[j]->TipoFicha = 'x';

No es lo mismo...

De todas formas, creo que te sobra lo de posicion x,y, porque ya en la matriz de fichas, con las posiciones en la tabla, te sobra para referenciar e identificar una ficha, pero bueno, eso ya es otro tema :P

Leunamal

L0c0 el codigo ya estaba puesto en el post nº #7 ^^


Javithelong lo de la matriz me referia a que pusiste:
"typedef Ficha[3][3] tablero;" Así tal como esta le falta el tipo,no? La matriz se llamaria Ficha pero no se le indica el tipo. Aunque posiblemente es que sea una variación a la hora de implementar matrices. Será lo más seguro y por eso me habría liado un poco. Siempre es bueno aprender nuevas formas. ^^

He puesto lo que sugieres:

typedef struct{
int x,y;
} posicion;

typedef struct T_Ficha{
posicion pos;
char TipoFicha;
} Ficha;

typedef Ficha[3][3] Tablero;

--

y me da el siguiente error al compilar:

..\juego.h syntax error before '[' token
..\juego.h syntax error before "CrearTablero"
..\juego.h [Warning] data definition has no type or storage class

Y muchos mas, pero que son derivados de estos.
Da fallo justamente en lo que comente antes. Una cosilla, a la hora de crear Ficha, juraria de que no haria falta poner:
"typedef struct T_Ficha{". Creo que bastaria con "typedef struct{" ya que lo que hace el typedef es sustituir lo que viene a continuación por la palabra puesta despues de la definición.
Si estoy equivocado corregirme ,plz.

Un saludoo y gracias a todos por contestar :)

javithelong

""typedef Ficha[3][3] tablero;" Así tal como esta le falta el tipo,no?"

Ficha es el tipo, y a una matriz de 3x3 de tipos de dato Ficha, le llamas tablero, que es otro tipo de dato. Luego en tu programa declaras tablero t; y ya juegas con él.

Ahora me haces dudar si se pueden poner definiciones asi, con matrices, es algo que nunca he hecho porque no le he visto sentido xD
Igual que pones, por ejemplo:

typedef char * pchar;

Y te defines un tipo de dato puntero a char que se llama pchar, poniendo:

typedef Ficha[3][3] tablero;

Defines un tipo de dato tablero, que es una matriz de 3x3 de fichas. Ara ya te he dicho, me haces dudar se pueden poner matrices asi (el error ese que te da de [)

Si te obligan a utilizar esta estructura de datos, no puedo ayudarte, porque no se, si puedes poner la estructura de datos que te apetezca, ponlo, que te describo la que pondría yo.

Un saludo

javithelong

Acabo de caer, prueba esto:

typedef Ficha tablero[3][3];

Leunamal

Tampoco me deja :( Fue lo que puse el otro dia cuando lo pusiste pensando de que se te olvido el tipo. Yo creo que para hacer este tipo de ejercicios, habria que definir o mejor dicho almacenar los datos en una estructura que no sea la tipica matriz de c. Quizas gestionando memoria con mallocs pues se podria crear la definicion del tipo en condiciones.

Hoy preguntó un compañero de clase al profesor de Estructura de Datos I la misma duda que tengo yo, sobre cómo crear el tipo Tablero, y el profesor le comentó de que es mas fácil pasar la matriz como parametro dela funcion CrearTablero. Pero vamos.. es la solución trivial.

Mañana si eso le pregunto, haber que me dice. Aunque creo que usando mallocs dudo que sea dificil.

Un saludo

Carcass

No puedes devolver una variable local de una función, ya que se crea en la pila de esta y se elimina al volver. Tendrías que devolver un puntero a una creada en el montón (con new, malloc o lo que sea) o, como bien dice tu profesor, pasar la variable a rellenar a la función:

void CrearTablero(Tablero *t) {
&nbsp;&nbsp;int i,j;

&nbsp;&nbsp;for(i=0;i<=3;i++) {
&nbsp;&nbsp;&nbsp;&nbsp;for(j=0;j<=3;j++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t[j] = ' ';
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;}
}

Como bien hacen en COM y CORBA, es mejor pasar así los parámetros de retorno y puedes usar el retorno para indicar si se realizó bien la tarea o no.

int CrearTablero(Tablero *t) {
&nbsp;&nbsp;int i,j;

&nbsp;&nbsp;for(i=0;i<=3;i++) {
&nbsp;&nbsp;&nbsp;&nbsp;for(j=0;j<=3;j++) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t[j] = ' ';
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;}

&nbsp;&nbsp;if(hahabidoalgúnerror) {
&nbsp;&nbsp;&nbsp;&nbsp;return códigodeerror;
&nbsp;&nbsp;} else {
&nbsp;&nbsp;&nbsp;&nbsp;return 0;
&nbsp;&nbsp;}
}

Algo así X-)

FraY

Hoy por fin tuve las clases de Estructura de Datos, y bueno.. el profesor probando todo lo que hice yo y nada.. Y al final me dijo que lo hiciese considerando Tablero como un puntero a Ficha. La idea es definirla como una pila de tamaño dinamico.

Se reserva memoria con el malloc y funciona perfect ^^

En cuanto en el post justamente anterior a este, se dice de que no se puede devolver variables locales a una función, pues bien. Si se pueden devolver, lo que no se puede es ACCEDER a esas variables fuera del ambito de la misma, es decir, intentar acceder a una variable que esta está situada en una función desde fuera de la misma.
Supongo que lo te habrá liado un poco, es que no viste el main.c donde se declara una variable t de tipo Tablero,y se pone a continuación el cansino:
"t=CrearTablero();"
Espero haberte aclarado eso ^.

En cuanto termine de hacer varias cosillas que tengo pendientes, pongo el codigo fuente, del CrearTablero y de la definición de los tipos.

Lo probé en clase y funcionan perfecto. El inconveniente que he encontrado es que he pasado de usar una matriz a un vector dinámico. Por lo que los dos bucles for que use antes, pasaría a ser un bucle que iria desde el elemento 0 hasta el 8. Ya que el tablero tiene 9 huecos para colocar fichas.

Pues eso, que luego posteo el código por si alguna vez os pasa algo parecido y no sepais como resolvero.

Un saludo

Leunamal

El de antes era yo, que sin querer he posteado con la cuenta de mi hermano.

Disculpadme
Hasta luego

Carcass

Puedes devolver una copia, nunca una referencia a una variable local. Bueno, por poder, puedes... Pero nadie te asegura que esa zona de memoria vaya a seguir conteniendo lo que crees que hay X-D

Leunamal

Puedes y no deberia de devolverte mierda si a la hora de llamar la funcion, ésta devuelve "algo" y se le asigna ese "algo" a un variable declarada previamente.

Os pongo el código:


#ifndef JUEGO
#define JUEGO

typedef struct{
int x,y;
} posicion;

typedef struct {
posicion pos;
char TipoFicha;
} Ficha;

typedef Ficha *Tablero;

typedef enum{jugador1,jugador2}jugador;

Tablero CrearTablero(void);

#endif


//Fichero de código : juego.c

#include <stdlib.h>
#include <stdio.h>
#include "error.h"
#include "juego.h"

Tablero CrearTablero(void)
{
int i,j;
Tablero t;

t=(Ficha )malloc(9sizeof(Ficha));

if(t==NULL)
Error("CrearTablero: No hay memoria");


for(i=0;i<=9;i++){
t.TipoFicha=' ';
}

return t;
}

Usuarios habituales

  • Leunamal
  • Carcass
  • FraY
  • javithelong
  • LOc0
  • maRc
  • cabron