Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: minari02 en 7 Febrero 2014, 20:59 pm



Título: Programa que identifique que tipo de dato se introduce C++
Publicado por: minari02 en 7 Febrero 2014, 20:59 pm
Hola que tal? desde hace rato me vengo preguntando como hacer un programa que, al introducir un dato, identifique que tipo de dato se ha introducido, alguien sabe como?? no tengo idea de como hacer eso... alguien puede?? pueden ir postenado sus ideas, por cierto, es solo una duda, que otros tambien tendran.


Título: Re: Programa que identifique que tipo de dato se introduce C++
Publicado por: leosansan en 7 Febrero 2014, 21:17 pm
Hola que tal? desde hace rato me vengo preguntando como hacer un programa que, al introducir un dato, identifique que tipo de dato se ha introducido, alguien sabe como?? no tengo idea de como hacer eso... alguien puede?? pueden ir postenado sus ideas, por cierto, es solo una duda, que otros tambien tendran.

Antes de introducir cualquier dato habrás tenido que declararlo previamente como int, char o lo que sea. Ahí está la respuesta. :rolleyes:

¡¡¡¡ Saluditos! ..... !!!!


(http://st.forocoches.com/foro/images/smilies/aaaaa.gif)


Título: Re: Programa que identifique que tipo de dato se introduce C++
Publicado por: vangodp en 8 Febrero 2014, 01:05 am
Eso es lo que comenta leo.
El problema es que todo lo que vas usar tienes que declararlo antes.
Una cosa que puedes hacer es entrar los datos como string y después hacerles un cast a int o float por ejemplo, a la hora de hacer un calculo.
Pero no le veo la necesidad a eso.
Tu lo dirás para que lo quieras.
tal vez estés formulando mal la pregunta.   ;)


Título: Re: Programa que identifique que tipo de dato se introduce C++
Publicado por: Yoel Alejandro en 8 Febrero 2014, 03:48 am
No se puede!!. C es un lenguaje "tipado", al contrario de otros lenguajes donde una variable puede alegremente cambiar de un tipo a otro.

Como te contestó otro usuario, esto significa que a cada variable que uses en C debes haberle definido previamente un tipo, de lo contrario el compilador te informará un error. Recuerda que distintos tipos ocupan distinto espacio en memoria, así que el compilador debe saber previamente el tipo de cada variable para calcular correctamente cuántos bytes asignarle dentro de la memoria de datos del programa.

Si un usuario mete un valor por la consola (teclado), aún así debes declarar un tipo esperado en la cadena de control de formato de scanf (posiblemente distinto al que el usuario esperaba, pero aún así es un tipo fijo declarado previamente en el programa). Por otra parte, la variable a la que será asignado este valor tiene un tipo previamente declarado, por tanto será ese tipo y no otro.

Ten en cuenta algo muy importante. Si por ejemplo declaras:

Código
  1. int x;

y luego haces algo como

Código
  1. scanf( "%d", &x);

pues ya dijiste que se esperaba un tipo entero. No importa que el usuario meta un valor decimal a través del teclado, el valor será convertido forzosamente a un entero (según las reglas implícitas de conversión de C).


Título: Re: Programa que identifique que tipo de dato se introduce C++
Publicado por: Gh057 en 8 Febrero 2014, 04:46 am
Hola minari02, como muy bien te han contestado el control que tiene el C sobre las variables exige la declaración antes de utilizarlas, aunque  bien pudiera ser que lo que intentas preguntar es como "validar" un dato ingresado, que es otra cosa... lo más usual es encapsular la entrada en un "do-while...", ya que permite correr la sentencia al menos una vez (el cual usamos para el ingreso del dato) y lo aceptamos o rechazamos mediante la condiciones definidas al caso. Saludos.


Título: Re: Programa que identifique que tipo de dato se introduce C++
Publicado por: leosansan en 8 Febrero 2014, 08:23 am
No se puede!!. C es un lenguaje "tipado", al contrario de otros lenguajes donde una variable puede alegremente cambiar de un tipo a otro.

