Título: Listas generales en C Publicado por: Fedex15 en 21 Abril 2017, 00:25 am Hola, estoy tratando de resolver un problema que se me pide con listas. Debo usar listas siguiendo la sig estructura:
Código
Tengo 3 archivos, el glist.h, glist.c, y main_g.c. Las funciones que tengo son las basicas, que me permiten crear, destruir, agregar final, agregar inicio, y recorrer. Código
El problema que estoy teniendo, es que ahora no estoy trabajando con listas donde el dato es un int, estoy trabajando con listas donde el dato es un puntero a void. Yo se que el puntero a void puede apuntar a cualquier tipo de dato, pero para poder desreferenciarlo tengo que aplicar el cast correspondiente al tipo de dato que guarda. Código
Este es el main que tengo: Código
Como podria hacer para poder saber cual es el tipo de dato al que apunta void. Como podria hacer lo que esta en la linea 20 Código
de forma general con la funcion imprimir_entero. El primer caso seria con un entero, un double y un char o cadena. Gracias Título: Re: Listas generales en C Publicado por: MAFUS en 21 Abril 2017, 11:08 am He intentado compilar el código y tiene muchos errores. Podría resolverlos pero, la verdad, me ha dado pereza. Si pudieras corregir el código para que no haya mas errores que el lógico que intentas resolver sería de agradecer.
Título: Re: Listas generales en C Publicado por: Fedex15 en 21 Abril 2017, 15:00 pm He intentado compilar el código y tiene muchos errores. Podría resolverlos pero, la verdad, me ha dado pereza. Si pudieras corregir el código para que no haya mas errores que el lógico que intentas resolver sería de agradecer. Gracias por responder, aca te dejo todo el codigo en un solo archivo: Código
yo lo compilo usando gcc listas.c -o lista, asi me funciona bien. PD: Aca te dejo unas modificaciones que estuve haciendo, haber si voy por buen camino. Código
Título: Re: Listas generales en C Publicado por: MAFUS en 21 Abril 2017, 19:30 pm No puedes, C no proporciona reflexión.
Pero gcc sí proporciona, gracias a una extensión del compilador, un operador typeof que sirve para obtener el tipo de un dato. https://gcc.gnu.org/onlinedocs/gcc/Typeof.html Por otra parte el estándar C11 tiene funciones genéricas las cuales se configuran mediante una macro especial. http://blog.smartbear.com/codereviewer/c11-a-new-c-standard-aiming-at-safer-programming/ Una forma de hacerlo es como la que estás realizando, marcar qué tipo de dato va a guardar la variable dato. Es decir, hacerlo a mano. Título: Re: Listas generales en C Publicado por: CalgaryCorpus en 24 Abril 2017, 01:41 am Cuando estas insertando, en estos momentos, con el codigo que presentas, indicas explicitamente el tipo de dato que esta siendo guardado., por ejemplo:
Código: dato_insertar(general, ENTERO, &b); luego te obligas a hacer un switch con ese tipo.dato_insertar(general2, DOUBLE, &num); dato_insertar(general3, CADENA, cadena); Tengo una solucion que elimina el switch posterior, aunque aun tienes que indicar el tipo de dato que usas al insertar. Sugiero crear un nuevo campo que guarde un puntero a una funcion que sepa imprimir el dato que estas agregando. Código: typedef struct _variante{ definir las funciones que saben imprimir, por ejemplo:int tipo; void* valor; void (*f)(void *); } variante; Código: void tipo_entero(void * pTipo) { printf("%d", *(int *)pTipo ); } Las otras funciones son similares, pero usan otros %d en el printf y otro cast. luego en dato_insertar simplemente se copia el puntero a funcion Código: void dato_insertar (dato datos, int tipo, void* d, void (*f)() ){ y esta funcion se invoca usando el nombre de la funcion a usar para imprimr. Nota que es solo el nombre de la funcion, No como siempre usas las funciones, con parentesis.datos->tipo = tipo; datos->valor = d; datos->f = f; } Código: dato_insertar(general, &b, tipo_entero ); y finalmente cuando quieras imprimir el dato, solo haces Código: dato.f(dato.valor); y esto imprimira de acuerdo a la funcion que usaste. Suerte! Título: Re: Listas generales en C Publicado por: Fedex15 en 24 Abril 2017, 02:59 am Cuando estas insertando, en estos momentos, con el codigo que presentas, indicas explicitamente el tipo de dato que esta siendo guardado., por ejemplo: Código: dato_insertar(general, ENTERO, &b); luego te obligas a hacer un switch con ese tipo.dato_insertar(general2, DOUBLE, &num); dato_insertar(general3, CADENA, cadena); Tengo una solucion que elimina el switch posterior, aunque aun tienes que indicar el tipo de dato que usas al insertar. Sugiero crear un nuevo campo que guarde un puntero a una funcion que sepa imprimir el dato que estas agregando. Código: typedef struct _variante{ definir las funciones que saben imprimir, por ejemplo:int tipo; void* valor; void (*f)(void *); } variante; Código: void tipo_entero(void * pTipo) { printf("%d", *(int *)pTipo ); } Las otras funciones son similares, pero usan otros %d en el printf y otro cast. luego en dato_insertar simplemente se copia el puntero a funcion Código: void dato_insertar (dato datos, int tipo, void* d, void (*f)() ){ y esta funcion se invoca usando el nombre de la funcion a usar para imprimr. Nota que es solo el nombre de la funcion, No como siempre usas las funciones, con parentesis.datos->tipo = tipo; datos->valor = d; datos->f = f; } Código: dato_insertar(general, &b, tipo_entero ); y finalmente cuando quieras imprimir el dato, solo haces Código: dato.f(dato.valor); y esto imprimira de acuerdo a la funcion que usaste. Suerte! Gracias por la respuesta, voy a ver que me sale. Ahora estoy haciendo un menu que me pidieron usando listas generales para crear listas de enteros. Título: Re: Listas generales en C Publicado por: CalgaryCorpus en 24 Abril 2017, 03:04 am La firma de la funcion modificada que propuse esta mala, o incompleta.
Dice Código: void dato_insertar (dato datos, int tipo, void* d, void (*f)() ){ deberia decir Código: void dato_insertar (dato datos, void* d, void (*f)(void *) ){ |