En esta ocasión hablaremos acerca de las cadenas de caracteres en C (también llamadas strings) que son vectores de tipo char y que tendrán muchas particularidades respecto de los array que vamos viendo.
Una de las primeras particularidades que veremos es que toda cadena termina en el caracter nulo '\0' que en código ASCII vale 0, o también puede terminar en el entero 0 (sin comillas). Este caracter nos permitirá conocer el final de una cadena y modificarla sin problemas mientras respetemos la capacidad de la misma.
Declarando una cadena de caracteres:
Declarar una cadena no representa nada nuevo respecto a lo que ya vimos en entradas anteriores, ya que lo haremos como declararíamos un vector de tipo char.
La capacidad de la cadena es la cantidad de caracteres que podrá almacenar nuestra cadena. Si queremos guardar una determinada palabra o frase hay que darle una capacidad adecuada para ello y recordar que el caracter nulo ocupa el espacio de un elemento en ella.
Es importante recordar ese detalle y que la longitud de la cadena que guardemos no supere la capacidad de la misma ya que si no podríamos tener errores de todos los colores del arcoiris incluso sin que el compilador se de cuenta de ello.
Inicializando una cadena de caracteres:
Inicializaremos una cadena de caracteres de la siguiente manera:
En este ejemplo, no utilizamos la capacidad máxima de nuestra cadena ya que la palabra que almacenamos tiene una longitud menor. Si recordamos cómo se almacenaban en memoria los elementos de un vector y hacemos lo mismo para esta cadena de ejemplo tendríamos algo así:
Otra forma de inicializar nuestra cadena, sería hacerlo como vimos para vectores, siempre recordando colocar el caracter nulo al final y colocar cada caracter entre comillas simples:
Una de las primeras particularidades que veremos es que toda cadena termina en el caracter nulo '\0' que en código ASCII vale 0, o también puede terminar en el entero 0 (sin comillas). Este caracter nos permitirá conocer el final de una cadena y modificarla sin problemas mientras respetemos la capacidad de la misma.
Declarando una cadena de caracteres:
Declarar una cadena no representa nada nuevo respecto a lo que ya vimos en entradas anteriores, ya que lo haremos como declararíamos un vector de tipo char.
Es importante recordar ese detalle y que la longitud de la cadena que guardemos no supere la capacidad de la misma ya que si no podríamos tener errores de todos los colores del arcoiris incluso sin que el compilador se de cuenta de ello.
Inicializando una cadena de caracteres:
Inicializaremos una cadena de caracteres de la siguiente manera:
En este ejemplo, no utilizamos la capacidad máxima de nuestra cadena ya que la palabra que almacenamos tiene una longitud menor. Si recordamos cómo se almacenaban en memoria los elementos de un vector y hacemos lo mismo para esta cadena de ejemplo tendríamos algo así:
O incluso si seguimos la lógica que nos indica que es un vector de caracteres podríamos inicializar cada elemento de nuestra cadena de acuerdo a su índice:
Aunque obviamente esto no es lo que recomendamos para inicializar una cadena es posible hacerlo así y hasta lo usaremos en algunas ocasiones en que necesitemos extraer un caracter específico de la misma.
SALIDA:
Usando printf con cadenas de caracteres:
Para mostrar por pantalla una cadena de caracteres usando printf, tendremos en cuenta dos nuevos detalles:
- La marca de formato de una cadena de caracteres será %s.
- Al indicar la cadena que mostraremos lo haremos con el nombre de la misma sin índice.
Con lo que usar printf para mostrar nuestra cadena de ejemplo será tan sencillo como poner :
Recordemos que nuestra cadena es un vector de tipo char, por lo que si queremos mostrar sólo un caracter en particular de la misma usaremos el índice y la marca de formato correspondiente (%c). Por lo que si quisiéramos mostrar sólo la j de la palabra ejemplo tendríamos:
ENTRADA:
Usando scanf para leer cadenas de caracteres:
Para leer cadenas de caracteres, scanf muestra su punto débil ya que sólo nos permite leer palabras y no oraciones completas, por lo que si ingresamos una frase sólo leerá hasta el primer espacio (blanco) de la misma.
Aún así mostraremos cómo leer una palabra a través de scanf en el siguiente ejemplo:
Y vemos que es igual de simple que con printf, sólo que notemos que colocamos sólo el nombre de la cadena sin el & ya que en una cadena el nombre guarda la dirección de memoria del primer elemento.
En caso que quisiéramos leer toda una cadena de caracteres con scanf deberíamos agregar varios scanf para ir leyendo cada palabra... en fin, nada óptimo ni mucho menos.
Usando gets para leer cadenas de caracteres:
Como vimos scanf muestra su debilidad ante las cadenas de caracteres, por lo que se necesita una función que pueda leer una cadena completa sin importar si es una palabra o toda una frase, otra función que puede utilizarse en este caso es gets que sí permite leer frases.
Si usar printf y scanf con cadenas de caracteres les pareció fácil, entonces usar gets les parecerá un juego de niños:
Se los dije... tan simple como escribir gets y pasar como argumento el nombre de la cadena.
Pero no todo lo que brilla es oro y ésta no es la excepción. Gets también tiene sus problemas ya que no verifica que la cadena que ingresamos no sobrepase la capacidad de nuestra cadena, por lo que es una función que fácilmente puede provocar un buffer overflow (desbordamiento).
Usando getchar para leer cadenas de caracteres:
Para leer un solo caracter podemos utilizar getchar que es una función que debe asignarse a una variable de tipo char de la manera que vemos a continuación:
Por lo que si hacemos memoria y pensamos que en un array cada elemento con su índice se comporta como una variable, se nos podría venir a la mente la idea de realizar un bucle para leer una cadena completa usando getchar.
Pero veamos ¿cómo podríamos implementarlo sin tener mil y un problemas? Porque si nos ponemos a pensar en todo lo que podría pasar sin condicionar esto tendríamos tema de sobra para hacer una película de terror para frikis.
A ver, pensemos todo lo que debemos tener en cuenta: la cadena no debe superar su capacidad incluyendo el caracter nulo y si presionamos enter se termina la cadena.
Así que si creamos una variable char auxiliar y agregamos todas las condiciones necesarias podríamos conseguir lo deseado en este while:
Pero esto de tener que usar un while con tantas condiciones, cuántos i++, agregar el caracter nulo y cuánto más ya no es tan sencillo como vimos con otras funciones y encima cuando veamos complejidad de algoritmos veremos que con la manera anterior se nos va a las nubes comparado con usar scanf o gets.
Usando fgets para leer cadenas de caracteres:
Hasta ahora por uno u otro motivo ninguna función nos ayuda a leer una cadena de caracteres sin problemas y de manera sencilla, pero antes de darnos por vencidos volvamos a la esencia de lo que queremos hacer y analicemos.
Queremos ingresar una frase a través del teclado... pero el teclado en sí para C es lo que llamamos un fichero, explicando muy superficialmente y para que se entienda el fichero de entrada estándar stdin es lo que representa lo que llamamos teclado. Y es uno de los ficheros que se encuentran abiertos cuando ejecutamos nuestro programa. Éste se encuentra declarado dentro de stdio.h, cuando veamos más adelante el uso de ficheros veremos la sintaxis de esta declaración pero por ahora lo importante es que quede claro esto de que el teclado es un fichero.
Entonces si el teclado es un fichero podemos hacer uso de una función llamada fgets que nos permitirá leer cadenas de caracteres especificando el máximo tamaño que podrá tener y de esta manera evitar los problemas de desbordamiento que tanto nos vienen molestando en las otras funciones.
El uso de fgets vuelve a ser tan sencillo como las primeras opciones que vimos:
Vemos que fgets recibe como argumentos el nombre de la cadena, la capacidad de la misma y el fichero en cuestión. Por lo que esta función nunca leerá más caracteres de los que nos permite la capacidad de la cadena, incluyendo el caracter nulo (lee hasta llegar a ese límite o hasta que el usuario presione enter); lo que nos quita un problema de encima.
Por el momento no analizaremos más de esta función ya que eso queda para cuando veamos ficheros, pero con esto ya podemos leer cadenas de caracteres con más tranquilidad.
Ya que este post se extendió bastante llegaremos hasta aquí por ahora y en el próximo trataremos exclusivamente algunas de las funciones que utilizaremos para trabajar con estas cadenas de caracteres.
Comentarios
Publicar un comentario