Como te contestó otro usuario, esto significa que a cada variable que uses en C debes haberle definido previamente un tipo, de lo contrario el compilador te informará un error.
.............................................

* Eso de que informa del error suena a broma. ¡Ojalá fuese siempre así!.

* Aunque previamente se haya definido un tipo para una variable siempre existe la posibilidad de cambiar el tipo mediante el correspondiente casting o mediante el uso de funciones tipo atoi, itoa,atof, etc.


..................................
.Por otra parte, la variable a la que será asignado este valor tiene un tipo previamente declarado, por tanto será ese tipo y no otro.

Ten en cuenta algo muy importante. Si por ejemplo declaras:

Código
  1. int x;

y luego haces algo como

Código
  1. scanf( "%d", &x);

pues ya dijiste que se esperaba un tipo entero. No importa que el usuario meta un valor decimal a través del teclado, el valor será convertido forzosamente a un entero (según las reglas implícitas de conversión de C).

 Según como lo interpretes. Si has declarado una variable como int e introduces 1.23 tomará como int el 1. Y si introduces 12as como dato toma el 12 como int. Y si introduces un caracter o una cadena, tipo a o asdf, en el mejor de los casos el int toma un valor "extraño" que afectará al resto de código por quedarse en el buffer. Y en el peor se produce un bucle infinito si estas en un for,while o do-while.

Hola minari02, como muy bien te han contestado el control que tiene el C sobre las variables exige la declaración antes de utilizarlas, aunque bien pudiera ser que lo que intentas preguntar es como "validar" un dato ingresado, que es otra cosa... lo más usual es encapsular la entrada en un "do-while...", ya que permite correr la sentencia al menos una vez (el cual usamos para el ingreso del dato) y lo aceptamos o rechazamos mediante la condiciones definidas al caso. Saludos.


Ahí estamos más de acuerdo , amigo Gh057. Se trata en realidad de validar el valor introducido, cosa que por comodidad no suele hacerse pero que en un programa serio es indispensable.

Por ejemplo si estamos tratando de introducir un int y no queremos disgustos en el resto del código hay que asegurarse que el valor introducido sea efectivamente un int. Y esto se puede realizar de varias maneras.

Para que veas minari02 como funciona, observa la salida del código que te propongo como validación de un int en el que no admite cosas como 1.23, 12as, asd12, o un simple caracter. Ante tales situaciones te vuelve a pedir que introduzcas un int:


Citar

Introduzca un numero entero:123.356

Introduzca un numero entero:12asd

Introduzca un numero entero:asd123

Introduzca un numero entero:a

Introduzca un numero entero:123456

numero= 123456


Código
  1. #include <stdio.h>
  2.  
  3. int main(){
  4.  int i,numero,flag=0;
  5.  char num [20];
  6.  do{
  7.    flag=0;
  8.    printf ("\nIntroduzca un numero entero:");
  9.    fflush(stdout);
  10.    scanf ("%s",num);
  11.    for (i=0;num[i];i++){
  12.      if (num[i]<'0' || num[i]>'9'){
  13.        flag=1;
  14.      }
  15.    }
  16.  
  17.  }while (flag!=0);
  18.  numero=atoi(num);
  19.  printf("\nnumero= %d\n",numero);
  20.  return 0;
  21. }
  22.  

Como ves algo más complejo que un simple:

Código
  1. #include <stdio.h>
  2.  
  3. int main(){
  4.  int numero;
  5.  printf ("\nIntroduzca un numero entero:");
  6.  fflush(stdout);
  7.  scanf ("%s",numero);
  8.  printf("\nnumero= %d\n",numero);
  9.  return 0;
  10. }
  11.  

Pero como te comenté, este último se revienta introduciendo un simple caracter,12.36,etc.

¡¡¡¡ Saluditos! ..... !!!!


