El tipo char, y constantes carácteres

Hasta ahora vimos el tipo int para valores enteros y float para valores decimales.

Existe un tipo de valores llamado char, para "character", que ocupa menos espacio en memoria y sirve para representar carácteres:

char c = 'a'; /* declaro el caracter c y le asigno el valor entero
                 constante que corresponde al carácter 'a' */

Una constante carácter se escribe con un carácter encerrado entre apóstrofes: 'a', 'Z', '2', '+', '\n', etc.

Mostrar un valor de tipo char con printf se hace con el especificador de conversión %c:

char letra = 'Z';
printf("%c\n", letra);

La función getchar permite leer un carácter ingresado por el usuario sin que el/ella tenga que tipear "enter". Es más fácil que usar scanf:

char letra;
letra = getchar();

Una variable o constante de tipo char ocupa 1 byte en memoria. Este byte puede ser visto también como un entero:

#include <stdio.h>
int main(void){
  char letra = 'Z';
  printf("%c\n", letra);
  printf("%d\n", letra);  /* se muestra el entero 90 */
  return 0;
}

También se puede directamente asignar un entero (dentro del rango 0 a 255) a una variable de tipo char:

#include <stdio.h>
int main(void){
  char letra = 80;
  printf("%d\n", letra);
  printf("%c\n", letra);  /* se muestra el carácter 'P' */
  return 0;
}

El lenguaje C usa una correspondencia entre carácteres y enteros que se es especificada en la tabla ASCII.

Es decir, para cada uno de los 256 valores distintos que puede tener una variable de tipo char, se asocia algun carácter, visible (que puede ser alfanumérico o no), o invisible (por ejemplo '\n', el carácter que representa el salto de línea, pero hay más).

Arreglos de carácteres (o cadenas de carácteres)

Una cadena de carácteres (o string) como la constante "hola", es en realidad un arreglo de carácteres:

'h'  'o'  'l'  'a' '\0'

con un valor final \0 agregado por el compilador.

Si miramos los valores enteros de la cadena "hola" en memoria, vamos a ver:

104  111  108  97   0 

En inglés se dice que esas strings son "null terminated", porque la macro NULL representa también el valor 0.

Una cadena se muestra con printf con el especificador de conversión %s ("string"):

char mensaje[5]="hola"; /* "hola" tiene 4 carácteres + el \0 final,
                            necesitamos un arreglo de tamaño 5 */ 

printf("%s", mensaje); /* no usar "&" porque mensaje es un arreglo */

Lectura de cadenas de carácteres en la entrada estandard

Este programita lee una string de dos formas distintas. Probar ingresando un nombre con espacio ("Juan Rodriguez"):

#include <stdio.h>
#define MAX 100

int main(void){
  int i=0;
  char name[MAX];

  printf("Ingresar un nombre con espacios:\n");
  scanf("%s", name);
  printf("El nombre leido por scanf es: %s.\n", name);

  return 0;
}

¿Qué observan cuando ingresan una cadena de carácteres con espacios?

Se puede resolver esto dándole a scanf un especificador de conversión un poco distinto. Ver el apunte "Aprenda C", sección 8.2.

Ejercicios con cadenas de carácteres

Consideramos el alfabéto latino de 26 letras, sin tildes (sin los caracteres acentuados), y sin la letra ñ.

Tener a mano alguna tabla ASCII.

¿Cual es el rango del alfabeto latino en minúsculas (ie, desde 'a' hasta 'z') en la tabla ASCII?

¿Cual es el rango del alfateto latino en mayúsculas (ie, desde 'A' hasta 'Z')?

¿Qué diferencia hay entre el carácter 'a' y el carácter 'A'? ¿'z' y 'Z'?

Escribir la función int es_minuscula(const char c) que devuelve 1 si el carácter dado es dentro del rango 'a' hasta 'z', y 0 sino.

Escribir la función int es_mayuscula(const char c) que devuelve 1 si el carácter dado es dentro del rango 'A' hasta 'Z', y 0 sino.

Escribir la función char cambiar_char(const char c) que, dada una minúscula, devuelve la correspondiente mayúscula, y vice versa. Si es dada otro carácter, devuelve el mismo carácter.

Escribir la función void cambiar_cadena(char cadena[]) que aplica carácter por carácter la función cambiar_chara una cadena.

Escribir un programa cadenas.c que lee una cadena dada por el usuario (posiblemente con espacios), le aplica cambiar_cadena y la muestra de nuevo.

Codificación de mensajes con rot13

rot13 es un algoritmo de codificación de mensajes muy sencillo, que permite hacer incomprensible, o menos obvio, un mensaje mediante substitución de carácteres.

"rot13" significa "rotar 13 posiciones", y consiste en reemplazar en un texto cada letra por la letra que está trece posiciones por delante en el alfabeto. El resto de los carácteres no es modificado.

Por ejemplo, el texto siguiente:

En el capitulo 45 de Games of Cards, muere Kenny.

es convertido en:

Ra ry pncvghyb 45 qr Tnzrf bs Pneqf, zhrer Xraal.

rot13 tiene una propiedad útil: es simétrico. Es decir que al mismo tiempo sirve para codificar y para decodificar un mensaje.

Pueden probar un convertidor en línea rot13.

Implementar rot13 en una función de tipo void rot13(char cadena[]).

Usarla en un programa pide una frase al usuario y la muestra transformada con el algoritmo rot13.