Apunte Cadenas de Caracteres
Transcripción
Apunte Cadenas de Caracteres
Universidad Tecnológica Nacional Facultad Regional Córdoba Departamento Ingeniería en Electrónica Catedra de Infomática 1 JTP Ing. Mascietti, Norma PA Pereira, Mauro Alejandro Cadena de caracteres 1. Fundamentos de cadenas y caracteres Los caracteres son bloques de construcción fundamentales para los programas fuente. Un programa puede contener constantes de carácter. Una constante de carácter es un valor int representado por un carácter entre comillas sencillas. El valor de una constante de carácter es el valor entero del carácter en el conjunto de caracteres de la máquina. Por ejemplo, 'z' representa el valor entero de z, y '\n' representa el valor entero de una nueva línea. Una cadena es un conjunto de caracteres tratados como una sola unidad. Una cadena puede incluir letras, dígitos y varios caracteres especiales como +, -, *, y $. En C, las literales de cadena, o constanes de cadena, se escriben dentro de comillas dobles de la siguiente manera: “Juan P. Pérez” (un nombre) “99999 de Eje Central” (la dirección de una calle) En C, una cadena es un arreglo de caracteres, los cuales terminan con el carácter nulo ('\0'). Se accede a una cadena mediante un apuntador a su primer carácter. El valor de una cadena es la dirección del primer carácter. Así, en C, es apropiado decir que una cadena es un apuntador, de hecho, un apuntador al primer carácter de la cadena. En este sentido, las cadenas son como arreglos, debido a que un arreglo también es un apuntador al primer elemento. Un arreglo de caracteres o una variable de tipo char * puede inicializarse con una cadena en la definición. Las definiciones char color[] = “azul”; const char *ptrColor = “azul”; inicializan una variable con la cadena “azul”. La primera definición crea un arreglo de 5 elementos, color, que contiene los caracteres 'a', 'z', 'u', 'l' y '\0'. La segunda variable crea una variable apuntador, ptrColor, que apunta a la cadena “azul” en algún lugar de la memoria. La definición del arreglo anterior también podría escribirse como char color[] = {'a', 'z', 'u', 'l', '\0'}; Cuando se define un arreglo para que contenga una cadena, éste debe ser lo suficiente grande para almacenar la cadena y su carácter de terminación nulo. La definición anterior determina automáticamente el tamaño del arreglo, basándose en el número de inicializaciones de la lista de inicialización ('a', 'z', 'u', 'l', '\0'). No almacenar suficiente espacio en un arreglo de caracteres para almacenar el carácter nulo que termina una cadena, es un error. Si una cadena es más grande que el arreglo de caracteres en el cual se va a almacenar, los caracteres más allá del final del arreglo sobrescribirán los datos siguientes en la memoria del arreglo. Una cadena puede almacenarse en un arreglo, por medio de scanf. Por ejemplo, la siguiente instrucción almacena el arreglo de caracteres palabra[20]: scanf( “%s”, palabra ); La cadena que introduce el usuario se almacena en palabra. Observe que palabra es un arreglo, el cual es, por supuesto, un apuntador, de modo que no necesitamos un & con el argumento palabra. La función scanf leerá caracteres hasta encontrar un espacio, un tabulador, un indicador de nueva línea o de fin de archivo. Observe que la cadena no debe ser mayor que 19 caracteres para dejar espacio suficiente para el carácter de terminación nulo. Para un arreglo de caracteres que se imprimirá como una cadena, el arreglo debe contener el carácter de terminación nulo. La cadena de caracteres está definida como un arreglo de caracteres, debido a que el nombre de un arreglo es la dirección de memoria del primer elemento del arreglo, por lo que si se iguala el nombre del arreglo al nombre de un puntero, a este puntero se le puede aplicar aritmética de punteros (ver apunte Punteros) para poder desplazarse entre los datos del arreglo. Las funciones scanf() y printf() reconocen a los espacios introducidos con la barra espaciadora como finales de cadena. Esto puede solucionarse usando las funciones gets() y puts() incluidas en la librería ctype.h 1 Universidad Tecnológica Nacional Facultad Regional Córdoba Departamento Ingeniería en Electrónica Catedra de Infomática 1 JTP Ing. Mascietti, Norma PA Pereira, Mauro Alejandro 2. Funciones de manipulación de cadenas de la biblioteca de manipulación de cadenas La biblioteca de manipulación de cadenas (<string.h>) proporciona muchas funciones útiles para manipular datos de cadenas (copiar y concatenar cadenas), comparar cadenas, buscar caracteres y otras cadenas dentro de cadenas, separar cadenas en tockens (separar cadenas en sus piezas lógicas) y determinar la longitud de cadenas. Vamos a ver algunas de ellas. Prototipos de función Descripción de la función char *strcpy (char *s1, const char *s2) Copia la cadena s2 dentro del arreglo s1. Devuelve el valor de s1. char *strncpy (char *s1, const char *s2, size_t n) Copia al menos n caracteres de la cadena s2 dentro del arreglo s1. Devuelve el valor de s1n. char *strcat (char *s1, const char *s2) Agrega la cadena s2 al arreglo s1. El primer carácter de s2 sobrescribe al carácter de terminación nulo de s1. Devuelve el valor de s1. char *strcat (char *s1, const char *s2, size_t n) Agrega al menos n caracteres de la cadena s2 al arreglo s1. El primer carácter de s2 sobrescribe al carácter de terminación nulo de s1. Devuelve el valor de s1. • • • • En la función strcpy, s1 (un arreglo de caracteres) debe ser lo suficientemente grande para almacenar la cadena s2 y el carácter de terminación nulo, el cual también se copia. Observe que en la función strncpy, un carácter de terminación nulo se escribe solamente si el número de caracteres a copiar (en s1) es al menos mayor en uno que la longitud de la cadena (s2). Por ejemplo, si “prueba” es el segundo argumento, se escribe un carácter de terminación nulo sólo si el tercer argumento de strncpy, es al menos 7 (seis caracteres en “prueba” más el carácter de terminación nulo). Si el tercer argumento es mayor que 7, el carácter nulo se agrega al arreglo hasta que se escriben el número total de caracteres especificados en el tercer argumento. Al usar la función srtcat, el primer carácter del segundo argumento remplaza el nulo ('\0') que termina la cadena del primer argumento. El programador debe asegurarse de que el arreglo utilizado para almacenar la primera cadena es lo suficientemente grande para almacenar la primera cadena, la segunda cadena y el carácter de terminación nulo copiado desde la segunda cadena. La función strncat agrega un carácter de terminación nulo automáticamente al resultado. Un error común de programación es no agregar el carácter de terminación nulo al primer argumento de strncpy, cuando el tercer argumento es menor o igual que la longitud de la cadena del segundo argumento. La figura 2.1 utiliza strcpy para copiar la cadena completa del arreglo x dentro del arreglo y, y utiliza strncpy para copiar los primeros 14 caracteres del arreglo x dentro del arreglo z. Se agrega un carácter nulo ('\n') al arreglo z, debido a que la llamada a strncpy en el programa no escribe un carácter de terminación nulo (el tercer argumento es menor que la longitud de la cadena del segundo argumento). 2 Universidad Tecnológica Nacional Facultad Regional Córdoba Departamento Ingeniería en Electrónica Catedra de Infomática 1 JTP Ing. Mascietti, Norma PA Pereira, Mauro Alejandro La Figura 2.2 muestra las funciones strcat y strncat. 3. Funciones de comparación de la biblioteca de manipulación de cadenas Prototipos de función Descripción de la función int strcmp ( const char *s1, const char *s2 ); Compara la cadena s1 con la cadena s2. La función devuelve 0, menor que 0, o mayor que 0, si s1 es igual, menor, o mayor que s2, respectivamente. int strncmp ( const char *s1, const char *s2, size_t n ); Compara hasta n caracteres de la cadena s1 con la cadena s2. La función devuelve 0, menor que 0, o mayor que 0, si s1 es igual, menor, o mayor que s2, respectivamente. Un error común de programación es suponer que strcmp y strncmp devuelven 1 cuando sus argumentos son iguale, ambas funciones devuelven 0. ¿Cómo sabe la computadora que una letra en particular va antes que otra? Todos los caracteres se representan en la computadora como códigos numéricos (ver Códigos de los caracteres de ASCII), cuando la computadora compara dos cadenas, en realidad compara los códigos numéricos de los caracteres de las cadenas. Observe la Figura 3.1 con las funciones strcmp y strncmp. 3 Universidad Tecnológica Nacional Facultad Regional Córdoba Departamento Ingeniería en Electrónica Catedra de Infomática 1 JTP Ing. Mascietti, Norma PA Pereira, Mauro Alejandro 4. Funciones de búsqueda de la biblioteca de manipulación de cadenas Prototipos de función Descripción de la función char *strchr( const char *s, int c ); Localiza la primera ocurrencia del carácter c en la cadena s. Si se localiza c, se devuelve un apuntador a c en s. De lo contrario, se devuelve un apuntador NULL. size_t strcspn( const char *s1, const char *s2 ); Determina y devuelve la longitud del segmento inicial de la cadena s1, que consiste en los caracteres no contenidos de la cadena s2. size_t strspn( const char *s1, const char *s2 ); Determina y devuelve la longitud del segmento inicial de la cadena s1, que consiste sólo en los caracteres contenidos en la cadena s2. char *strpbrk( const char *s1, const char *s2 ); Localiza la primera ocurrencia en la cadena s1 de cualquier carácter de la cadena s2. Si se localiza un carácter de la cadena s2, se devuelve un apuntador al carácter de la cadena s1. De lo contrario, se devuelve un apuntador NULL. char *strrchr( const char *s, int c ); Localiza la última ocurrencia de c en la cadena s. Si se localiza a c, se devuelve un apuntador a c en la cadena s. De lo contrario, se devuelve un apuntador NULL. char *strstr( const char *s1, const char *s2 ); Localiza la primera ocurrencia en la cadena s1 de la cadena s2. Si se localiza la cadena, se devuelve un apuntador a la cadena en s1. De lo contrario, se devuelve un apuntador NULL. char *strtok( char *s1, const char *s2 ); Una secuencia de llamadas a strtok separa la cadena s1 en “tokens” (piezas lógicas como palabras de una línea de texto) separados por caracteres contenidos en la cadena s2. La primera llamada contiene s1 como el primer argumento, y las llamadas subsiguientes contienen a NULL como el primer argumento, para continuar separando la misma cadena. Un apuntador al token actual es devuelto por cada llamada. Si no hay más tokens cuando se llama a la función, se devuelve NULL. La Figura 4.1 utiliza strchr para buscar la primera ocurrencia de 'a' y la primera ocurrencia de 'z' en la cadena “Esta es una prueba”. 4 Universidad Tecnológica Nacional Facultad Regional Córdoba Departamento Ingeniería en Electrónica Catedra de Infomática 1 JTP Ing. Mascietti, Norma PA Pereira, Mauro Alejandro La función strcspn determina la longitud de la parte inicial de la cadena correspondiente a su primer argumento, la cual no contiene carácter alguno de la cadena de su segundo argumento. La función devuelve la longitud del segmento. La Figura 4.3 muestra un programa que localiza la primera ocurrencia en cadena1 de cualquier carácter de cadena2. La Figura 4.4 muestra un programa que busca la última ocurrencia del carácter 'z' en la cadena “Un zoo tiene muchos animales, incluso zebras”. 5 Universidad Tecnológica Nacional Facultad Regional Córdoba Departamento Ingeniería en Electrónica Catedra de Infomática 1 JTP Ing. Mascietti, Norma PA Pereira, Mauro Alejandro La función strspn (Figura 4.5) determina la longitud de la parte inicial de una cadena que se encuentra en su primer argumento, y que contiene sólo caracteres de la cadena en su segundo argumento. La función devuelve la longitud del segmento. La Figura 4.6 utiliza strstr para encontrar la cadena “def” en la cadena “abcdefabcdef”. La función strtok (Figura 4.7) se utiliza para separar una cadena en una serie de tokens. Un token es una secuencia de caracteres separados por demilitadores (generalmente espacios o marcas de puntuación). Por ejemplo, en una línea de texto, cada palabra puede considerarse como un token, y los espacios que separan a las palabras pueden considerarse delimitadores. 6 Universidad Tecnológica Nacional Facultad Regional Córdoba Departamento Ingeniería en Electrónica Catedra de Infomática 1 JTP Ing. Mascietti, Norma PA Pereira, Mauro Alejandro Para separar una cadena en tokens (suponiendo que la cadena contiene más de un token), se necesitan múltiples llamadas a strtok. La primera llamada a strtok contiene dos argumentos, una cadena que va a separarse en tokens, y una cadena que contiene caracteres que separan los tokens. En la Figura 4.7, la instrucción ptrToken = strtok( cadena, “ ”); asigna a ptrToken un apuntador al primer token en la cadena. En segundo argumento de strtok, “ ”, indica que los tokens de la cadena están separados por espacios. La función strtok busca el primer carácter de la cadena que no sea un carácter delimitador 5. Ejercitación EJEMPLO 1: Escriba un programa que inicialice un arreglo de caracteres con la palabra “electronica”, luego otro arreglo que se inicialice con la misma palabra pero con el fin de cadena localizado antes de la “n”.Imprima los dos arreglos y observe las diferencias. #include <stdio.h> int main (void) { char cadena1[]={'e','l','e','c','t','r','o','n','i','c','a','\0'}; char cadena2[12]={'e','l','e','c','t','r','\0','n','i','c','a'}; printf("La cadena entera es\n\t\t"); puts(cadena1); printf("La cadena con el fin desplazado es\n\t\t"); puts(cadena2); } EJEMPLO 2: Escriba un programa que me permita introducir una cadena de caracteres y luego, mediante una función, convierta la primer letra en mayúscula y las siguientes 49 en letras minúsculas. #include <stdio.h> #include <ctype.h> //para las funciones toupper y tolower #define MAXCADENA 50 void ConvertirLetras(char *cadena); int main (void) { char cadena[MAXCADENA+1]; printf("\nEscriba una cadena de hasta %d caracteres, " "luego presione ENTER:\n\n\n\t", MAXCADENA); gets(cadena); ConvertirLetras(cadena); printf("\n\t%s\n\n\n", cadena); system ("PAUSE"); return 0; } void ConvertirLetras(char *cadena) 7 Universidad Tecnológica Nacional Facultad Regional Córdoba Departamento Ingeniería en Electrónica Catedra de Infomática 1 JTP Ing. Mascietti, Norma PA Pereira, Mauro Alejandro { *cadena = toupper (*cadena); while (*cadena != '\0') { cadena=cadena+1; *cadena = tolower(*cadena); } } EJEMPLO 3: Escriba un programa que cuente la cantidad de letras ‘a’ y ‘ ’ (espacios) que se repiten. Luego, cambiar cada ‘ ’ por un guión bajo. #include <stdio.h> int main (void) { char cadena[] = "Me encanta informatica I"; char *p, *q; int espacios=0, letras_a=0; p = cadena; q = cadena; while (*p != '\0') { if (*p==' ') espacios++; if (*p=='a') letras_a++; p++; } printf( "De la cadena: \"%s\" , podemos saber que hay:\n\n", cadena ); printf( "\t %i espacios\n", espacios ); printf( "\t %i letras a\n", letras_a ); printf( "\nReemplazando los espacios por guiones bajos, la cadena nos queda:\n", cadena ); system ("PAUSE"); while (*q!='\0') { if (*q==' ') *q = '_'; q++; } printf( "\n\n\t\"%s\" \n\n\n", cadena ); system ("PAUSE"); return 0; } 8 Universidad Tecnológica Nacional Facultad Regional Córdoba Departamento Ingeniería en Electrónica Catedra de Infomática 1 JTP Ing. Mascietti, Norma PA Pereira, Mauro Alejandro EJEMPLO 4: Escriba un programa que me permita introducir una palabra y luego convierta las letras a mayúsculas y a minúsculas alternativamente. #include <stdio.h> #include <ctype.h> int main() { char palabra[100]; int i=0; printf("Escriba una palabra\n\n: "); gets(palabra); printf("\n\nLa palabra alternada entre mayusculas y minusculas queda\n\n: "); while (palabra[i]!='\0') { if ( (i % 2) == 0) printf("%c", toupper(palabra[i])); else printf("%c", tolower(palabra[i])); i++; } printf( "\n\n\n" ); system( "PAUSE" ); return 0; } 9