(http://st.forocoches.com/foro/images/smilies/aaaaa.gif)


Título: Re: Programa que identifique que tipo de dato se introduce C++
Publicado por: Yoel Alejandro en 8 Febrero 2014, 15:30 pm
Leosasan, estas discusiones sobre el comportamiento del compilador ante ciertas situaciones irregulares en los programas son sumamente enriquecedoras tanto para nosotros como para los usuarios menos experimentados de la comunidad  :)

Respecto a que no crees que el compilador informe un error siempre que encuentre una referencia a una variable que no se ha definido con anterioridad, ..... bueno dependerá del tipo de compilador, y lo estricto que éste sea.

Yo uso gcc de GNU para Linux y siempre me informa esta situación y lo cataloga como error (no Warning). Ello significa que el proceso de compilación se detiene y no genera un ejecutable. Por ejemplo, quise poner la sentencia de asignación x = 1 sin antes haber declarado la x y aquí el mensaje obtenido:

Código:
test1.c: In function ‘main’:
test1.c:18: error: ‘x’ undeclared (first use in this function)
test1.c:18: error: (Each undeclared identifier is reported only once
test1.c:18: error: for each function it appears in.)

Ni siquiera (considerando que C99 define "int por defecto") se le ocurrió tomar la variable x como int y seguir con la compilación. Claro, esto quizá dependerá del tipo de compilador, a lo mejor algunos son más flexibles, o pueden ser configurados sobre cómo responder en situaciones como ésta.

En todo caso, creo que un compilador estricto es mejor (el de GNU lo es), porque te enseña desde el principio a programar como es debido, y ceñirte mejor a la norma ISO/IEC 9899:1999, mejor llamada ANSI C99 !!!

============================
Por otra parte, respecto a lo de convertir "1.23" en 1, y "12as" como 12, a eso precisamente me refiero con "las reglas de conversión implícita de tipo de C". Ya que es un lenguaje tipado, él posee protolocos internos que le dicen cómo convertir un valor dado a otro tipo esperado.

Ahora, SUPONEMOS que cadenas como "12as" se convertirán a 12, pero en general de la forma exacta de conversión yo no estoy seguro, pero eso debe estar claramente definido en la norma ANSI C99. Por algo C es un lenguaje que ha sido absolutamente normado, y al tener una duda sólo hay que consultar lo que dice la norma al respecto.

Yo no he investigado profundamente la conversión a entero de cadenas que incluyen caracteres no numéricos, preferiría validar el dato por mí mismo, tal como lo propone leosasan en su código.

Al usuario que inició este post le recuerdo que C tiene normas internas de conversión de tipo, y serán SÓLO esas, las que especifica el estándar oficial, y no las que tú creas, o las que crea el usuario. En tales situaciones "anómalas", nada te garantiza que el comportamiento de la función scanf será como tú supones que será. Pero como programador debes mantener tu programa siempre "bajo control", por eso debes confeccionar una rutina de validación de los datos que introduce el usuario según tus propias normas y preferencias. Eso te recomiendo  :) :)

======================
Continuando el tema, y para que minari02 te acostumbres a la buen práctica de validar los datos de entrada (nunca confíes en el buen juicio del usuario de tu programa) he aquí una humilde contribución que preparé hace tiempo. Esta función isnumeric recibe una cadena y devuelve True si corresponde a un número válido, y False si no. Admite los caracteres 0-9, además de +-., y el espacio. Los espacios al inicio y al final de la cadena serán despreciados, y además filtra la cadena de una forma más sofisticada que sólo ver si está compuesta de caracteres permitidos. Por ejemplo, permite el '+' o el '-', pero sólo uno de ellos, y antecediendo a cualquier carácter numérico. O sea, que por ejemplo rechazará expresiones como "++354", ó "3-456". El signo decimal '.' sólo podrá aparecer una vez.

Aquí el código, para que lo incluyas en tu programa. Se aceptan con agrado sugerencias y mejoras  ;-)

