Foros del Web » Programación para mayores de 30 ;) » C/C++ »

Determinar el tipo de dato de una variable

Estas en el tema de Determinar el tipo de dato de una variable en el foro de C/C++ en Foros del Web. Hola maestros, mi duda en esta oportunidad es como puedo determinar el tipo de dato de una variable, por ejemplo si la variable es int ...
  #1 (permalink)  
Antiguo 09/09/2006, 16:31
Avatar de El_Metallick  
Fecha de Ingreso: noviembre-2002
Ubicación: Santiago, Chile
Mensajes: 1.718
Antigüedad: 21 años, 5 meses
Puntos: 16
Determinar el tipo de dato de una variable

Hola maestros, mi duda en esta oportunidad es como puedo determinar el tipo de dato de una variable, por ejemplo si la variable es int o es char o es long, etc, lo que necesito es hacer una funcion para agregar datos independiente del tipo de dato que sea y se me ocurrio hacer algo asi:

preguntar si el tipo de datos es un numero entero, un long, etc, entonces
variable = valor;
preguntar si el tipo de dato es un char o un arreglo de char (string) entonces
strcpy(variable,valor);

pero no se como lograrlo en C, espero su ayuda saludos
__________________
Haz la guerra en la cama y el amor donde se te de la gana...
El tiempo es el mejor maestro, lo único malo es que te mata...¡¡Aprovecha tu tiempo!!
  #2 (permalink)  
Antiguo 09/09/2006, 18:34
arm
 
Fecha de Ingreso: mayo-2006
Mensajes: 112
Antigüedad: 18 años
Puntos: 0
No estoy seguro haber entedido, pero puede utilizar
typeid(tipo).name
y te etornara en tempo de ejecucion el tipo de una varible.

(p.e)
int a;
.
.
.
typeid(a).name;


retorna.....mmm....no recuerdo bien (nucalo he nececitado) pero creo que es char*, que seria la cadena "int".

puedes utilizar un switch para selecionar la asignacion apropiada
__________________
-> La duda adecuada es un buen comienzo <-
  #3 (permalink)  
Antiguo 09/09/2006, 19:39
 
Fecha de Ingreso: abril-2006
Ubicación: Acapulco Gro. México
Mensajes: 483
Antigüedad: 18 años
Puntos: 2
en C?:

podrias usar un diseño, al estilo polimorfico de C++, pero tambien podria haber una solucion mas facil.

por ejemplo usar una estructura auto descriptiva.

enum Tipo { Char, Short, Int, Long, Float, Long, PChar, PInt , etc..};

union Data { char datac, short datas, int datai, float dataf, char* datapc, etc..};

struct TTipo
{
Tipo tipo;
Data dato;
};

y una vez que tienes esta estructura ya puedes hacer tus funcines que la usen siempre verificando o asignando el tipo de dato a manejar.

ejemplo:

