30 de agosto de 2016

Arreglos de caracteres (cadenas).

   Todo lo que hasta este momento se ha comentado para los arreglos respecto a su declaración, inicialización, recorrido, y uso con funciones, es aplicable a arreglos de cualquiera de los tipos de datos de C incluyendo char; sin embargo, este tipo de arreglos poseen características particulares, empezando porque es común denominar a un arreglo de caracteres (char) como cadena, de ahí que su tratamiento y discusión se hayan separado en una entrada especial.

   Si se han revisado las entradas anteriores, en este momento el lector cuenta con algo de experiencia en la declaración, inicialización, recorrido, y uso de arreglos con funciones, por lo que en el Ejemplo 6.6 se presentan estos conceptos en el contexto de cadenas, es decir: arreglos de caracteres.

   Las líneas 12, 13 y 14 muestran la declaración de tres cadenas: cadena1, cadena2 y cadena3. Note que las dos primeras no tienen un tamaño explícito y que han sido inicializadas de forma distinta.

   La cadena1 se ha inicializado con una frase contenida entre comillas dobles. En el lenguaje de programación C, cualquier sucesión de elementos contenida entre comillas dobles es una cadena, y dicha cadena está compuesta por todos los caracteres entre comillas (incluyendo los espacios en blanco), más un carácter no visible, pero que delimita el fin de la cadena. Este carácter recibe el nombre de fin de cadena y es '\0', que aunque es un carácter compuesto por dos símbolos (\ y 0), se considera como uno solo y se denota entre comillas simples: '\0'. Por lo tanto la cadena1 tiene un tamaño implícito o longitud no de 18 caracteres como podría pensarse en un principio, sino de 19.

   Por otro lado, la cadena2 (línea 13) tiene una inicialización más parecida a lo que se vio en su momento para arreglos de tipo int y float. Note que cada unos de los elementos de la cadena, incluyendo el fin de cadena, se encuentran entre comillas simples. Para este tipo de inicialización el terminador de cadena '\0' debe proporcionarse de manera explícita, ya que de otra forma, la cadena estaría mal formada, es decir, sin terminar, y esto podría llevar a efectos o resultados desde inesperados (impresión de caracteres extraños más allá de lo que en principio conforma la cadena) hasta catastróficos (intentos de acceso a memoria no reservada y la consecuente anulación del programa). Esta cadena tiene una longitud implícita de seis caracteres.

   La cadena3 no ha sido inicializada y se utilizará para leer una cadena desde la entrada estándar a través de la función gets (la cual recibe una cadena almacena en ella lo que se procesa de la entrada estándar, hasta que se introduzca un ENTER, (\n) (línea 18).

   El ciclo for de la línea 21 muestra el recorrido clásico de una cadena. Observe que la expresión condicional depende del carácter de fin de cadena ('\0'), y que el cuerpo del ciclo (línea 22) imprime la cadena cadena1 carácter por carácter con un espacio entre ellos.

   La línea 23 muestra el uso de la función putchar para imprimir el carácter de avance de línea y un retorno de carro. Dicha función es equivalente a la sentencia:

printf("\n");

   Note que la secuencia de escape '\n' ha sido escrita entre comillas simples en la línea 23 debido a que la función putchar escribe en la salida estándar el carácter que recibe como argumento.

   El Ejemplo 6.6 también dos funciones que se describen a continuación:
  • longitud (línea 38): recibe una cadena, la cual se identifica como c dentro de la función, y realiza un recorrido sobre c para llegar al final de la misma, de tal forma que la variable de control i contiene la longitud de c cuando la expresión condicional del for se evalúa como 0; el cuerpo del ciclo está vacío porque no hay nada más que hacer y esto se enfatiza con el ";" de la línea 42. Finalmente la función regresa la longitud de la cadena: i (línea 43).
  • imprimeAlReves (línea 30):  recibe una cadena, la cual se identifica como c dentro de la función y realiza un recorrido inverso sobre c, es decir, del último carácter de la cadena (longitud - 1) al primero (0). Dentro del recorrido, la cadena se imprime en la salida estándar carácter por carácter.
   Note que la cadena original (como argumento la cadena original es cadena2 (línea 25), como parámetro es c (línea 30)) no se invierte, sino que únicamente se imprime al revés, por lo tanto la cadena original permanece inalterada; asegúrese de comprender esto antes de continuar.

   Una posible salida del Ejemplo 6.6 se  muestra en la siguiente figura:

Una posible salida del Ejemplo 6.6.
 
    En la entrada correspondiente a los apuntadores se retomará el tema de cadenas.