Código
  1. /* No cero si la cadena apuntada por s representa un número real decimal.
  2. La cadena deberá contener sólo los caracteres "+-0123456789. ".
  3.  
  4. - El carácter de punto decimal es el punto '.', es opcional y sólo puede aparecer
  5.  una vez en la cadena.
  6. - El carácter de signo '+' o '-' es opcional, sólo puede aparecer una vez y como
  7.  primer carácter no blanco de la cadena.
  8. - Se admiten secuencias de espacios ' ' al principio o al final de la cadena, pero
  9.  son ignoradas. No se admiten espacios en el medio de la cadena.
  10.  
  11. Esta definición es acorde con la configuración regional estándar en Español, pero
  12. pudiera adaptarse para la configuración en Inglés (la coma ',' antes que el punto '.').
  13.  
  14. No admitimos en esta implementación representaciones en punto flotante con mantisa y
  15. exponente, sólo mantisa.
  16. */
  17. int isnumeric(const char *s) {
  18.  
  19. const char *allowed_chars = "0123456789."; /* caracteres permitidos */
  20. char c;
  21. int i, j, N;
  22. bool exists_point = false, exists_sign = false;
  23. bool pre_space = false, post_space = false;
  24.  
  25. N = strlen(allow_chars);
  26. for (i = 0; i < INT_MAX && s[i]!='\0'; i++) {
  27. c = s[i];
  28.  
  29. // sólo se admite un carácter opcional '+' ó '-' y como primer
  30. // no blanco de la cadena
  31. if (c == '+' || c == '-') {
  32. if (exists_sign == true)
  33. return 0;
  34. else {
  35. exists_sign = 1;
  36. if (i>0)
  37. if (s[i-1] != ' ') return 0;
  38. }
  39. continue;
  40. }
  41.  
  42. if (c == ' ') {
  43. if (pre_space == false) pre_space = 1;
  44. if (i > 0 && s[i-1] != ' ') post_space = 1;
  45. continue;
  46. }
  47. if (post_space == true && c != ' ') return 0;
  48.  
  49. // buscando caracteres permitidos
  50. for (j=0; j<N; j++)
  51. if (c == allowed_chars[j]) break;
  52. if (j == N) return 0;
  53.  
  54. // no puede haber más de un carácter '.'
  55. if (c == '.') {
  56. if (exists_point == 1)
  57. return 0;
  58. else
  59. exists_point = 1;
  60. }
  61. }
  62.  
  63. // si no detecta error, sale con valor 1
  64. return 1;
  65. }


Título: Re: Programa que identifique que tipo de dato se introduce C++
Publicado por: ivancea96 en 8 Febrero 2014, 15:58 pm
Me gusta la idea de yoel_alejandro.
Pero, aprobechendo que el tipo de retorno de "isNumeric" es int, podría retornarse un número según el tipo de dato. (float, double, int, long long int, etc)

Sería una función muy útil.


Título: Re: Programa que identifique que tipo de dato se introduce C++
Publicado por: ivancea96 en 8 Febrero 2014, 16:08 pm
Me pongo a esto:

Código
  1. enum type{
  2.    type_signed = 1,
  3.    type_bool = 2,
  4.    type_int = 4,
  5.    type_short = 8,
  6.    type_float = 16,
  7.    type_double = 32,
  8.    type_char = 64
  9.    /* ... */
  10. }
  11.  
  12. int typeOf(string s){
  13.    /** Esto retornará un entero compuesto de los números que pueda ser.
  14.           Si es "12", por ejemplo, puede ser short, int, float, double y char. Entonces, retornaría: 4+8+16+32+64. (Puede ser más tipos, pero aun estoy empezando el enum jaja **/
  15. }
Luego, la salida de typeOf se parsearía así:
Código
  1. if(typeOf(str)&type_double) double d = parse<double>(str);
la función parse podría tener un template para retornar el tipo indicado xD


EDITO: Como es diferente el tamaño de un signed al de un unsigned (el tamaño máximo), quitaré el type_signed, y pondré type_uchar, type_uint etc etc

