Programación en C

xWeST

Forista Legendario
Registrado
10 Feb 2011
Mensajes
11.822
Reacciones
267
La cosa va de estructuras de datos, punteros y tipos.

Quiero crear una lista de estructuras de datos sin definir: véase char, struct, int o incluso una compuesta... la cosa está en una lista de nodos de cualquier tipo, por ejemplo:

char dato y char *siguiente
tJugador jugador y tJugador *siguiente
int n y int *siguiente

Podría crear una estructura void dato y void *siguiente definiendo el tamaño de void? También veo posible hacerla con char y haciendo un cast en función del tamaño pero no sé como sería.

No sé si me he explicado bien. Vamos esos programadores que seguro que somos unos cuantos.
 
C

chanfr

Invitado
xWeST;11116077 dijo:
La cosa va de estructuras de datos, punteros y tipos.

Quiero crear una lista de estructuras de datos sin definir: véase char, struct, int o incluso una compuesta... la cosa está en una lista de nodos de cualquier tipo, por ejemplo:

char dato y char *siguiente
tJugador jugador y tJugador *siguiente
int n y int *siguiente

Podría crear una estructura void dato y void *siguiente definiendo el tamaño de void? También veo posible hacerla con char y haciendo un cast en función del tamaño pero no sé como sería.

No sé si me he explicado bien. Vamos esos programadores que seguro que somos unos cuantos.

Me temo que lo que pies no se puede hacer, al menos no de forma tan simple... tu que puedes definir un void* y luego hacer un cast a que tipo de dato esta apuntado, pero no puedes definir un void dato, porque void en sí no existe... solo existe void* que es una referencia a una posición de memoria de la que no tienes información de la que hay dentro.

que es lo que quieres exactamente?? que la misma lista contenga nodos de distintos tipos?? para esto te puedes definir nodos de distinto tipo y hacer que el punto de referencia al siguiente nodo sea un void* y hacer un cast cuando lo quieras utilizar.. para para esto tienes que tener control de lo que hay en cada nodo de la lista...
 

xWeST

Forista Legendario
Registrado
10 Feb 2011
Mensajes
11.822
Reacciones
267
chanfr;11116571 dijo:
Me temo que lo que pies no se puede hacer, al menos no de forma tan simple... tu que puedes definir un void* y luego hacer un cast a que tipo de dato esta apuntado, pero no puedes definir un void dato, porque void en sí no existe... solo existe void* que es una referencia a una posición de memoria de la que no tienes información de la que hay dentro.

que es lo que quieres exactamente?? que la misma lista contenga nodos de distintos tipos?? para esto te puedes definir nodos de distinto tipo y hacer que el punto de referencia al siguiente nodo sea un void* y hacer un cast cuando lo quieras utilizar.. para para esto tienes que tener control de lo que hay en cada nodo de la lista...

No, lo que quiero es crear por ejemplo una lista de enteros, otra de carácteres, otra de estructuras llamadas jugador... de lo que sea. La idea sería no tener que definir cada lista por separado sinó hacer el cast y coger el tipo solo teniendo una lista.
 
C

chanfr

Invitado
xWeST;11120420 dijo:
No, lo que quiero es crear por ejemplo una lista de enteros, otra de carácteres, otra de estructuras llamadas jugador... de lo que sea. La idea sería no tener que definir cada lista por separado sinó hacer el cast y coger el tipo solo teniendo una lista.

Mmm.. quieres definir una lista de un tipo abstracto y luego poder hacer un cast de esta lista a un tipo de lista que ya tienes definido?? pero para manejar esto siempre vas a necesitar saber el tipo de la lista que vas a manejar... creo que no termino de entender la idea... aún así si tienes la posibilidad de definirte los tres tipos te va a quedar el código mucho mas limpio.. cuantos menos casts tengas que hacer mejor....
 

xWeST

Forista Legendario
Registrado
10 Feb 2011
Mensajes
11.822
Reacciones
267
chanfr;11121975 dijo:
Mmm.. quieres definir una lista de un tipo abstracto y luego poder hacer un cast de esta lista a un tipo de lista que ya tienes definido?? pero para manejar esto siempre vas a necesitar saber el tipo de la lista que vas a manejar... creo que no termino de entender la idea... aún así si tienes la posibilidad de definirte los tres tipos te va a quedar el código mucho mas limpio.. cuantos menos casts tengas que hacer mejor....

