toupper y tolower en C: ejercicio resuelto

toupper y tolower en C: ejercicio resuelto

Si buscas toupper y tolower en C ejercicio resuelto, aquí tienes los patrones esenciales: convertir un carácter individual, normalizar una cadena completa a mayúsculas o minúsculas, y realizar una búsqueda case-insensitive.

toupper y tolower están declaradas en <ctype.h> y operan sobre un int (el valor del carácter cast a unsigned char). Si el carácter no es una letra, se devuelve sin modificar.

Enunciado

  1. Convierte el carácter 'a' a mayúscula y 'Z' a minúscula.
  2. Normaliza la cadena "Hola, MUNDO! 123" a todo minúsculas y a todo mayúsculas.
  3. Compara dos cadenas ignorando mayúsculas/minúsculas sin modificar los originales.

Solución en C

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <stdio.h>
#include <ctype.h>
#include <string.h>

void a_minusculas(const char *src, char *dst) {
    while (*src) *dst++ = (char)tolower((unsigned char)*src++);
    *dst = '\0';
}

void a_mayusculas(const char *src, char *dst) {
    while (*src) *dst++ = (char)toupper((unsigned char)*src++);
    *dst = '\0';
}

/* Comparación case-insensitive sin modificar las cadenas originales */
int strcmp_ci(const char *a, const char *b) {
    while (*a && *b) {
        int da = tolower((unsigned char)*a);
        int db = tolower((unsigned char)*b);
        if (da != db) return da - db;
        a++; b++;
    }
    return tolower((unsigned char)*a) - tolower((unsigned char)*b);
}

int main(void) {
    /* 1. Carácter individual */
    printf("toupper('a') = '%c'\n", toupper('a'));
    printf("tolower('Z') = '%c'\n", tolower('Z'));

    /* 2. Cadena completa */
    const char *original = "Hola, MUNDO! 123";
    char buf[64];

    a_minusculas(original, buf);
    printf("Minusculas: %s\n", buf);

    a_mayusculas(original, buf);
    printf("Mayusculas: %s\n", buf);

    /* 3. Comparación case-insensitive */
    const char *s1 = "Programacion";
    const char *s2 = "PROGRAMACION";
    printf("strcmp_ci(\"%s\", \"%s\") = %d\n", s1, s2, strcmp_ci(s1, s2));

    return 0;
}

Resultado esperado

1
2
3
4
5
toupper('a') = 'A'
tolower('Z') = 'z'
Minusculas: hola, mundo! 123
Mayusculas: HOLA, MUNDO! 123
strcmp_ci("Programacion", "PROGRAMACION") = 0

Errores frecuentes

  • Pasar char directamente sin cast a unsigned char: en plataformas donde char es con signo, caracteres con código > 127 (acentos, ñ) se representan como valores negativos. El estándar exige que el argumento sea unsigned char o EOF.
  • Modificar la cadena original cuando solo se necesita comparar: lo correcto es convertir a una copia o comparar carácter a carácter como en strcmp_ci.
  • Asumir que toupper/tolower funciona con locales: las funciones de <ctype.h> dependen del locale activo. Para caracteres ASCII básicos (a-z, A-Z) siempre funcionan. Para ñ, á, etc., hay que usar setlocale o funciones de la biblioteca de internacionalización.
  • Olvidar el \0 al final al construir la cadena destino: la función a_minusculas agrega el terminador explícitamente; sin él printf("%s") leerá más allá del buffer.

Aplicación práctica

La normalización de cadenas a un caso uniforme se usa en búsquedas de texto, comparación de identificadores (comandos de shell, nombres de usuario), parseo de tokens de protocolos y cualquier sistema donde la entrada del usuario no tenga caso fijo.

Siguiente ejercicio recomendado

Práctica guiada y libro completo

Si quieres una ruta completa con progresión real de dificultad:

FAQ

¿Por qué hay que hacer cast a unsigned char antes de toupper/tolower?

Porque el estándar de C especifica que el argumento debe ser representable como unsigned char o debe ser EOF. En plataformas donde char tiene signo, un carácter con código > 127 se convierte en un entero negativo, lo que produce comportamiento indefinido al pasarlo a toupper/tolower. El cast (unsigned char) convierte el valor al rango correcto (0–255).

¿toupper y tolower modifican la cadena original?

No. Son funciones puras que reciben un carácter y devuelven otro. Para modificar una cadena hay que iterar carácter a carácter y reemplazar cada elemento con el resultado, como hace a_mayusculas en este ejercicio.

¿Cómo funciona la normalización con caracteres acentuados (á, é, ñ)?

Las funciones de <ctype.h> trabajan con el locale activo (setlocale). En el locale "C" (por defecto) solo tratan las letras ASCII. Para soportar caracteres UTF-8 como á o ñ hay que usar towupper/towlower de <wctype.h> con tipos wchar_t, o una biblioteca de internacionalización como ICU.