EDITO 2: Finalmente:
Código
  1. enum type{
  2.    /**    SIGNED TYPES    **/
  3.    type_bool     = 0b0000000000000001,
  4.    type_char     = 0b0000000000000010,
  5.    type_short    = 0b0000000000000100,
  6.    type_int      = 0b0000000000001000,
  7.    type_llong    = 0b0000000000010000,
  8.    type_float    = 0b0000000000100000,
  9.    type_double   = 0b0000000001000000,
  10.    type_ldouble  = 0b0000000010000000,
  11.  
  12.    /**    UNSIGNED TYPES    **/
  13.    type_ubool    = 0b0000000100000000,
  14.    type_uchar    = 0b0000001000000000,
  15.    type_ushort   = 0b0000010000000000,
  16.    type_uint     = 0b0000100000000000,
  17.    type_ullong   = 0b0001000000000000,
  18.    type_ufloat   = 0b0010000000000000,
  19.    type_udouble  = 0b0100000000000000,
  20.    type_uldouble = 0b1000000000000000,
  21.  
  22.    /**    OTHER    **/
  23.    type_signed   = 0b0000000011111111,
  24.    type_unsigned = 0b1111111100000000,
  25.    type_all      = 0b1111111111111111
  26. };


RE-EDITO: Ahora me dió pereza poner toodos los "if" para comprobar cada tipo jaja. Si alguien se anima, aunque sea para 1 tipo solo, que postée :3


