Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Introduccin
Las cadenas por dentro
Funciones de manejo de cadenas
o strlen
o strcpy
o strcat
o sprintf
o strcmp
Entrada de cadenas por teclado
o scanf
o gets
o Qu son los buffer y cmo funcionan
o getchar
Recorrer cadenas con punteros
Arrays de cadenas
Ordenar un array de cadenas
Ejercicios
Introduccin
Vamos a ver por fin cmo manejar texto con
mostrarlo por pantalla.
Para empezar dir que en C no existe un tipo string como en otros lenguajes. No
existe un tipo de datos para almacenar texto, se utilizan arrays de chars. Funcionan
igual que los dems arrays con la diferencia que ahora jugamos con letras en vez
de con nmeros.
Se les llama cadenas, strings o tiras de caracteres. A partir de ahora les
llamaremos cadenas.
Para declarar una cadena se hace como un array:
char texto[20];
Al igual que en los arrays no podemos meter ms de 20 elementos en la cadena.
Vamos a ver un ejemplo para mostrar el nombre del usuario en pantalla:
#include <stdio.h>
int main()
{
char nombre[20];
printf( "Introduzca su nombre (20 letras mximo): " );
scanf( "%s", nombre );
printf( "\nEl nombre que ha escrito es: %s\n", nombre );
}
Vemos cosas curiosas como por ejemplo que en el scanf no se usa el smbolo &. No
hace falta porque es un array, y ya sabemos que escribir el nombre del array es
equivalente a poner &nombre[0].
Tambin puede llamar la atencin la forma de imprimir el array. Con slo usar %s
ya se imprime todo el array. Ya veremos esto ms adelante.
Si alguno viene de algn otro lenguaje esto es importante: en
esto:
C no se puede hacer
int main()
{
char texto[20];
texto = "Hola";
}
#include <stdio.h>
int main()
{
char nombre[] = { 'G', 'o', 'r', 'k', 'a' };
printf( "Texto: %s\n", nombre );
}
En mi ordenador sala:
Texto: GorkaTamao de la cadena: 5 bytes
Pero en el tuyo despus de "Gorka" puede aparecer cualquier cosa. Lo que aqu
sucede es que no encuentra el smbolo '\0' y no sabe cundo dejar de imprimir.
Afortunadamente, cuando metemos una cadena se hace de la primera forma y el
se encarga de poner el dichoso smbolo al final.
C para el manejo de
strlen
strcpy
strcat
sprintf
strcmp
strlen
Esta funcin nos devuelve el nmero de caracteres que tiene la cadena (sin contar
el '\0').
#include <stdio.h>
#include <string.h>
int main()
{
char texto[]="Gorka";
int longitud;
longitud = strlen(texto);
printf( "La cadena \"%s\" tiene %i caracteres.\n", texto,
longitud );
}
Crea tus propias funciones: Vamos a ver cmo se hara esta funcin si no
dispusiramos de ella. Si no te enteras cmo funciona consulta Recorrer cadenas
con punteros.
#include <stdio.h>
#include <string.h>
int main()
{
char texto[]="Gorka";
char *p;
int longitud=0;
p = texto;
while (*p!='\0')
{
longitud++;
printf( "%c\n", *p ); /* Mostramos la letra actual */
p++;
/* Vamos a la siguiente letra */
}
printf( "La cadena \"%s\" tiene %i caracteres.\n", texto,
longitud );
}
Para medir la longitud de la cadena usamos un puntero para recorrerla (el puntero
p). Hacemos que p apunte a texto. Luego entramos en un bucle while. La condicin
del bucle comprueba si se ha llegado al fin de cadena ('\0'). Si no es as suma 1 a
longitud, muestra la letra por pantalla e incrementa el puntero en 1 (con esto
pasamos a la siguiente letra).
strcpy
#include <string.h>
char *strcpy(char *cadena1, const char *cadena2);
Copia el contenido de cadena2 en cadena1. cadena2 puede ser una variable o una
cadena directa (por ejemplo "hola"). Debemos tener cuidado de que la cadena
destino (cadena1) tenga espacio suficiente para albergar a la cadena origen
(cadena2).
#include <stdio.h>
#include <string.h>
int main()
{
char textocurso[] = "Este es un curso de C.";
char destino[50];
strcpy( destino, textocurso );
printf( "Valor final: %s\n", destino );
}
Vamos a ver otro ejemplo en el que la cadena destino es una cadena constante
("Este es un curso de C") y no una variable. Adems en este ejemplo vemos que la
cadena origen es sustituida por la cadena destino totalmete. Si la cadena origen es
ms larga que la destino, se eliminan las letras adicionales.
#include <stdio.h>
#include <string.h>
int main()
{
char destino[50] = "Esto no es un curso de HTML sino un curso de
C.";
printf( "%s\n", destino );
strcpy( destino, "Este es un curso de C." );
printf( "%s\n", destino );
}
strcat
#include <string.h>
char *strcat(char *cadena1, const char *cadena2);
Copia la cadena2 al final de la cadena1.
#include <stdio.h>
#include <string.h>
int main()
{
char nombre_completo[50];
char nombre[]="Gorka";
char apellido[]="Urrutia";
strcpy(
strcat(
strcat(
printf(
}
nombre_completo, nombre );
nombre_completo, " " );
nombre_completo, apellido );
"El nombre completo es: %s.\n", nombre_completo );
Como siempre tenemos que asegurarnos que la variable en la que metemos las
dems cadenas tenga el tamao suficiente. Con la primera lnea metemos el
nombre en nombre_completo. Usamos strcpy para asegurarnos de que queda
borrado cualquier dato anterior. Luego usamos un strcat para aadir un espacio y
finalmente metemos el apellido.
sprintf
#include <stdio.h>
int sprintf(char *destino, const char *format, ...);
Funciona de manera similar a printf, pero en vez de mostrar el texto en la pantalla
lo guarda en una variable (destino). El valor que devuelve (int) es el nmero de
caracteres guardados en la variable destino.
strcmp
#include <string.h>
int strcmp(const char *cadena1, const char *cadena2);
Compara cadena1 y cadena2. Si son iguales devuelve 0. Un nmero negativo si
cadena1 va antes que cadena2 y un nmero positivo si es al revs:
cadena1 == cadena2 -> 0
cadena1 > cadena2 -> nmero negativo
cadena1 < cadena2 -> nmero positivo
#include <stdio.h>
#include <string.h>
int main()
{
char nombre1[]="Gorka";
char nombre2[]="Pedro";
printf( "%i", strcmp(nombre1,nombre2));
}
scanf
gets
Qu son los buffer y cmo funcionan
getchar
scanf
Hemos visto en captulos anteriores el uso de scanf para nmeros, ahora es el
momento de ver su uso con cadenas.
Scanf almacena en memoria (en un buffer) lo que vamos escribiendo. Cuando
pulsamos ENTER (o Intro o Return, como se llame en cada teclado) lo analiza,
comprueba si el formato es correcto y por ltimo lo mete en la variable que le
indicamos.
#include <stdio.h>
#include <string.h>
int main()
{
char cadena[30];
printf( "Escribe una palabra: " );
fflush( stdout );
scanf( "%s", cadena );
printf( "He guardado: \"%s\" \n", cadena );
}
Ejecutamos el programa e introducimos la palabra "hola". Esto es lo que tenemos:
Escribe una palabra: hola
He guardado: "hola"
Si ahora introducimos "hola amigos" esto es lo que tenemos:
Escribe una palabra: hola amigos
He guardado: "hola"
Slo nos ha cogido la palabra "hola" y se ha olvidado de amigos. Por qu? pues
porque scanf toma una palabra como cadena. Usa los espacios para separar
variables.
Es importante siempre asegurarse de que no vamos a almacenar en cadena ms
letras de las que caben. Para ello debemos limitar el nmero de letras que le va a
introducir scanf. Si por ejemplo queremos un mximo de 5 caracteres usaremos
%5s:
#include <stdio.h>
#include <string.h>
int main()
{
char cadena[6];
printf( "Escribe una palabra: " );
fflush( stdout );
scanf( "%5s", cadena );
printf( "He guardado: \"%s\" \n", cadena );
}
Si metemos una palabra de 5 letras (no se cuenta '\0') o menos la recoge sin
problemas y la guarda en cadena.
Escribe una palabra: Gorka
He guardado: "Gorka"
Si metemos ms de 5 letras nos cortar la palabra y nos dejar slo 5.
Escribe una palabra: Juanjo
He guardado: "Juanj"
gets
Esta funcin nos permite introducir frases enteras, incluyendo espacios.
#include <stdio.h>
char *gets(char *buffer);
Almacena lo que vamos tecleando en la variable buffer hasta que pulsamos ENTER.
Si se ha almacenado algn caracter en buffer le aade un '\0' al final y devuelve un
puntero a su direccin. Si no se ha almacenado ninguno devuelve un puntero NULL.
#include <stdio.h>
#include <string.h>
int main()
{
char cadena[30];
char *p;
printf( "Escribe una palabra: " );
fflush( stdout );
p = gets( cadena );
if (p) printf( "He guardado: \"%s\" \n", cadena );
else printf( "No he guardado nada!\n" );
}
Esta funcin es un poco peligrosa porque no comprueba si nos hemos pasado del
espacio reservado (de 29 caracteres en este ejemplo: 29letras+'\0').
getchar
Recorrer cadenas con punteros
Las cadenas se pueden recorrer de igual forma que hacamos con las matrices,
usando punteros.
Vamos a ver un ejemplo: Este sencillo programa cuenta los espacios y las letras 'e'
que hay en una cadena.
#include <stdio.h>
#include <string.h>
int main()
{
char cadena[]="Gorka es un tipo estupendo";
char *p;
int espacios=0, letras_e=0;
p = cadena;
while (*p!='\0')
{
if (*p==' ') espacios++;
if (*p=='e') letras_e++;
p++;
}
Arrays de cadenas
Un array de cadenas puede servirnos para agrupar una serie de mensajes. Por
ejemplo todos los mensajes de error de un programa. Luego para acceder a cada
mensaje basta con usar su nmero.
#include <stdio.h>
#include <string.h>
int error( int errnum )
{
char *errores[] = {
"No
"No
"No
"Me
};
int main()
{
char *dichos[ELEMENTOS] = {
"La avaricia rompe el saco",
"Ms Vale pjaro en mano que ciento volando",
"No por mucho madrugar amanece ms temprano",
"Ao de nieves, ao de bienes",
"A caballo regalado no le mires el diente"
};
char *temp;
int i, j;
printf( "Lista desordenada:\n" );
for( i=0; i<ELEMENTOS; i++ )
printf( " %s.\n", dichos[i] );
for( i=0; i<ELEMENTOS-1; i++ )
for( j=0; j<ELEMENTOS; j++ )
if (strcmp(dichos[i], dichos[j])>0)
{
temp = dichos[i];
dichos[i] = dichos[j];
dichos[j] = temp;
}
printf( "Lista ordenada:\n" );
for( i=0; i<ELEMENTOS; i++ )
printf( " %s.\n", dichos[i] );
}
Cmo funciona el programa:
1.- Tomamos el primer elemento de la matriz. Lo comparamos con todos los
siguientes. Si algunos es anterior los intercambiamos. Cuando acabe esta primera
vuelta tendremos "A caballo regalado no le mires el diente" en primera posicin.
2.- Tomamos el segundo elemento. Lo comparamos con el tercero y siguientes. Si
alguno es anterior los intercambiamos. Al final de esta vuelta quedar "A caballo
regalado no le mires el diente" en segunda posicin.
Para mayor claridad (eso espero) voy a sustituir cada cadena por su primera letra
(menos la de "Ao de nieves..." que la sustituyo por A). Y as represento el
proceso:
0
9
1
2
3
M
4
N
5
L
1
9'
L
M
N
2
10
L
M
N
3'
4'
6'
7'
8'
L
M
N
A
M
N
A
M
N
A
M
N
M
N
M
N
L
N
L
N
A
N
10'
L
M
N
L
A
A
N
A
N
A
M
M
A