void Asignar(TTipo *destino, const TTipo *origen)
{
if(origen->tipo == PChar)
{
strcpy(destino->datopc, origen->datopc);
destino->tipo = origen->tipo;
}
else
{
destino->datoi = origen->datoi;
destino->tipo = origen->tipo;
}

aqui el problema seria que cada que crearas una nueva estructura tendria que asignar el tipo que es.

por ejemplo:

TTipo* Crear(Tipo type, Data value)
{
TTipo *var = (TTipo*)malloc(sizeof(TTipo));
if(type == PChar)
{
var->tipo = type;
strcpy(var->datopc, value);
}
else
{
var->tipo = type;
var->datoi = value;
}
return var;
}

TTipo miint = Crear(Int, 1000);
TTipo micad = Crear(PCarh, "Cadena");

TTipo var;

Asignar(var, miint);

//ahora var es una cadena.(Copia de micad).


para hacer una suma la funcion seria similar solo que tienes que verificar el tipo de ambos operandos.


TAl vez hay una manera mas facil usando preprocesador, pero ahora no estoy muy creativo, jeje.

Saludos.
  #4 (permalink)  
Antiguo 09/09/2006, 20:16
Avatar de El_Metallick  
Fecha de Ingreso: noviembre-2002
Ubicación: Santiago, Chile
Mensajes: 1.718
Antigüedad: 21 años, 5 meses
Puntos: 16
gracias por las respuestas amigos, la verdad de las cosas es que lo que me respondes tu arm es C++ y necesito hacerlo en C y lo que me dices tu Nivel7 no lo logro entender del todo... saludos
__________________
Haz la guerra en la cama y el amor donde se te de la gana...
El tiempo es el mejor maestro, lo único malo es que te mata...¡¡Aprovecha tu tiempo!!
  #5 (permalink)  
Antiguo 10/09/2006, 02:05
 
Fecha de Ingreso: abril-2006
Ubicación: Acapulco Gro. México
Mensajes: 483
Antigüedad: 18 años
Puntos: 2
Bueno, en realidad no pense que seria complicado,

te explico.
la enun Tipo es para crear las constantes que se usaran en un if o switch para saber el tipo que estamos manejando.

tambien se puede hacer:

#define CHAR 1
#define SHORT 2
#define INT 3
#define PCHAR 4
//etc...

y la union la use para evitar crear una estructura con un miembro de cada tipo:

//usando las constantes declaradas con define
//y sin la union Data

struct Var
{
int tipo
char cdat;
short sdat;
int idat;
char* pcdat;
//etc...
};

de esta forma
la estructura Var puede contener cualquier tipo, y ademas un campo que describe el tipo contenido.

ya que en C los tipos no se describen asi mismos mas que por el tamaño en bytes en la memoria, y este no te sirbe de mucho, ya que un int es igual a todos los tipos puntero, es decir 4 bytes.

ose:

sizeof(char) es 1;
sizeof(short) es 2;
sizeof(int) es 4;
sizeof(long) puede ser 4 u 8.
y
sizeof(char*) es 4;
sizeof(void*)es 4;
sizeof(long*) es 4;

asi que te seria dificil diferenciar un int de un puntero, y peror diferenciar un tipo de puntero en particular.


pero usando la estructura con el descriptor de tipo, ya podemos saber de que tipo se trata la variable que estamos usando,
es decir si quieres crear un int ya no usarias int sino:

Var varInt = Crear(INT , 100);

para crea<r una cadena:

Var varstr = Crear(PCHAR, "Cadena");

la funcion Crear podria ser como te mencione en el mensage anterior.

//use un puntero a void, pues no hay en este caso una union
//y la funcion teiene que aceptar cualquier valor o cadena.
Var* Crear(int tipo, void* dato)
{
Var* var = malloc(sizeof(Var));
switch(tipo)
{
case PCHAR:
var->tipo = tipo;
strcpy(var->pcdat, (char*)dato;
break;
case INT:
var->tipo = tipo;
var->idat = *((int*)dato);
break;
//etc..
}
return var;
}

ejemplo;

main()
{
char elNombre[40];
int laEdad;
Var nombre ;
Var edad;

scanf("%s %i", elNombre, &laEdad);

nombre = Crear(PCHAR, elNombre);
edad = Crear(INT, la Edad);

//una vez que ya tienes las variables con su valor y tipo respectivo ya
//puedes utilizarlas segun quieras.
};

por ejemplo, pordrias crear una funcion sumar, que sume los numeros y las cadenas las concatene, y que si sumas un numero y una cadena segun la pocicion de cada openrando:
por ejemplo, si cadena esta antes que numero, numero se convierte a cadena y se concatenan, si numero esta antes que cadena, cadena se convierte a numero y se suman. etc.

Var* Sumar(Var* op1, Var* op2)
{
Var* var = malloc(sizeof(Var));
switch(op1->tipo)
{
case PCHAR:
var->tipo = op1->tipo;
strcpy(var->dato, op1->dato);
if(op2->tipo == INT)
{
strcat(var->dato, (la converion a cad de op2->dato));
}
else
{
strcat(var->dato, op2->dato);
}
break;
case INT:
var->tipo = INT;
if(op2->tipoPCHAR)
{
var->dato = op1->dato + (laconvercion a int de op2->dato);
}
else
{
var->dato = op1->dato + op2->dato;
}
break;
}
return var;
}

podrias usarla en el programa:

Var* misdatos = Sumar(nombre, edad);
el resultado seria: (nisdatos->dato) "un nombre 27";
//la inversa en este caso no se puede.

en fin podria usarse de muchas formas.

Saludos.

Última edición por Nivel7; 10/09/2006 a las 02:13
  #6 (permalink)  
Antiguo 10/09/2006, 12:25
Avatar de El_Metallick  
Fecha de Ingreso: noviembre-2002
Ubicación: Santiago, Chile
Mensajes: 1.718
Antigüedad: 21 años, 5 meses
Puntos: 16
Ahora si me quedo mas claro gracias master Nivel7... pero ahora me surgio otro problema, la cosa es que tengo que trabajar con listas enlasadas y tengo 3 una auto, una usuario y una arriendo, lo que necesito es hacer solo una funcion que agregue cualqueir tipo de dato a cualquier estructura y si cambio las estructuras no tenga que modificar la funcion crear, trate de hacerle unas modificaciones a tu código y me quedo asi:

Código:
#define INT 1
#define STRING 2

//****************************  Declaración de las estructuras  ****************************

//Se define la estructura Auto
typedef struct Auto {
       int codigo;        //Código del auto
       char *marca;       //Marca del auto
       char *modelo;      //Modelo del auto
       int anho;          //Año del auto
       int n_ejemplares;  //Número de ejemplares del auto
       struct Auto *next;
}Auto;

//Se define la estructura Usuario
typedef struct Usuario {
       char rut[9];       //Rut del Usuario
       char *nombres;     //Nombres del Usiario
       char *apellidos;   //Apellidos del Usuario
       char *direccion;   //Dirección del Usuario
       char *ciudad;      //Ciudad del Usuario
       char *pais;        //País del Usuario
       char telefono[9];  //Teléfono del Usuario
       struct Usuario *next;
}Usuario;

//Se define la estructura Arriendo
typedef struct Arriendo {
       int codigo;         //Código del auto
       char *marca;        //Marca del auto
       char *modelo;       //Modelo del auto
       int anho;           //Año del auto
       char rut[9];        //Rut arrendatario
       char *nombres;      //Nombres arrendatario
       char *apellidos;    //Apellidos Arrendatario
       char fecha[9];      //Fecha en la que se arrendo
       char vence[9];      //Fecha en la que vence el arriendo
       struct Arriendo *next;
}Arriendo;

struct Auto *NuevoAuto;
struct Auto *PrimerAuto;
struct Auto *RecorreAuto;
struct Auto *AnteriorAuto;

struct Usuario *NuevoUsuario;
struct Usuario *PrimerUsuario;
struct Usuario *RecorreUsuario;
struct Usuario *AnteriorUsuario;

struct Arriendo *NuevoArriendo;
struct Arriendo *PrimerArriendo;
struct Arriendo *RecorreArriendo;
struct Arriendo *AnteriorArriendo;

void Crear(int tipo, char* estructura, char* dato, void* valor)
{
     char *nuest;
     char *prest;
     char *reest;
     
     nuest = strcat("Nuevo",estructura);
     prest = strcat("Primer",estructura);
     reest = strcat("Recorre",estructura);
     
     switch(tipo)
     {
         case INT:
             nuest->dato = ((int*)valor);
             break;
         case STRING:
             nuest->dato = (char *)malloc(sizeof(char)*strlen((char*)valor));
             strcpy(nuest->dato,(char*)valor);
             break;
     }
     
     nuest->next = NULL;
     
     if (prest == NULL)
     {
        prest = nuest;
        reest = nuest;
     }
     else
     {
        reest->next = nuest;
     }
     reest = nuest;
}
 


Mi problema es que me dice que dato no pertenece a ninguna estructura ni a ninguna union... te agradeceria si me pudieras dar una idea de como hacerlo.

Saludos y muchisimas gracias por tu valiosa ayuda.
__________________
Haz la guerra en la cama y el amor donde se te de la gana...
El tiempo es el mejor maestro, lo único malo es que te mata...¡¡Aprovecha tu tiempo!!
  #7 (permalink)  
Antiguo 10/09/2006, 19:18
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 21 años, 5 meses
Puntos: 52
Bueno, no se, pero en ese caso yo veria no como tipo de dato de la variable, sino como su capacidad.

Es decir, a cualquier varaible asignarle el valor que quieras.

char a=1;
int a=1;
long a=1;

Todo esto es posible.

Pero si lo que buscas es algo ams dinamico pues intenta recrear las plantillas en C.

#define nodo(tipo) \
typedef struct _nodo{
tipo dato;
struct _nodo *sig_nodo;
}NODO;

Masomenos es la idea de una lsita enlazada con plantillas traducido a C.

Tu le pones

nodo(int);

y te crea un nodo con tipo de datos int.

Es masomenos la idea, espero que te funcione.

Saludos
  #8 (permalink)  
Antiguo 10/09/2006, 20:26
 
Fecha de Ingreso: abril-2006
Ubicación: Acapulco Gro. México
Mensajes: 483
Antigüedad: 18 años
Puntos: 2
Bueno, en relidad esto podria ser mas complejo de lo que espere, no entiendo muy bien el proposito de tu progrmama:

que dato queieres que sea generico?

las estructuras, o los campos de tus estructuras??

si tansolo quieres que los campos de tus estructuras sean genericos, puedes usar lo que te hesugerido,

yq en lugar de usar
int, char*, etc.
para declara los campos de tu estructura usa la estructura Tipo, que te he mencionado en mensajes previos.

struct Auto
{
Tipo *codigo;
Tipo *marca;
//etc.
};

de esta forma solo los campos serian genericos.

si quieres que sean tus estructuras las que sean genericas, la opcion es que
la estructura Tipo, comtemple esto, es decir ademas de poder manipular datos primitivos de C, tambien manipule los tipos definidos por tus estructuras.

en C++ esto seria mas facil ya que hay sobrecarga de operadores, en C, no.


otra solucion es usar polimorfismo al estilo C, jeje.

las estructuras que as creados podrian estar contenidas en una sola, o podia haber una estructura base comun a todas, en su composicion.

esta estructura usara punteros a funciones, las cuales apuntaran a funciones en particular para cada tipo o dato manejado por tu estructura.

ejemplo: (muy basico).

union Variant {char* pcdat, int idat};

struct Base
{
Variant var;
void (*Crear)(Base*, Variant);
};


void CreaInt(Base* This, Variant value)
{
This->var.idat = value;
}

void CreaStr(Base* This, Variant value)
{
strcpy(This->var.pcdat, value);
}

Base VarInt;
Base VarStr;

VarInt.Crear = CreaInt;
VarStr.Crear = CreaStr;


VarInt->Crear(&VarInt, 1000);
VarStr->Crear(&VarStr, "Cadena");

este seria el funcionamiento y uso basico, pero realmente no se si pueda ayudarte este diseño.

Tal puedeas encontra solucion en el preprocesador, pero no soy bueno en eso. jaja

Saludos.
  #9 (permalink)  
Antiguo 10/09/2006, 21:09
Avatar de El_Metallick  
Fecha de Ingreso: noviembre-2002
Ubicación: Santiago, Chile
Mensajes: 1.718
Antigüedad: 21 años, 5 meses
Puntos: 16
Muchas gracias nuevamente Nivel7, la verdad de las cosas es que yo tampoco entiendo mucho el sentido de este programa (lo estoy haciendo para la universidad) y nos dijeron que las funciones agregar, modificar, eliminar y listar tenian que ser independientes de las estructuras, osea que si despues el profesor quiere cambiar las estructuras por las que el quiera las funciones puedan usarce sin ser modificadas... la verdad de las cosas es que el tema ya me tiene enfermo :P, por ahora simplemente voy a dejar el programa funcionando (un sistema para administrar una empresa de arriendo de autos con listas enlazadas y que la información se guarde en un archivo de texto al salir del programa y se carguen al abrirlo pero durante la ejecución que trabaje solo con las listas), y voy a preguntar como pretenden que logre esto... saludos master y muchisimas gracias por tu paciencia y ayuda, gracias a ti tambien Instru... saludos
__________________
Haz la guerra en la cama y el amor donde se te de la gana...
El tiempo es el mejor maestro, lo único malo es que te mata...¡¡Aprovecha tu tiempo!!
  #10 (permalink)  
Antiguo 11/09/2006, 02:06
 
Fecha de Ingreso: abril-2006
Ubicación: Acapulco Gro. México
Mensajes: 483
Antigüedad: 18 años
Puntos: 2
Ja ja, ok, de nada, en realidad el objetivo es algo raro, en fin.

Saludos.
  #11 (permalink)  
Antiguo 12/09/2006, 17:54
 
Fecha de Ingreso: abril-2005
Mensajes: 3.083
Antigüedad: 19 años
Puntos: 17
La verdad, no tiene sentido agregar datos a una variable de esa manera.

--
A la solución de Nivel7 con "union": Bien, pero no has contado con varias cosas:

1. Algunos datos son punteros. No estás asignándoles memoria.
2. Cada vez que Asignes, copies, o lo que sea, otra vez lo mismo: A liberar memoria, crear nueva...

--
A la solución con una super estructura, lo mismo, y además:

1. La estructura sería inmensa.
2. Para crear un dato, pasas un void*. Entonces, cuando llames a la función Crear, tendrías que diferenciar entre no punteros y punteros. Es decir, el ejemplo que has puesto, no vale:

int laEdad;
edad = Crear(INT, laEdad); // Adiós!

Si el compilador no te avisa... pum! Leerás 4 bytes de memoria cuyo offset sea "laEdad".

--
Y a ambas:

¿Qué pasa si es un float a un int? ¿O cadena a char? ... etc. Te toca, para cada operador, definir todas las combinaciones posibles. Además, muy lento.

--

La solución "a la C++" es mejor, sería lo mismo que haber usado funciones virtuales. Pero para eso solución se implementan macros que crean las estructuras, es decir:

#define newint(nombre) var nombre = { nullvar, crearint, sumarint, ... };

o mejor, creando un array de cada operador para cada tipo y luego asignando

#define newvar(tipo,nombre) var nombre = { nullvar, crear[tipo], sumar[tipo], ... };



Aunque eso de: "en C++ esto seria mas facil ya que hay sobrecarga de operadores, en C, no."

En C++ existen las clases, herencia, funciones virtuales y templates; que fundamentalmente manejan todo esto. ;)
  #12 (permalink)  
Antiguo 15/09/2006, 12:56
 
Fecha de Ingreso: abril-2006
Ubicación: Acapulco Gro. México
Mensajes: 483
Antigüedad: 18 años
Puntos: 2
buenas observaciones, MaxExtrme, pero creo que si he contemplado lo que mencionas, ademas, como podras ver es tan solo una sugerencia de lo que podria hacer, lo que he escrito lo he escrito directamente de mi cabeza a el foro. asi que ni siquiera se si funciona o no. te repito es tan solo una sugerencia, el tenia que ponerlo a prueba.

Acepto que tenga errores.

Saludos.
  #13 (permalink)  
Antiguo 15/09/2006, 18:10
 
Fecha de Ingreso: abril-2005
Mensajes: 3.083
Antigüedad: 19 años
Puntos: 17
Cita:
Iniciado por Nivel7 Ver Mensaje
buenas observaciones, MaxExtrme, pero creo que si he contemplado lo que mencionas, ademas, como podras ver es tan solo una sugerencia de lo que podria hacer, lo que he escrito lo he escrito directamente de mi cabeza a el foro. asi que ni siquiera se si funciona o no. te repito es tan solo una sugerencia, el tenia que ponerlo a prueba.

Acepto que tenga errores.

Saludos.
Claro evidentemente ;)

Sólo apuntaba (y me habré colado también) cosas que veía en esas soluciones.

En cualquier caso, sigo pensando que es una rotunda gilipollez, lo de la variable "Variant".
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 12:16.