Título: Re: Programa que identifique que tipo de dato se introduce C++
Publicado por: minari02 en 8 Febrero 2014, 20:36 pm
bueno.... claro que ya habia pensado lo de que hay que iniciar la variables... pero... me he perdido... se puede hacer lo que le he preguntado??? lamento no comprender todo lo que han puesto!  :-(

Gracias!


Título: Re: Programa que identifique que tipo de dato se introduce C++
Publicado por: ivancea96 en 8 Febrero 2014, 21:49 pm
Se puede hacer, pero tendrías que comprobar la cadena a ver si se puede convertir. Despues de saber si se puede convertir, tendrías que convertirla.

Aquí te pongo un par de códigos:

Saber a que tipos de dato se puede transformar:
Código
  1. #include <iostream>
  2.  
  3. using namespace std;
  4.  
  5. enum type{
  6.    /**    TYPES    **/
  7.    type_bool     = 0b000000000001,
  8.    type_char     = 0b000000000010,
  9.    type_uchar    = 0b000000000100,
  10.    type_short    = 0b000000001000,
  11.    type_ushort   = 0b000000010000,
  12.    type_int      = 0b000000100000,
  13.    type_uint     = 0b000001000000,
  14.    type_llong    = 0b000010000000,
  15.    type_ullong   = 0b000100000000,
  16.    type_float    = 0b001000000000,
  17.    type_double   = 0b010000000000,
  18.    type_ldouble  = 0b100000000000,
  19.  
  20.    /**    OTHER    **/
  21.    type_signed   = 0b111010101011,
  22.    type_unsigned = 0b000101010100,
  23.    type_all      = 0b111111111111
  24. };
  25.  
  26. bool allNumeric(string s){
  27.    for(int i=0; i<s.size(); i++)
  28.        if(s[i]<48 || s[i]>57)
  29.        return false;
  30.    return true;
  31. }
  32.  
  33. bool minorEqual(string a, string b){
  34.    if(a.size()<b.size()) return true;
  35.    if(a.size()>b.size()) return false;
  36.    if(a==b) return true;
  37.    for(int i=0; i<a.size(); i++)
  38.        if(a[i]<b[i]) return true;
  39.        else if(a[i]>b[i]) return false;
  40.    return true;
  41. }
  42.  
  43. int typeOf(string s){
  44.    if(s=="") return 0;
  45.    int type = 0;
  46.    bool sign = false;
  47.    /** BOOL **/
  48.    if((s.size()==1 && (s[0]=='0'||s[0]=='1'))||(s.size()==4 &&s.substr(0, 4)=="true")||(s.size()==5 &&s.substr(0, 5)=="false"))
  49.        type+=type_bool;
  50.  
  51.    /** CHAR && UCHAR **/
  52.    if(s.size()==1)
  53.        type+=type_char+type_uchar;
  54.    else{
  55.        if(s[0]=='-')
  56.            sign=true;
  57.        if(s.size()<4+sign && allNumeric(s.substr(sign, s.size()))){
  58.            if(sign){
  59.                if(minorEqual(s.substr(1, s.size()), "128"))
  60.                    type+=type_char;
  61.            }else{
  62.                if(minorEqual(s.substr(0, s.size()), "127"))
  63.                    type+=type_char;
  64.                if(minorEqual(s.substr(0, s.size()), "255"))
  65.                    type+=type_uchar;
  66.            }
  67.        }
  68.    }
  69.  
  70.    /** SHORT && USHORT **/
  71.    if(s[0]=='-')
  72.        sign=true;
  73.    if(allNumeric(s.substr(sign, s.size()))){
  74.        if(sign){
  75.            if(minorEqual(s.substr(1, s.size()), "32768"))
  76.                type+=type_short;
  77.        }else{
  78.            if(minorEqual(s.substr(0, s.size()), "32767"))
  79.                type+=type_short;
  80.            if(minorEqual(s.substr(0, s.size()), "65535"))
  81.                type+=type_ushort;
  82.        }
  83.    }
  84.  
  85.    /** INT && UINT **/
  86.    if(s[0]=='-')
  87.        sign=true;
  88.    if(allNumeric(s.substr(sign, s.size()))){
  89.        if(sign){
  90.            if(minorEqual(s.substr(1, s.size()), "2147483648"))
  91.                type+=type_int;
  92.        }else{
  93.            if(minorEqual(s.substr(0, s.size()), "2147483647"))
  94.                type+=type_int;
  95.            if(minorEqual(s.substr(0, s.size()), "4294967295"))
  96.                type+=type_uint;
  97.        }
  98.    }
  99.  
  100.    /** LONG && ULONG **/
  101.    if(s[0]=='-')
  102.        sign=true;
  103.    if(allNumeric(s.substr(sign, s.size()))){
  104.        if(sign){
  105.            if(minorEqual(s.substr(1, s.size()), "9223372036854775808"))
  106.                type+=type_llong;
  107.        }else{
  108.            if(minorEqual(s.substr(0, s.size()), "9223372036854775807"))
  109.                type+=type_llong;
  110.            if(minorEqual(s.substr(0, s.size()), "18446744073709551615"))
  111.                type+=type_ullong;
  112.        }
  113.    }
  114.    double b=atof(s.c_str());
  115.    float a=(float)b;
  116.    bool is=false;
  117.    if(b==0.0 && (s=="0"||s=="0.0")){
  118.        type+=type_float+type_double;
  119.    }else if(b!=0.0){
  120.        type+=type_double;
  121.        if(a==b)
  122.            type+=type_float;
  123.    }
  124.    return type;
  125. }
  126.  
  127. int main(){
  128.    string s;
  129.    getline(cin, s);
  130.    if(typeOf(s)&type_int)
  131.        cout << "Se puede transformar en un entero (signed)." << endl;
  132.    cin.get();
  133.    return 0;
  134. }


Ejemplo de como transformar string a int:
Código
  1. int potencia(int n, int b){
  2.   int temp=1;
  3.   for(int i=0;i<b;i++) temp=temp*n;
  4.   return temp;
  5. }
  6.  
  7. int parseString(string s){
  8. string a;
  9. int num = 0;
  10. for(int i=s.length()-1;i>=0;i--){
  11.  if(!((int)s[i]>=48 && (int)s[i]<=57)) return 0;
  12.  num+=((int)s[i]-48)*(potencia(10, s.length()-i-1));
  13. }
  14. return num;
  15. }

Bueno, aún no acabé con las funciones para transformar de string a numérico.
Igualmente, puedes usar las funciones atol(string) Retorna un LONG, atof() Retorna un DOUBLE, atoi() Retorna un INT


EDITO: Me olvidé decir, que el FLOAT, de la función typeOf(string), no funciona. Pero funciona para double.


Título: Re: Programa que identifique que tipo de dato se introduce C++
Publicado por: minari02 en 9 Febrero 2014, 15:04 pm
mmm... ahora entiendo... Muchas gracias a todos  ;D


Título: Re: Programa que identifique que tipo de dato se introduce C++
Publicado por: Yoel Alejandro en 9 Febrero 2014, 18:22 pm
Interesante la solución de minari!!!

Como lo que se introduce es una cadena, un programa personalizado podría decidir si se intentó introducir un short, int, long, float, etc. Al estilo quizá de VisualBasic.

Aunque yo sólo añadiría que en el código se usan algunas características C++ no indispensables, uno podría intentar ---como ejercicio---, traducir todo a C puro. Porque si no es esencial usar clases, ¿por qué C++ u no C?

De hecho, leí una vez que supuestamente el código compilado "tipo C" se ejecuta más rápida y eficientemente que el código compilado como "tipo C++". ¿Qué saben de esto?


Título: Re: Programa que identifique que tipo de dato se introduce C++
Publicado por: minari02 en 9 Febrero 2014, 20:21 pm
me parece muy interesante... aunque, complicado! yoel_alejandro en el titulo he especificado C++ porque es el que estoy aprendiendo pero teniendo lo que  ivancea96 si sabes C puedes pasarlo de C++ a C supongo yo...


Título: Re: Programa que identifique que tipo de dato se introduce C++
Publicado por: vangodp en 9 Febrero 2014, 20:30 pm
C es lineal, c++ pega muchos mas saltos.
C también se desvía cuando creas funciones no inline, pero a cambio un programa en c++ puede ser un plato de macarrón. XD
La programación orientada a objetos pasa mayor factura.
Pero siempre puedes optimizar lo máximo :D
Si haces un programa que no salte de una función a otra esta claro que va ser mas eficiente.




Título: Re: Programa que identifique que tipo de dato se introduce C++
Publicado por: rir3760 en 10 Febrero 2014, 18:41 pm
Si por ejemplo declaras:
Código
  1. int x;

y luego haces algo como
Código
  1. scanf( "%d", &x);

pues ya dijiste que se esperaba un tipo entero. No importa que el usuario meta un valor decimal a través del teclado, el valor será convertido forzosamente a un entero (según las reglas implícitas de conversión de C).
No hay que confundir los temas porque se corre el riesgo de terminar con una confusión espantosa.

Las conversiones (promoción de enteros y conversiones aritméticas usuales) se realizan tomando un tipo compatible y pasando este a otro. Por ejemplo "(unsigned int) - 1" resulta en el valor máximo que puede almacenarse en una variable de tipo unsigned int.

En el caso que nos ocupa (obtener un valor en base a una cadena de caracteres) lo único que aplica es la definición de la función utilizada ya sea atoi, strtol, scanf, etc..

----

No se puede!!. C es un lenguaje "tipado", al contrario de otros lenguajes donde una variable puede alegremente cambiar de un tipo a otro.

Como te contestó otro usuario, esto significa que a cada variable que uses en C debes haberle definido previamente un tipo, de lo contrario el compilador te informará un error.

+

* Eso de que informa del error suena a broma. ¡Ojalá fuese siempre así!.

* Aunque previamente se haya definido un tipo para una variable siempre existe la posibilidad de cambiar el tipo mediante el correspondiente casting o mediante el uso de funciones tipo atoi, itoa,atof, etc.
Aqui se están mezclando dos temas:

A) Obtener el valor de una variable de tipo T y convertir ese valor a otro tipo U mediante una conversión explicita o implícita. Esto aplica a C.

