¿Como filtrar todo tipo de datos de entrada en un programa?

Iniciado por aimnotabot, 24 Noviembre 2018, 03:41 AM

0 Miembros y 3 Visitantes están viendo este tema.

aimnotabot

Me gustaría saber como puedo filtrar distintos tipos de entrada en un programa...
Por ejemplo un programa en el que el usuario tenga que introducir uno o varios números y no se permitan caracteres alfabéticos, he pensado en hacerlo con un bucle que pregunte todo el rato la misma pregunta de ingreso de datos hasta que el usuario finalmente ingrese el tipo de caracter necesario, pero no se hacerlo...  :-\

Rave1996

Tu mejor opción sería emplear expresiones regulares (regex).

Puedes consultar la siguiente fuente donde viene bastante información...

AlbertoBSD

La forma correcta de realizar esto es procesar todo como texto o cadena de carectares al momento de la entrada y procesar los tipos de datos directamente con las funciones apropias como strtol o strtof

Codigo para C


int dato_entero;
float dato_flotante;
char temp[10];
//Capturamos variable_entera
do {
printf("Capture variable_entera: ");
fgets(temp,10,stdin);
dato_entero= strtol(temp,NULL,10); //Solo procesamos numeros BASE 10

/*En la funcion anterior se pude cambiar el NULL, por un apuntador y asi deteminar en que momento se para la funcion strtol, si el apuntador Apunta, a un '\n' significa que leyo hasta un Enter, si apunta a alguna letra o simbolo significa que trataron de ingresar caracteres distintos a los esperados*/

}while(dato_entero >= 0); // Salimos del DO solo si el valor leido es negativo


do {
printf("Capture variable_flotante: ");
fgets(temp,10,stdin);
dato_flotante= strtof(temp,NULL);

/*En la funcion anterior se pude cambiar el NULL, por un apuntador y asi deteminar en que momento se para la funcion strtol, si el apuntador Apunta, a un '\n' significa que leyo hasta un Enter, si apunta a alguna letra o simbolo significa que trataron de ingresar caracteres distintos a los esperados*/



}while(dato_flotante == 0.0); // Salimos del DO solo si el valor leido distinto de 0


Para C++ deben de existir formas diferentes de procesarlos datos
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW

K-YreX

Existe una librería que es <cctype> o <ctype.h> para C++ y C respectivamente que tienes algunas funciones como por ejemplo <isalnum> (comprueba si el caracter es alfanumérico), <isalpha> (comprueba si el caracter es alfabético) o <isdigit> (comprueba si el caracter es un digito decimal).
Esas son las que más te pueden interesar pero si le echas un vistazo a la librería entera tiene más funciones para hacer muchas más comprobaciones, como puede ser ver si hay espacios en blanco, ver si son mayúsculas o minúsculas o comprobar si el caracter es hexadecimal, entre otras más...

Espero que esto te sirva, suerte.
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

aimnotabot

Cita de: AlbertoBSD en 24 Noviembre 2018, 05:02 AM
La forma correcta de realizar esto es procesar todo como texto o cadena de carectares al momento de la entrada y procesar los tipos de datos directamente con las funciones apropias como strtol o strtof

Codigo para C


int dato_entero;
float dato_flotante;
char temp[10];
//Capturamos variable_entera
do {
printf("Capture variable_entera: ");
fgets(temp,10,stdin);
dato_entero= strtol(temp,NULL,10); //Solo procesamos numeros BASE 10

/*En la funcion anterior se pude cambiar el NULL, por un apuntador y asi deteminar en que momento se para la funcion strtol, si el apuntador Apunta, a un '\n' significa que leyo hasta un Enter, si apunta a alguna letra o simbolo significa que trataron de ingresar caracteres distintos a los esperados*/

}while(dato_entero >= 0); // Salimos del DO solo si el valor leido es negativo


