Descarga la aplicación para disfrutar aún más
Vista previa del material en texto
- 151 - Unidad 8 Caracteres y Strings 8.1 Definiciones de caracteres y strings 8.1.1 Carácter Como se mencionó en el tema de “tipos de datos en C”, un carácter se define como tipo char: Una variable char es similar a una variable int pero con la salvedad que puede almacenar un valor entero más chico (en el rango de -128 a 127). Los valores enteros positivos de las variables de tipo char están relacionadas con la tabla de caracteres ASCII, tal como se muestra en la tabla 8.1. Tabla 8.1 Tabla de caracteres ASCII Si en una variable char se almacena el valor entero 65 luego se puede imprimir dicho valor como carácter y si se ve en la tabla ASCII dicho valor está asociado al carácter 'A'. En el tema de “Entrada y salida de datos estándar” se mencionó que existen las funciones: getchar(): que lee un carácter del teclado. - 152 - putchar(): la cual imprime un carácter en la pantalla en la posición actual del cursor. y se mostró un ejemplo. También existe la función getch(), la cual lee un solo carácter directamente desde el teclado, sin mostrar tal carácter en pantalla. En el ejemplo 8.1 se definen tres variables de tipo char y se cargan dos por asignación y la tercera por teclado. Luego se imprimen los valores de las mismas. A una variable char se le puede asignar directamente un entero comprendido entre -128 y 127: char letra1=65; Luego si se imprime indicando en la función printf que se trata de un caracter %c lo que se obtiene es el valor para dicho carácter ASCII, es decir la letra A: printf("%c",letra1); También es muy común asignar el valor del carácter ASCII, así el programa queda más fácil de leer: char letra2='A'; Como se puede ver cuando se asigna el valor del carácter ASCII se debe encerrarlo entre comillas simples. En el ejemplo 8.1 se ha guardado en las variables letra1 y letra2 el mismo valor (utilizando dos formas distintas): char letra1=65; char letra2='A'; - 153 - Para la carga de un valor de tipo char por teclado se emplea la función scanf y en el primer parámetro indicamos en la cadena de formato que se trata de un carácter el dato a ingresar " %c" y será fundamental agregar un espacio en blanco previo al carácter %: scanf(" %c",&letra3); No olvidar el carácter & previo a indicar el nombre de la variable a cargar (con esa sintaxis se indica que se le pasa la dirección de memoria donde se almacena la variable), el no disponer el & generará un error en tiempo de ejecución del programa. Otro ejemplo sería el 8.2, en el cual se permite la carga de valores enteros por teclado. Luego de ingresar el valor se muestra un mensaje por pantalla que pida confirmar al usuario si desea cargar otro valor ingresando los caracteres 's' o 'n'. Mostrando al final la suma de los valores ingresados. En el programa se define un acumulador llamado suma que se inicializa cuando se define: int suma=0; Por otro lado, se define una variable llamada "continua" que almacenará la respuesta del operado indicando si desea cargar otro valor: char continua; Conviene utilizar un do/while ya que por lo menos un valor se ingresará por teclado: - 154 - do { printf("Ingrese un valor entero:"); scanf("%i",&valor); suma=suma+valor; No olvidar disponer un espacio en blanco previo a %c dentro de la cadena de control de la función scanf (el espacio en blanco libera el valor que queda en el buffer del teclado luego de ingresar el entero): printf("Desea cargar otro valor [s/n]:"); scanf(" %c",&continua); El operador puede cargar en la variable continua cualquier carácter, pero el ciclo repetitivo se verifica verdadero solo si ingresa la letra 's' minúscula (debe quedar claro que la tabla de caractes ASCII define valores distintos para las mayúsculas y para las minúsculas): } while(continua=='s'); Cuando se sale de la estructura repetitiva mostramos el acumulador suma: printf("La suma de todos los valores ingresados es:"); printf("%i",suma); Otro ejemplo sería el 8.3, en el cual se pretende mostrar el abecedario de la 'A' a la 'Z' primero en mayúsculas y luego en minúsculas. Se utiliza una variable de tipo char dentro de un for. - 155 - Se debe tener en cuenta que una variable char es idéntica a una variable int con la salvedad que puede tomar valores comprendidos entre -128 y 127. Entonces, sin ningún problema se puede utilizar una variable char en un for e incrementarla con el operador ++ (incrementa en 1 una variable int o char). Para mostrar el abecedario en mayúsculas se inicia con la variable letra con el primer carácter del abecedario 'A' y cada vuelta del for la incrementamos en 1 a la variable: char letra; for(letra='A';letra<='Z';letra++) { printf("%c",letra); printf("-"); } Por legibilidad se inicia la variable letra con el valor 'A', un resultado idéntico tendríamos si se inicializa a la variable letra con el valor entero 65: for(letra=65;letra<='Z';letra++) { printf("%c",letra); printf("-"); } 8.1.2 String o cadena de caracteres En C no existe un tipo predefinido para manipular cadenas de caracteres (string). Sin embargo, el estándar de C define algunas funciones de biblioteca para tratamiento de cadenas. Una cadena en C es un arreglo de caracteres de una dimensión (vector de caracteres) que termina con el carácter especial ‘\0’ (cero). El formato para declarar una cadena es: char nombre[n]; donde: n >= 1 y representa a la longitud-1 real de la cadena. Un ejemplo de declaración de cadena: char cadena [5]; Debido a que en la representación interna de una cadena de caracteres es terminada por el símbolo '\0', para un texto de "n" caracteres, debemos reservar "n+1”. El carácter '\0', aunque pertenece a la cadena, no aparece al utilizar funciones como printf. En el caso especial de los arreglos de caracteres, se pueden utilizar varias formas de inicialización: - 156 - char cadena[] = "Hola"; char cadena[] = {'H','o','l','a',0}; char cadena[] = {'H','o','l','a','\0'}; sin especificar el tamaño de la cadena, o especificando el tamaño: char cadena[5] = "Hola"; char cadena[5] = {'H','o','l','a',0}; char cadena[5] = {'H','o','l','a','\0'}; Durante la inicialización, se reserva automáticamente el número de bytes necesarios para la cadena, esto es, el número de caracteres más uno. Por ejemplo: char txt[] == "Hola"; txt: 'H' 'o' 'l' 'a' '\0' Para acceder a un elemento de una cadena de caracteres puede hacerse de la misma manera que el acceso al elemento de un arreglo. cadena[i]; donde: 0 <=i < n Por ejemplo: char A[5] = "Hola"; txt: 'H' 'o' 'l' 'a' '\0' A[0] A[1] A[2] A[3] A[4] Las cadenas se muestran con printf y la adecuada marca de formato sin que se presenten dificultades especiales. Lo que sí resulta problemático es leer cadenas. La función scanf presenta una seria limitación: solo puede leer “palabras”, no “frases”. Ello nos obliga a presentar una nueva función (gets). 8.2 Operaciones con caracteres y strings 8.2.1 Operaciones con caracteres Con caracteres, además de leerlos e imprimirlos, se puede realizar las siguientes operaciones: Sumar un entero de un carácter Restar un entero de un carácter Sumar un carácter de otro Restar un carácter de otro Comparar dos caracteres entre si CUIDADO: Al sumar o restar el resultado no debe salirse del rango de representación ASCII. - 157 - El ejemplo 8.4 se muestran todas las operaciones mencionadas con caracteres. - 158 - 8.2.2 Operaciones con cadenas de caracteres Entrada/salida de cadenas. Las cadenas se muestran con printf y la adecuada marca de formato sin que se presenten dificultades especiales. Lo que sí resulta problemático es leer cadenas. La función scanfpresenta una seria limitación: solo puede leer “palabras”, no “frases”. Ello obliga a presentar una nueva función (gets). Salida con printf: Empecemos por considerar la función printf, que muestra cadenas con la marca de formato %s. El ejemplo 8.5 que muestra su uso. Se puede alterar la presentación de la cadena con modificadores, como se muestra en el ejemplo 8.6. Si se desea mostrar una cadena carácter a carácter, se Puede hacer llamando a printf sobre cada uno de los caracteres, pero debe recordar que la marca de formato asociada a un carácter es %c, tal como se observa en el ejemplo 8.7. - 159 - Entrada con scanf: La función scanf es un reto mayor. En el ejemplo 8.8 se pretende leer e imprimir una cadena en la que se pueden almacenar hasta 80 caracteres (sin contar el terminador nulo). Debe notar que con las cadenas no hay que poner el caracter & del identificador al usar scanf. Recordar: cadena[0] es un char, pero cadena, sin más, es la dirección de memoria en la que empieza el vector de caracteres. Al ejecutar el programa introduciendo la cadena "una" se obtiene el resultado por pantalla mostrado en la figura 8.1. Figura 8.1 Salida al introducir la cadena “una”. - 160 - Hay un problema práctico con scanf: solo lee una palabra, es decir, una secuencia de caracteres no blancos. Si al ejecutar el programa se teclean un par de palabras, por ejemplo: “una prueba”, sólo se muestra la primera palabra. Por pantalla se obtendría un resultado similar al mostrado en la figura 8.2: Figura 8.2 Salida al introducir la cadena “una prueba”. Entrada con gets: La función gets lee todos los caracteres que hay hasta encontrar un salto de línea. Dichos caracteres, excepto el salto de línea, se almacenan a partir de la dirección de memoria que se indique como argumento y se añade un terminador. En el ejemplo 8.9 se muestra esta situación. En la figura 8.3 se muestra el resultado de si se introduce la cadena “uno dos” y posteriormente la cadena “tres cuatro”. Figura 8.3 Salida al introducir dos cadenas utilizando gets(). Entrada con sscanf: La función sscanf es similar a scanf (se diferencia en la “s” inicial), pero no obtiene información leyéndola del teclado, sino que la extrae de una cadena. En el ejemplo 8.10 se pretende entender el procedimiento. - 161 - En el programa se ha definido una variable auxiliar, linea, que es una cadena con capacidad para 80 caracteres más el terminador (puede resultar conveniente reservar más memoria para ella en según la aplicación). Cada vez que se desee leer un valor escalar, se lee en línea un texto que introduce el usuario y se obtiene el valor escalar (numérico) con la función sscanf. Dicha función recibe, como primer argumento, la cadena en línea; como segundo, una cadena con marcas de formato; y como tercer parámetro, la dirección de la variable escalar en la que se quiere depositar el resultado de la lectura. Si se ejecuta el programa, un resultado posible es el mostrado en la figura 8.4. Figura 8.4 Salida al utilizar sscanf(). Escritura de cadenas con sprintf: Hay una función que puede simplificar notablemente la creación de cadenas cuyo contenido se debe calcular a partir de uno o más valores: sprintf, disponible incluyendo la cabecera stdio.h (se trata, en cierto modo, de la operación complementaria de sscanf ). La función sprintf se comporta como printf, - 162 - salvo por un “detalle”: no escribe texto en pantalla, sino que lo almacena en una cadena. El ejemplo 8.11 muestra su uso. Si se ejecuta el programa se mostrará por pantalla lo mostrado en la figura 8.5 Figura 8.5 Salida al utilizar sprintf(). Asignación y copia de cadenas: Para efectuar una copia de una cadena, se hacer carácter a carácter, o en su defecto usar la función strcpy correspondiente incluidas en <string.h>. En el ejemplo 8.12 se muestra la copia de una cadena carácter por carácter. - 163 - Se debe notar que el ciclo recorre los 10 caracteres que realmente hay en original, pero, de hecho, solo se requieren copiar los caracteres que hay hasta el terminador, incluyéndole a él. Eso se muestra en el ejemplo 8.13. Longitud de una cadena: El convenio de terminar una cadena con el carácter nulo permite conocer fácilmente la longitud de una cadena. En el ejemplo 8.14 se muestra cómo hacerlo. - 164 - Calcular la longitud de una cadena es una operación frecuentemente utilizada, así que está predefinida en la biblioteca de tratamiento de cadenas <string.h> (strlen). En el ejemplo 8.15 se hace un conteo de caracteres usando strlen (conteo de vocales minúsculas) leída la cadena desde teclado, Esta función también será mencionada en el siguiente tema. Concatenación: En C existe la posibilidad de concatenar cadenas con ciclos. En el ejemplo 8.16 se piden dos cadenas y se concatena la segunda a la primera: - 165 - Si se escribe, por ejemplo, "Juan" y “Perez”, el resultado se muestra en la figura 8.6. Figura 8.6 Concatenado cadenas de caracteres. 8.3 Funciones estándares de caracteres y cadenas de caracteres La biblioteca estándar de C tiene un rico y variado conjunto de funciones de manejo de caracteres y cadenas de caracteres. En una implementación estándar, las funciones de cadena requieren el archivo de cabecera string.h, que proporciona sus prototipos. Las funciones de caracteres utilizan ctype.h, como archivo de cabecera. Como C no comprueba los límites durante las operaciones sobre cadenas de caracteres, el programador es el responsable de prevenir los posibles desbordamientos de las mismas. De acuerdo con el estándar ANSI C, si se desborda una cadena de caracteres, "su comportamiento quedará indefinido", lo que en otras palabras significa que el programa seguramente fallará. En C, un carácter imprimible es cualquiera que pueda mostrarse en una pantalla. Normalmente son los caracteres que se encuentran entre el espacio (0x20) y la tilde (0x7E). Los caracteres de control tienen valores entre 0 y 0x1F, además de del (0x7F). Las funciones de caracteres tienen declarados sus parámetros como enteros. Sin embargo, sólo se utiliza el byte menos significativo; la función de caracteres convierte automáticamente su argumento a unsigned char. De cualquier forma, se pueden utilizar argumentos de tipo carácter al llamarlas, ya que los caracteres se transforman automáticamente en enteros en el momento de la llamada. A continuación, una breve descripción de las funciones más comunes, en las que el archivo de cabecera necesario es <ctype.h>: isalpha: Esta función devuelve un entero distinto de cero si la variable es una letra del alfabeto, en caso contrario devuelve un cero. int isalpha(*char); - 166 - isalnum: Esta función devuelve cierto (un entero cualquiera distinto de cero) si carácter es una letra o dígito, y falso (el valor entero 0) en caso contrario. int isalnum(*char); isblank: Esta función devuelve cierto si carácter es un espacio en blanco o un tabulador. int isblank(*char); isdigit: Esta función devuelve un entero distinto de cero si la variable es un número (entre 0 y 9), en caso contrario devuelve un cero. int isdigit(*char); isgraph: Esta función devuelve un entero distinto de cero si la variable es cualquier carácter imprimible distinto del espacio, pero si es un espacio devuelve cero. int isgraph(*char); islower: Esta función devuelve un entero distinto de cero si la variable esta en minúscula, en caso contrario devuelve un cero. int islower(*char); ispunct: Esta función devuelve un entero distinto de cero si la variable es un carácter de puntuación, en caso contrario, devuelve un cero. int ispunct(*char); isspace: Esta función devuelve cierto si carácter es un espacio en blanco, un saltode línea, un retorno de carro, un tabulador, etc., y falso en caso contrario. int isspace(*char); isupper: Esta función devuelve un entero distinto de cero si la variable esta en mayúsculas, en caso contrario, devuelve un cero. int isupper(*char); - 167 - tolower: Esta función devuelve el carácter equivalente al de la variable en minúsculas, si la variable es una letra; en caso contrario devuelve el carácter sin modificar. *char=tolower(*char); toupper: Esta función devuelve el carácter equivalente al de la variable en mayúsculas, si la variable es una letra; en caso contrario devuelve el carácter sin modificar. *char=toupper(*char); En el ejemplo 8.17 se cuenta el número de letras y números que hay en una cadena. El ejemplo 8.18 utiliza el resto de las funciones y muestra una información completa del valor que contiene la variable tipo carácter. - 168 - A continuación, una breve descripción de las funciones más comunes, en las que el archivo de cabecera necesario es <string.h>: memset: Esta función Inicializa una región de memoria (buffer) con un valor determinado. Se utiliza principalmente para inicializar cadenas con un valor determinado. memset (var_cadena,’carácter’,tamaño); strcat: Esta función concatena cadenas, es decir, añade la segunda cadena a la primera, sin que la primera cadena pierda su valor original. Lo único que se debe tener en cuenta es que la longitud de la primera cadena debe tener la longitud suficiente para guardar la suma de las dos cadenas. strcat(cadena1, cadena2); strchr: Esta función devuelve un apuntador a la primera ocurrencia, del carácter especificado, en la cadena donde se busca. Si no lo encuentra, devuelve un apuntador nulo. - 169 - strchr(cadena,’carácter’); strchr(“texto”,’carácter’); strcmp: Esta función compara alfabéticamente dos cadenas y devuelve un entero basado en el resultado de la comparación. La comparación no se basa en la longitud de las cadenas. Esta función es muy utilizada para comprobar contraseñas. strcmp(cadena1,cadena2); strcmp(cadena2,”texto”); En la tabla 8.2 se muestran los valores resultantes al comparar dos cadenas con la función strcmp. Tabla 8.2 Resultado de comparación strcmp Valor Descripción Menor a Cero Cadena 1 menor que Cadena 2 Cero Cadena 1 igual a Cadena 2 Mayor a Cero Cadena 1 mayor que Cadena 2 strcpy: Esta función copia el contenido de una cadena de caracteres, específicamente el de la segunda cadena de caracteres en la primera. El contenido de la primera cadena se pierde, y la segunda cadena debe estar apuntando a NULL. Lo único que se debe contemplar es que el tamaño de la segunda cadena sea menor o igual a la cadena donde la copiamos. strcpy(cadena1,cadena2); strcpy(cadena1,”texto”); strlen: Esta función devuelve la longitud de una cadena terminada en nulo. El carácter nulo no se contabiliza. La función devuelve un valor entero que indica la longitud de la cadena. variable=strlen(cadena); strncat: Esta función concatena el número de caracteres, definido en la misma, de la segunda cadena en la primera, y coloca un carácter nulo al final de la primera cadena. La primera cadena no pierde información pues se posicionan desde su último carácter (el carácter nulo). Esto no modifica la segunda cadena. Se debe controlar que la longitud de la primera cadena sea lo suficientemente larga para almacenar las dos cadenas, pues en caso de solaparse, strncat() queda indefinido y el programa falla. - 170 - strncat(cadena1,cadena2,nº de caracteres); strncmp: Esta función compara alfabéticamente un número de caracteres entre dos cadenas y devuelve un entero basado según el resultado de la comparación. Ambas cadenas deben estar finalizadas por un carácter nulo. Los valores devueltos son los mismos que en la función strcmp. strncmp(cadena1,cadena2,nº de caracteres); strncmp(cadena1,”texto”,nº de caracteres); strncpy: Esta función copia el número de caracteres definidos de la segunda cadena a la primera. La cadena 2 debe estar finalizada por un carácter nulo. En la primera cadena se pierden aquellos caracteres que se copian de la segunda. En caso de que la cadena 2 tenga menos caracteres que la segunda, se añaden caracteres nulos al final de cadena 1 hasta que se hayan copiado n caracteres. Alternativamente, si la cadena 2 tiene más de n caracteres, la cadena 1 no tendrá carácter nulo de terminación. strncpy(cadena1,cadena2,nº de caracteres); strncpy(cadena1,”texto”,nº de caracteres); strrchr: Dicha función devuelve un apuntador a la última ocurrencia del carácter buscado en la cadena. Si no lo encuentra devuelve un apuntador nulo. strrchr(cadena,’carácter’); strrchr(“texto”,’carácter’); strpbrk: Esta función devuelve un apuntador al primer carácter de la cadena que coincida con algún carácter de la cadena a buscar. Si no hay correspondencia devuelve un apuntador nulo. strpbrk(“texto”,”cadena_de_busqueda”); En el ejemplo 8.19 se copia, concatena, mide e inicializa cadenas. - 171 - En el ejemplo 8.20 se pide una contraseña de entrada. Luego pide 10 códigos de 6 dígitos. Por último, pide los 3 primeros dígitos de los códigos que se desean ver. - 172 - En el ejemplo 8.21 se busca en una cadena a partir de un grupo de caracteres. Si no encuentra coincidencia con ninguna letra en la cadena muestra un mensaje de error.
Compartir