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).

Algoritmo de validación

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.

Validar entero

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í.

Validación de número float en C

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.

Poniendo todo junto

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.

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.
parzibyte

Programador freelancer listo para trabajar contigo. Aplicaciones web, móviles y de escritorio. PHP, Java, Go, Python, JavaScript, Kotlin y más :) https://parzibyte.me/blog/software-creado-por-parzibyte/

Entradas recientes

Desplegar PWA creada con Vue 3, Vite y SQLite3 en Apache

Ya te enseñé cómo convertir una aplicación web de Vue 3 en una PWA. Al…

3 días hace

Arquitectura para wasm con Go, Vue 3, Pinia y Vite

En este artículo voy a documentar la arquitectura que yo utilizo al trabajar con WebAssembly…

3 días hace

Vue 3 y Vite: crear PWA (Progressive Web App)

En un artículo anterior te enseñé a crear un PWA. Al final, cualquier aplicación que…

3 días hace

Errores de Comlink y algunas soluciones

Al usar Comlink para trabajar con los workers usando JavaScript me han aparecido algunos errores…

3 días hace

Esperar promesa para inicializar Store de Pinia con Vue 3

En este artículo te voy a enseñar cómo usar un "top level await" esperando a…

3 días hace

Solución: Apache – Server unable to read htaccess file

Ayer estaba editando unos archivos que son servidos con el servidor Apache y al visitarlos…

4 días hace

Esta web usa cookies.