Supongo que es lo que acabaré haciendo, pero ahora ya es por curiosidad :descojon:

La idea es hacer un

def tLista **void {
void (dato);
void *(siguiente);
} struct;

y luego ir haciendo los casts oportunos para poder hacerlo como int, char o cualquier otro dato definido haciendo el cast. Tendría que saber el tamaño del tipo: size(datoAEntrarEnLista);

Yo tengo la idea clara, pero técnicamente creo que no es posible. No sé si me estoy explicando bien.
 
C

chanfr

Invitado
Lo que se me ocurre que puedes hacer:

typedef struct ElementoLista {
void *dato;
struct ElementoLista *siguiente;
}Elemento;

de esta forma tienes el nodo siempre del mismo tamaño, son dos punteros, a la hora de reservar memoria para un puntero no le hace falta saber a que esta referenciando.

con esto ya puedes utilizar malloc para reservar memoria para el tipo que quieras y hacer que dato referencie a esa memoria.

Pero sigo diciendo que no es muy óptimo por el control exhaustivo y manual que debes tener en cuenta para que todo cuadre y no tengas problemas con los casts...
 

xWeST

Forista Legendario
Registrado
10 Feb 2011
Mensajes
11.822
Reacciones
267
Mira, esta función por ejemplo intercambia dos datos sean del tipo que sean, la usé en otro proyecto con sus respectivos casts y sin problema.

Código:
void intercanvia (char *a, char *b, int length) {
    char *aux;
    int i;
    aux = (char*) malloc (length);
    for (i = 0; i < length; ++i) {
        aux[i] = a[i];
        a[i] = b[i];
        b[i] = aux[i];
    }
    free(aux);
}

La diferencia que veo ahora es que char, que es el tipo de datos básico debería declararse dinámicamente dentro de la función haciendo el cast dentro cada vez según el tipo que sea.
 
C

chanfr

Invitado
xWeST;11123076 dijo:
Mira, esta funci&#243;n por ejemplo intercambia dos datos sean del tipo que sean, la us&#233; en otro proyecto con sus respectivos casts y sin problema.

Código:
void intercanvia (char *a, char *b, int length) {
    char *aux;
    int i;
    aux = (char*) malloc (length);
    for (i = 0; i < length; ++i) {
        aux[i] = a[i];
        a[i] = b[i];
        b[i] = aux[i];
    }
    free(aux);
}

La diferencia que veo ahora es que char, que es el tipo de datos b&#225;sico deber&#237;a declararse din&#225;micamente dentro de la funci&#243;n haciendo el cast dentro cada vez seg&#250;n el tipo que sea.

Ufffffff bastante trillado... Recorrer memoria con chars... Esto de trabajar con tipos que no conoces puede ser peligroso sobre todo cuando trabajas con memoria din&#225;mica..
Para el intercambio que has hecho pod&#237;as utilizar directamente memcpy y te ahorras tener que recorrer con char* algo que no es una cadena de char... Si no te queda mas remedio utiliza el tipo que te he puesto antes.. Con eso no tienes que saber el tipo "dato" que tienes dentro del nodo ya que solo lo apuntas con un puntero... Pero como te digo si lo puedes evitar...
 

xWeST

Forista Legendario
Registrado
10 Feb 2011
Mensajes
11.822
Reacciones
267
d.perez768;11124083 dijo:
xWest donde estudias? En la UAB?

Si lo dices por la función: sí, puede que os la hayan pasado en alguna clase o práctica, al profesor le gustó mucho el tema de los casts :descojon::descojon: puedes odiarme! :goodman :descojon::descojon:

chanfr;11124296 dijo:
Ufffffff bastante trillado... Recorrer memoria con chars... Esto de trabajar con tipos que no conoces puede ser peligroso sobre todo cuando trabajas con memoria dinámica..
Para el intercambio que has hecho podías utilizar directamente memcpy y te ahorras tener que recorrer con char* algo que no es una cadena de char... Si no te queda mas remedio utiliza el tipo que te he puesto antes.. Con eso no tienes que saber el tipo "dato" que tienes dentro del nodo ya que solo lo apuntas con un puntero... Pero como te digo si lo puedes evitar...

Es tedioso, pero es solo una copia y te evita tener que hacer una función para cada tipo además que siendo memoria dinámica permite liberar la que no se usa. Veo complicada la solución del puntero que me propones.
 
Arriba