do {
printf("Capture variable_flotante: ");
fgets(temp,10,stdin);
dato_flotante= strtof(temp,NULL);

/*En la funcion anterior se pude cambiar el NULL, por un apuntador y asi deteminar en que momento se para la funcion strtol, si el apuntador Apunta, a un '\n' significa que leyo hasta un Enter, si apunta a alguna letra o simbolo significa que trataron de ingresar caracteres distintos a los esperados*/



}while(dato_flotante == 0.0); // Salimos del DO solo si el valor leido distinto de 0


Para C++ deben de existir formas diferentes de procesarlos datos

¿No hay alguna forma de filtrar cualquier dato no deseado por teclado usando condicionales y bucles únicamente? Si se pudiese, ¿como lo haría?

K-YreX

Depende de lo que quieras filtrar.
Si quieres filtrar que cuando pides un número te introduzcan un número positivo claro que puedes con un filtro <do while> que es lo que se suele usar.
Sin embargo si quieres filtrar que una cadena de caracteres cumpla una condición o condiciones específicas pues tendrás que hacer más comprobaciones y lo mejor será crear una función que se encargue de eso ya que no existen funciones para todo lo que se puede hacer.

Lo que te ha mostrado AlbertoBSD sería una forma fácil de entender y segura de filtrar datos ya que usando <gets> te quitas de problemas con el buffer. Si lo quieres más simple todavía puedes hacer uso de <scanf> pero ten en cuenta que entonces puedes tener problemas de buffer.


int num;
do{
    printf("Introduce un numero positivo: ");
    scanf("%d", &num);
}   while(num < 0);


Ahí tienes un ejemplo de lo que sería un filtro para enteros positivos lo más simple que creo que puede hacerse.
Espero que te sirva de ayuda.
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

aimnotabot

Cita de: YreX-DwX en 24 Noviembre 2018, 12:46 PM
Depende de lo que quieras filtrar.
Si quieres filtrar que cuando pides un número te introduzcan un número positivo claro que puedes con un filtro <do while> que es lo que se suele usar.
Sin embargo si quieres filtrar que una cadena de caracteres cumpla una condición o condiciones específicas pues tendrás que hacer más comprobaciones y lo mejor será crear una función que se encargue de eso ya que no existen funciones para todo lo que se puede hacer.

Lo que te ha mostrado AlbertoBSD sería una forma fácil de entender y segura de filtrar datos ya que usando <gets> te quitas de problemas con el buffer. Si lo quieres más simple todavía puedes hacer uso de <scanf> pero ten en cuenta que entonces puedes tener problemas de buffer.


int num;
do{
    printf("Introduce un numero positivo: ");
    scanf("%d", &num);
}   while(num < 0);


Ahí tienes un ejemplo de lo que sería un filtro para enteros positivos lo más simple que creo que puede hacerse.
Espero que te sirva de ayuda.

Ese tipo de filtros si sabía hacerlos, pero me gustaria hacer uno sencillo para todo carácter que no sea un número positivo. Por ejemplo, imagina que el usuario introduce una arroba, un guión o un símbolo de dollar. ¿Si se pudiese hacer de manera sencilla como lo haria?

K-YreX

Cita de: YreX-DwX en 24 Noviembre 2018, 05:35 AM
Existe una librería que es <cctype> o <ctype.h> para C++ y C respectivamente que tienes algunas funciones como por ejemplo <isalnum> (comprueba si el caracter es alfanumérico), <isalpha> (comprueba si el caracter es alfabético) o <isdigit> (comprueba si el caracter es un digito decimal).
Esas son las que más te pueden interesar pero si le echas un vistazo a la librería entera tiene más funciones para hacer muchas más comprobaciones, como puede ser ver si hay espacios en blanco, ver si son mayúsculas o minúsculas o comprobar si el caracter es hexadecimal, entre otras más...

Espero que esto te sirva, suerte.

Como te comenté existen unas funciones en la librería <ctype.h>. Por ejemplo para ver si lo que ha introducido es un caracter podemos hacer lo siguiente:

