En este post sobre programación en C te mostraré cómo saber si un número ingresado por el usuario es un número válido, es decir, validar un número en C.
Lo que haremos será un poco complejo, pues la validación de números en C no es una tarea sencilla, pero lo vamos a lograr.
Vamos a hacer una función que comprueba números enteros o int, y otra función que se encarga de la validación números flotantes (con punto decimal y signo de negativo).
El lenguaje ya provee maneras de convertir números o de saber si un número es válido, pero tiene algunas deficiencias.
Por ejemplo, algunas funciones dejan de leer cuando encuentran una letra e indican que el número es válido.
Así que lo que haremos será leer el número como cadena, y luego recorrerlo. Por cada letra de la cadena vamos a comprobar si es un dígito, y en caso de que no lo sea, comprobamos si es el punto decimal o el signo de negativo.
Finalmente invocamos a la función que convierte una cadena a un número, sin temer a que haya errores de conversión, pues antes ya lo hemos validado.
Nota: se puede “refinar” el algoritmo aunque puede que al final nos encontremos con algún error. En este caso he probado que la cadena “-.
” pasa como válida aunque no es un número válido.
Para el caso de los números enteros (recordemos que existen los negativos) vamos a permitir que haya un guión al inicio, y que los demás números sean dígitos (con isdigit
). El código queda así, para una función que regresa un booleano:
int esEnteroValido(char cadena[LONGITUD_CADENA]) {
int longitud = strlen(cadena);
// Quitar espacios, saltos de línea, etcétera
while (longitud > 0 && isspace(cadena[longitud - 1]))
longitud--;
if (longitud <= 0) return 0;
int i;
for (i = 0; i < longitud; ++i) {
// En caso de que sea un guión, y que no esté al inicio, no es válido
if (cadena[i] == '-' && i > 0) {
return 0;
}
// Si no es dígito, tampoco es válido
if (!isdigit(cadena[i]) && cadena[i] != '-') {
return 0;
}
}
return 1;
}
Validamos también que al quitar espacios o saltos de línea, la longitud sea mayor que 0. Después recorremos y en caso de que el carácter sea un guión y que ese guión no haya sido encontrado al inicio, regresamos false
.
Además de la validación anterior, comprobamos si no es un dígito, para lo cual devolvemos false
.
Si se recorre toda la cadena y no se encontró ningún error, regresamos true
. Y así es como terminamos de validar un int en C. En este caso no encontré errores, aunque supongo que se me debió pasar algo por ahí.
Ahora veamos cómo validar un número flotante en C. En este caso también puede incluir puntos decimales. A simple vista veo dos errores, uno de ellos es la cadena -.
o por ejemplo 1.
Queda así:
int esFlotanteValido(char *cadena) {
int longitud = strlen(cadena);
// Quitar espacios, saltos de línea, etcétera
while (longitud > 0 && isspace(cadena[longitud - 1]))
longitud--;
if (longitud <= 0) return 0;
int i;
int haEncontradoElPunto = 0;
for (i = 0; i < longitud; ++i) {
// En caso de que sea un guión, y que no esté al inicio, no es válido
if (cadena[i] == '-' && i > 0) {
return 0;
}
// El punto solo puede aparecer una vez
if (cadena[i] == '.') {
// Si ya lo ha encontrado antes, entonces no es válido
if (haEncontradoElPunto) {
return 0;
} else {
haEncontradoElPunto = 1;
}
}
// Si no es dígito, tampoco es válido
if (!isdigit(cadena[i]) && cadena[i] != '-' && cadena[i] != '.') {
return 0;
}
}
return 1;
}
Si te fijas, también he agregado la validación de que el punto solo puede aparecer una vez.
Ahora veamos cómo trabajar con estas funciones de validación de números en C. Una vez que ya sabemos que son válidos, los convertimos.
Para el caso de la cadena a flotante usamos strtof
y para la conversión de cadena a entero usamos strtol
.
Si te preguntas por qué usamos fgets
en lugar de scanf
mira este post.
/*
____ _____ _ _ _
| _ \ | __ \ (_) | | |
| |_) |_ _ | |__) |_ _ _ __ _____| |__ _ _| |_ ___
| _ <| | | | | ___/ _` | '__|_ / | '_ \| | | | __/ _ \
| |_) | |_| | | | | (_| | | / /| | |_) | |_| | || __/
|____/ \__, | |_| \__,_|_| /___|_|_.__/ \__, |\__\___|
__/ | __/ |
|___/ |___/
____________________________________
/ Si necesitas ayuda, contáctame en \
\ https://parzibyte.me /
------------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
Creado por Parzibyte (https://parzibyte.me). Este encabezado debe mantenerse intacto,
excepto si este es un proyecto de un estudiante.
*/#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<stdlib.h>
#define LONGITUD_CADENA 1000
int esFlotanteValido(char *cadena) {
int longitud = strlen(cadena);
// Quitar espacios, saltos de línea, etcétera
while (longitud > 0 && isspace(cadena[longitud - 1]))
longitud--;
if (longitud <= 0) return 0;
int i;
int haEncontradoElPunto = 0;
for (i = 0; i < longitud; ++i) {
// En caso de que sea un guión, y que no esté al inicio, no es válido
if (cadena[i] == '-' && i > 0) {
return 0;
}
// El punto solo puede aparecer una vez
if (cadena[i] == '.') {
// Si ya lo ha encontrado antes, entonces no es válido
if (haEncontradoElPunto) {
return 0;
} else {
haEncontradoElPunto = 1;
}
}
// Si no es dígito, tampoco es válido
if (!isdigit(cadena[i]) && cadena[i] != '-' && cadena[i] != '.') {
return 0;
}
}
return 1;
}
int esEnteroValido(char cadena[LONGITUD_CADENA]) {
int longitud = strlen(cadena);
// Quitar espacios, saltos de línea, etcétera
while (longitud > 0 && isspace(cadena[longitud - 1]))
longitud--;
if (longitud <= 0) return 0;
int i;
for (i = 0; i < longitud; ++i) {
// En caso de que sea un guión, y que no esté al inicio, no es válido
if (cadena[i] == '-' && i > 0) {
return 0;
}
// Si no es dígito, tampoco es válido
if (!isdigit(cadena[i]) && cadena[i] != '-') {
return 0;
}
}
return 1;
}
int main() {
char numeroFlotanteComoCadena[LONGITUD_CADENA];
// Leer el número como cadena
printf("Ingresa un número flotante: ");
fgets(numeroFlotanteComoCadena, sizeof(numeroFlotanteComoCadena), stdin);
if (!esFlotanteValido(numeroFlotanteComoCadena)) {
printf("Número no válido");
return 0;
}
// Si llegamos aquí, el flotante es válido
float numeroFlotante = strtof(numeroFlotanteComoCadena, NULL);
printf("El flotante es: %0.2f y si le sumamos 10 es %0.2f", numeroFlotante, numeroFlotante + 10);
char numeroEnteroComoCadena[LONGITUD_CADENA];
// Leer el número como cadena
printf("\nIngresa un número entero: ");
fgets(numeroEnteroComoCadena, sizeof(numeroEnteroComoCadena), stdin);
if (!esEnteroValido(numeroEnteroComoCadena)) {
printf("Número no válido");
return 0;
}
// Si es válido, lo convertimos a entero
int numeroEntero = strtol(numeroEnteroComoCadena, NULL, 10); // <- El 10 es la base del número para strtol
printf("El entero es: %d y si le sumamos 10 es %d", numeroEntero, numeroEntero + 10);
return 0;
}
Dentro de la función main solicitamos dos números. En el primer caso validamos un flotante y en el segundo validamos un entero.
Hoy te voy a presentar un creador de credenciales que acabo de programar y que…
Ya te enseñé cómo convertir una aplicación web de Vue 3 en una PWA. Al…
En este artículo voy a documentar la arquitectura que yo utilizo al trabajar con WebAssembly…
En un artículo anterior te enseñé a crear un PWA. Al final, cualquier aplicación que…
Al usar Comlink para trabajar con los workers usando JavaScript me han aparecido algunos errores…
En este artículo te voy a enseñar cómo usar un "top level await" esperando a…
Esta web usa cookies.