B) Lenguajes sin tipos donde las operaciones dependen del contexto, esto usualmente aplica con lenguajes de scripts, mas o menos así:
Código:
a = 111         // Valor numerico 111
b = 222         // Valor numerico 222
Imprimir a + b  // Imprime 333

// ...

a = "111"       // La cadena 111
b = "222"       // La cadena 222
Imprimir a + b  // Imprime 111222

Para que veas minari02 como funciona, observa la salida del código que te propongo como validación de un int en el que no admite cosas como 1.23, 12as, asd12, o un simple caracter. Ante tales situaciones te vuelve a pedir que introduzcas un int:
Ya que la validación consiste en verificar que los caracteres sean solo dígitos el bucle lo puedes acortar a:
Código
  1. do {
  2.   puts("Introduzca un numero entero:");
  3.   scanf("%s", num);
  4.  
  5.   for (i = 0; isdigit(num[i]); i++)
  6.      ;
  7. }while (num[i] != '\0');
Y falta incluir el encabezado <stdlib.h> antes de utilizar atoi. Por ultimo como validación ambos programas (el tuyo y el mio) solo sirven para practicar ya que tienen agujeros (por ejemplo no se verifica el valor de retorno de la función scanf).

----

Yo uso gcc de GNU para Linux y siempre me informa esta situación y lo cataloga como error (no Warning). Ello significa que el proceso de compilación se detiene y no genera un ejecutable. Por ejemplo, quise poner la sentencia de asignación x = 1 sin antes haber declarado la x y aquí el mensaje obtenido:
Código:
test1.c: In function ‘main’:
test1.c:18: error: ‘x’ undeclared (first use in this function)
test1.c:18: error: (Each undeclared identifier is reported only once
test1.c:18: error: for each function it appears in.)

Ni siquiera (considerando que C99 define "int por defecto") se le ocurrió tomar la variable x como int y seguir con la compilación.
Es al revés. En el estándar C90 si se declara una variable y se omite el tipo este es, de forma predeterminada, int. A partir de C99 no indicar el tipo en una declaración es un error.

Por otra parte, respecto a lo de convertir "1.23" en 1, y "12as" como 12, a eso precisamente me refiero con "las reglas de conversión implícita de tipo de C". Ya que es un lenguaje tipado, él posee protolocos internos que le dicen cómo convertir un valor dado a otro tipo esperado.
Sin ofender y sin temor a repetir: las conversiones de tipos compatibles no aplican en este caso, lo único que aplica es la especificación de la función utilizada.

Un saludo


Título: Re: Programa que identifique que tipo de dato se introduce C++
Publicado por: Yoel Alejandro en 10 Febrero 2014, 20:55 pm
Sólo para comentar, considérese que la propuesta:

Código
  1.    do {
  2.      puts("Introduzca un numero entero:");
  3.      scanf("%s", num);
  4.  
  5.      for (i = 0; isdigit(num[i]); i++)
  6.         ;
  7.    }while (num[i] != '\0');
  8.  
no admite números negativos. Los números "negativos" también son enteros. Y por cierto que isdigit requiere <ctype.h> !!!

Y un poco aparte del tema, moderador una pregunta, ¿Hay alguna manera que solicitar que mis mensajes no sea citados o mencionados por cierto usuario en particular? Porque en este foro hay gente que en vez de venir a aportar soluciones propias, se dedica a examinar y poner epítetos a los aportes de los demás.


Título: Re: Programa que identifique que tipo de dato se introduce C++
Publicado por: rir3760 en 11 Febrero 2014, 02:48 am
Sólo para comentar, considérese que la propuesta:
Código
  1.    do {
  2.      puts("Introduzca un numero entero:");
  3.      scanf("%s", num);
  4.  
  5.      for (i = 0; isdigit(num[i]); i++)
  6.         ;
  7.    }while (num[i] != '\0');
no admite números negativos. Los números "negativos" también son enteros.
Por supuesto que no los procesa ya que como comente el programa de leosansan solo intenta validar verificando que todos los caracteres sean dígitos.

Y por cierto que isdigit requiere <ctype.h>!
Ouch! Gracias por la corrección.

Un saludo