char caracter;
do{
    printf("Introduce un caracter alfabetico: ");
    scanf("%c", &caracter);
}   while(!isalpha(caracter));


No he comprobado al tratarse de C si eso tendría el resultado esperado la verdad ya que aquí las variables se guardan usando el formato entonces por ejemplo si metes un número se convertirá en el caracter al que corresponde ese código ASCII. Entonces para evitar dudas la forma segura sería hacerlo como te han comentado, guardas la entrada en una cadena C y luego haces las comprobaciones. Por ejemplo para ver que no hay ningún signo como un guión o una exclamación sería recorrer la cadena y comprobar cada caracter.
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

AlbertoBSD

#8
Cita de: aimnotabot en 24 Noviembre 2018, 13:10 PM
Ese tipo de filtros si sabía hacerlos, pero me gustaria hacer uno sencillo para todo carácter que no sea un número positivo. Por ejemplo, imagina que el usuario introduce una arroba, un guión o un símbolo de dollar. ¿Si se pudiese hacer de manera sencilla como lo haria?

Lo que aimnotabot necesita es otro lenguaje de programación. Que tenga una funcion magica que sea inteligente y pasa de precedir cualquier input......, O espera esto es C y C++ puedes programar una funcion que haga cualquier cosa!!!!

Puedes usar todas las respuestas que ya te dieron y meterlas en una funcion creada por ti que se adapte a tus necesidades.

Realmente el C basico no hay manera facil de hacerlo, tal vez con C++ y varias de sus funciones como las que te mencionan de regex en el primero reply, podrías lograr algo mas sencillo, pero si seria de investigar un poco mas ya que hay muchas funciones "nuevas" que no conozco de C++.

Cita de: Rave1996 en 24 Noviembre 2018, 04:38 AM
Tu mejor opción sería emplear expresiones regulares (regex).

Puedes consultar la siguiente fuente donde viene bastante información...


El mejor de los casos que seria programar una función que haga lo que quieres de una forma que tu comprendas.


int i;
i = funcion_leer("Ingrese un numero positivo\n",CONSTANTE_PARA_POSITIVOS);


Y por otro lado tendrias.


int funcion_leer(char *s,int tipo) {
int valor;
int entrar_1 = 1;
int entrar_2 = 1;
char temporal[50];
char *ptr;
do {
entrar_2 = 1;
do{
printf(s);
fgets(temporal,50,stdin);
fflush(stdin);
valor = strtol(temporal,&ptr,10);
switch(ptr[0]) {
case '\n':
case '\r': //No recuardo cual de los 2 es el bueno, esto depende del sistema operativo segun recuerdo, favor de corregirme si estoy en un error
case '\0':
entrar_2 = 0; //Salimos por que la cadena no tiene caracteres extraños
break;
default:
break;
}
}while(entrar_2);//De aqui no salimos hasta que strtol confirme que no tenemos ningun caracter raro, esto es cuando ptr apunte solo a '\r' o '\n' o '\0';
switch(tipo){ //Ahora evaluamos que el dato sea lo que buscamos
case NUMERO_ENTERO: //Cualquier Numero
entrar_1 = 0;
break;
case NUMERO_NATURAL: // > 0
if(valor > 0) {
entrar_1 = 0;
}
break;
case NUMERO_NEGATIVO:
if(valor < 0) {
entrar_1 = 0;
}
break;
case NUMERO_PAR:
if(valor %2 == 0) {
entrar_1 = 0;
}

break;
case NUMERO_IMPAR:
if(valor % 2 == 1) {
entrar_1 = 0;
}
break;
//etc...
}
}while(entrar_1);
return valor;
}


Obviamente tienes que tener declaradas X cantidad de constantes, no es algo tan sencilla la funcion completa, pero es lo mejor validado que podrás encontrar.

Aqui esta el ejemplo de salida.




Saludos
Donaciones
1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW