miércoles, 30 de mayo de 2012

Las Funciones Getchar y Putchar

La función getchar recibe un carácter, mientras que la función putchar imprime un carácter. Este par de funciones son más útiles de lo que parece. Permiten manipular de distintas maneras archivos y caracteres. El siguiente programa es un clásico. Recibe carácter por carácter la entrada del usuario (puede ser un número, una cadena, un archivo) con la función getchar y lo imprime con la función putchar.


/*+++++++++++++++++++++++++++++++++++++++++
  * ESTE PROGRAMA LEE E IMPRIME UNA CADENA + 
  * CARACTER POR CARACTER                  +
  * +++++++++++++++++++++++++++++++++++++++*/

 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  *                                                       +
  *                   ALGORITMO                           +
  * Solicitar una cadena                                  +
  *                                                       +
  + Recibe un caracter                                    +
  * Mientras (el caracter recibido no sea fin de archivo) +
  * { // Abre mientras                                    +
  * Imprime el siguiente caracter                         +
  * Incrementa en uno el numero de caracteres             +
  * Recibe el siguiente caracter                          +
  * }  // Cierra mientras                                 +
  *                                                       +
  *++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

  #include <stdio.h>
  
  int main()
  {  /* Abre main */
  int c;

  printf("\nEste programa recibe e imprime una cadena de caracteres ");
  printf("caracter por caracter.\nPor favor introduzca la cadena: \n");

  while(EOF != (c = getchar()))
  putchar(c);
  
  return 0;
  } /* Cierra main */

_____________________________________________________________________________________________
Ahora hagamos un análisis del programa línea por línea para revisar cada instrucción

/*+++++++++++++++++++++++++++++++++++++++++
  * ESTE PROGRAMA LEE E IMPRIME UNA CADENA + 
  * CARACTER POR CARACTER                  +
  * +++++++++++++++++++++++++++++++++++++++*/

 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  *                                                       +
  *                   ALGORITMO                           +
  * Solicitar una cadena                                  +
  *                                                       +
  + Recibe un caracter                                    +
  * Mientras (el caracter recibido no sea fin de archivo) +
  * { // Abre mientras                                    +
  * Imprime el siguiente caracter                         +
  * Incrementa en uno el numero de caracteres             +
  * Recibe el siguiente caracter                          +
  * }  // Cierra mientras                                 +
  *                                                       +
  *++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

Este par de comentarios indican de qué va el programa.

#include <stdio.h>

Un encabezado que indica que se usará entrada y salida estándar. Además de eso, en este programa se hace uso de otro contenido de este encabezado: la definición del valor del carácter que indica el fin de archivo EOF (End of File)

int main()

Recuerde que en C la unidad básica de programación es la función. El nombre main es también un buen nombre para esta función. main se llamaba la función principal en el lenguaje de programación B, del cual evolucionó el lenguaje C.

{  /* Abre main */

Los corchetes se utilizan en cualquier parte donde pueda ponerse una instrucción simple (salvo en el operador ternario). En el caso de la función main (en realidad en cualquier definición de función) las llaves son obligatorias. NO es correcto escribir un programa como éste:

int main()

return 0;

Un programa con una función main vacía debe escribirse así

main()
{

}

Éste es el programa más corto que puede escribirse en el lenguaje C. Sólo consta de 8 caracteres. Sobra decirlo: el programa no hace nada, pero sintácticamente está bien. Es prescindible el encabezado stdio.h, la instrucción return y el tipo int. No son prescindibles el nombre main, los paréntesis después del nombre, ni las llaves. Todos los cuerpos de las funciones deben estar contenidos en llaves.

int c;

Esta declaración de variable reserva espacio para un tipo entero. La variable, c, será utilizada para almacenar temporalmente cada uno de los caracteres. El tipo de datos char es el tipo adecuado para almacenar caracteres. ¿Por qué se utiliza entonces el tipo int? Porque c también debe guardar el valor de EOF, el fin de archivo, el cual generalmente es -1 (véase este programa). Dado que los tipos char son enteros sin signo, al declarar a la variable c como tipo char, no se podría distinguir el fin de archivo.

printf("\nEste programa recibe e imprime una cadena de caracteres ");
printf("caracter por caracter.\nPor favor introduzca la cadena: \n");

Este par de líneas printf son un mensaje para el usuario.

while(EOF != (c = getchar()))

Esta es una forma muy compacta de escribir código. Dentro de la condición de while ocurren varias cosas, y ellas tienen que ver con el orden de precedencia de los operadores. Lo que está dentro de los paréntesis externos, sea lo que sea; se evalúa como una expresión booleana. Si no es una expresión booleana, entonces se convierte explícitamente a una, esto quiere decir que si el valor de dicha expresión es 0, entonces se toma como "falso" y no se realiza el cuerpo de if y por otra parte, el compilador tomará como "verdadero" todo valor distinto de 0, y en ese caso se ejecuta el cuerpo de la instrucción while. Lo primero que "ve" el compilador dentro de los paréntesis externos es una condición:
EOF != (expresion) ¿Qué es EOF? EOF es el caracter que indica el fin del archivo. En los sistemas Unix el fin de archivo es Ctrl D, en tanto que en los sistemas windows es Ctrl C. Si usa un sistema distinto, deberá averiguar cuál es la combinación de teclas que indican EOF. EOF tiene un valor determinado por la plataforma en la que programe. Este valor tiene que ser tal que no se pueda confundir con cualquier carácter válido (como a, b, c, \t, etc). Generalmente se trata de un número negativo (-1). La condición dentro de los paréntesis de while dice "mientras el carácter leído sea distinto de EOF, realiza este cuerpo de instrucciones". Pero ¿qué hay a la derecha del operador relacional !=? Este operador es un operador "izquierdo", toma el valor de la izquierda y lo compara con el de la derecha. A su derecha, y entre paréntesis aparece la expresión x = getchar() ¿Por qué aparece esta expresión entre paréntesis? Porque la precedencia del operador relacional != es superior a la del operador de asignación =. De no haber paréntesis, el compilador primero compararía el valor de c con EOF y luego trataría de asignar el valor de getchar() a la cantidad que se encuentra a la izquierda de =, lo cual provocará un error en la compilación; en este caso los paréntesis son necesarios. Por lo tanto, después de evaluar el valor de EOF, el compilador evalúa la expresión c = getchar(), y aquí se encuentra una expresión que contiene al operador = de asignación. La asociatividad de = es de derecha a izquierda, primero se evalúa la expresión a la derecha y eso se le asigna a la variable c. Pero la expresión de la derecha es una invocación de la función getchar(), definida en el encabezado stdio.h Esa función lo que hace es recibir un carácter de la entrada. La sintaxis general de la función getchar es la siguiente:

int getchar(void)

La función retorna un entero (el valor del carácter leído) y no recibe ningún parámetro. Este valor entero se asigna a la variable c, que se ha declarado previamente como tipo int. Y es ese valor, el de c, el que se compara con EOF. Si el carácter leído es distinto a EOF, entonces se lee el siguiente y así. Se trata pues de un ciclo while controlado por centinela.

putchar(c);

El cuerpo de while consta de una sola instrucción: la función putchar, la cual recibe un entero y retorna también un entero. Esos int son los valores de un carácter. La forma general de la función putchar es la siguiente:

int putchar(int caracter);

En este programa, putchar(c) simplemente envía a la salida estándar el carácter que getchar() acaba de leer.

return 0;

La instrucción return 0; como en todos los programas, indica que se ha terminado el programa satisfactoriamente.

} /* Cierra main */

Esta llave indica el fin del cuerpo de main. Muchas veces le va a ocurrir que hay cuerpos de instrucciones que contienen llaves sin cerrar. Para evitar esto, créese el buen hábito de cerrar el cuerpo antes de escribir las instrucciones. También acostúmbrese a indicar, en cada caso, a qué instrucción corresponden las llaves.
_______________________________________________________________________________________________
Lo que aprendió:
El significado de EOF
La función getchar()
La función putchar()
_______________________________________________________________________________________________
Esta entrada forma parte del Curso de C con Programas Explicados Línea por Línea
Índice
Entrada Anterior
Entrada Siguiente

3 comentarios:

  1. Como dicen Kernighan y Ritchie en su libro, con getchar y putchar se puede manejar una gran cantidad de código, sin necesidad de usar scanf. En El Lenguaje de Programación C el uso de scanf se retrasa bastante.

    ResponderEliminar
    Respuestas
    1. Gracias por el comentario, Anónimo. Es cierto que se puede manipular bastante código con éstas funciones. Para los ejercicios del capítulo 1 del libro de Kernighan-Ritchie, sólo se usan éstas funciones, además de printf, y algunos de esos programas son bastante interesantes.
      ¡Saludos!.

      Eliminar
  2. Siempre tuve una duda en este ejemplo: Entiendo que cuando escribo un carácter en el teclado, se visualiza inmediatamente, pero por qué cuando presiono enter se repite nuevamente la línea?

    ResponderEliminar

Related Posts Plugin for WordPress, Blogger...