05. Funciones de entrada/salida

Última modificación por editor1 el 2018/09/17 10:32

Objetivos

  1. Entender el concepto de entrada y salida.
  2. Conocer los métodos para leer datos de la entrada.
  3. Conocer los métodos para escribir datos a la salida.

Introducción

Los programas informáticos básicamente son manipuladores de información, ya sea un programa de contabilidad, un sistema de inteligencia artificial o el sistema operativo de un ordenador. Por tanto, los programas necesitan poder obtener esta información para procesarla y poder dar salida a los resultados. Si no tenemos entrada, los programas se limitarían a hacer siempre lo mismo con los mismos datos y, si no tenemos salida, los resultados del programa nunca se podrían usar para nada.

Cuando pensamos en entrada de datos nos referimos a cualquier tipo de entrada; pueden ser las teclas que se pulsan en un teclado, la posición del ratón o pantalla táctil, un fichero en disco, una dirección de internet, un lector de códigos de barras, una webcam o el micrófono. Del mismo modo, cuando hablamos de salida nos podemos referir a un amplio abanico de opciones, desde la pantalla del ordenador, un archivo, una impresora o el sistema de control de un robot.

Entre todos estos dispositivos hay dos que tienen un papel especialmente relevante: el teclado para la entrada de datos y la pantalla para la salida de datos. De hecho, si no se cambia explícitamente, la entrada estándar (o stdin del inglés standard input) es el teclado, y la salida estándar (o stdout del inglés standard output) es la pantalla.

En esta guía veremos cómo podemos comunicarnos con estos dispositivos para leer información desde el teclado y mostrarla en la pantalla.

1. Entrada

Lo primero que hay que saber es que cuando se pulsan teclas en un teclado, estas se convierten en su código ASCII y se almacenan como caracteres en lo que se llama un buffer, el cual contiene toda la secuencia de caracteres que han escrito y que ningún programa ha leído todavía.

bufferTeclat.png

Los métodos para leer datos irán leyendo de este buffer considerando qué tipo de información intentamos leer. Hay que tener en cuenta que el salto de línea también cuenta como una tecla cualquiera y se representa habitualmente con '\n'. Este buffer es una estructura conocida como FIFO (First In First Out), lo que quiere decir que lo leeremos en orden de llegada. A continuación se muestra un ejemplo del contenido del buffer a medida que se van pulsando teclas del teclado:

Tecla pulsadaContenido del buffer
 1 '1'
 3 '3' '1'
 2 '2' '3' '1'
 Salto de línea '\n' '2' '3' '1'
 a 'a' '\n' '2' '3' '1'
 Salto de línea '\n' 'a' '\n' '2' '3' '1'

Para leer la información de este buffer, tenemos a nuestra disposición un conjunto de instrucciones en lenguaje algorítmico según el tipo de datos que queremos leer:

InstrucciónDescripción
 readChar Lee un carácter del buffer
 readBoolean Lee un boolean del buffer
 readInteger Lee un entero del buffer
 readReal Lee un real del buffer
 readString Lee un real del buffer

Veamos cuál sería el resultado de aplicar estas instrucciones teniendo en cuenta que c es una variable de tipo carácter, i una variable de tipo entero y r una de tipo real:

Buffer InicialInstruccionesBuffer finalResultado
 '\n' 'a' '\n' '2' '3' '1' c:= readChar() '\n' 'a' '\n' '2' '3' La variable c contiene el valor 49 (valor ASCII del carácter 1).
 '\n' 'a' '\n' '2' '3' '1' i:= readInteger() '\n' 'a' La variable i contiene el valor 132. Dado que los enteros pueden tener varias cifras, se lee hasta el salto de línea o un espacio.
 '\n' 'a' '\n' '2' '3' '1' r:= readReal() '\n' 'a' La variable r contiene el valor 132,0. Dado que los reales pueden tener varias cifras, se lee hasta el salto de línea o un espacio.
 '\n' 'a' c:= readChar() '\n' La variable c contiene el valor 97 (valor ASCII del carácter a).
 '\n' 'a' i:= readInteger()  Error. No se puede interpretar la letra a como un entero.
 '\n' 'a' r:= readReal()  Error. No se puede interpretar la letra a como un real.

2. Salida

En el caso de la salida pasa algo similar. Cuando escribimos en la salida estándar, toda la información queda guardada en forma de caracteres en un buffer, que se va leyendo y mostrando en la pantalla.

bufferPantalla.png

Para escribir la información en este buffer y se muestre, tenemos a nuestra disposición una serie de instrucciones en lenguaje algorítmico según el tipo de datos que queremos escribir:

InstrucciónDescripción
 writeChar Escribe un carácter en el buffer
 writeBoolean Escribe un boolean en el buffer
 writeInteger Escribe un entero en el buffer
 writeReal Escribe un real en el buffer
 writeReal Escribe una cadena de carácteres en el buffer

3. Entrada y salida en C

Para poder acceder a la entrada y salida estándares en C, necesitaremos utilizar una librería estándar de C. Las librerías son conjuntos de funcionalidades que extienden las instrucciones básicas del lenguaje C, facilitando hacer ciertas tareas. En este caso la librería se llama stdio (standard input/output) y, para poder utilizarla, tendremos que importarla a nuestro programa. Para ello, tendremos que añadir la siguiente línea de código al principio de nuestro archivo (sin punto y coma):

# include <stdio.h>

Una vez importada, podemos utilizar sus funcionalidades directamente. Tanto en el caso de la entrada como en el de la salida, hay que especificar el tipo y formato de los datos. Para ello, se pasa la cadena de formato de entrada y salida, donde las variables que se quieren leer o escribir se indican con el símbolo % y, a continuación, una letra especificando el tipo de variable. A continuación se muestra un resumen de las más habituales:

Tipo de datoEspecificativo de tipoEjemplo de datos 
 Carácter %c 'a'
 Boolean %u 0 (equivalente de true), 1 (equivalente de false); en general, cualquier tipo enumerativo usará el especificativo %u.
 Entero %d 34 o -32
 Real %f 3.1415
 String %s"Hello World"
 Puntero %p0x000000AA; los punteros los trataremos en el módulo "13. Punteros en C".

A continuación veremos ejemplos de estas cadenas de formato para la entrada y la salida.

3.1. Entrada

El método genérico para la entrada de datos es el método scanf, que espera una cadena de formato indicando qué debe leer del buffer de teclado y la lista de variables donde se guardarán los valores leídos. Todas las variables deben ir precedidas del símbolo & (que significa «dirección de» y que veremos en la unidad de memoria). En la siguiente tabla tenemos la traducción de los métodos en lenguaje algorítmico anteriores, teniendo en cuenta que c es una variable de tipo carácter, i de tipo entero y r de tipo real:

MétodoTraducción a C
 readChar scanf("%c", &c)
 readBoolean scanf("%u", &b)
 readInteger scanf("%d", &i)
 readReal scanf("%f", &r)
 readString scanf("%s", s)

Además, en el caso de leer un carácter tenemos la instrucción getchar que nos permite hacer una asignación directa:

c=getchar();

3.2. Salida

En el caso de la salida por pantalla, tenemos el método printf, que espera una cadena de formato indicando qué tiene que escribir y la lista de variables de donde obtener la información. En la siguiente tabla tenemos la traducción de los métodos en lenguaje algorítmico anteriores, teniendo en cuenta que c es una variable de tipo carácter, i de tipo entero y r de tipo real:

MétodoTraducción a C
 writeChar printf("%c", c)
 writeBoolean printf("%u", b)
 writeInteger printf("%d", i)
 writeReal printf("%f", r)
 writeString printf("cadena de carácteres")
 writeString printf("%s", s)

Además, cabe recordar que tenemos un carácter especial para indicar el salto de línea ('\n'), que lo podemos utilizar en el formato para indicar que queremos que se haga un salto de línea. De lo contrario todo se escribirá seguido en la misma línea.

Adicionalmente, podemos añadir modificaciones a cómo queremos que se muestren los datos. Estos modificadores se ponen entre el símbolo % y el especificativo de tipo:

%[modificadores][ancho][.precisión]especificativo

A continuación vemos unos cuantos ejemplos. Podéis encontrar más información, aquí.

FormatoValor variable Salida
"%0d" 3 3
 "%03d" 003 
"%f" 3.14 3.14000
 "%2.1f" 3.14 3.1

4. Ejemplos

4.1. Ejemplo 05_01: entrada

Enunciado:

Definid un algoritmo que lea dos enteros y calcule su suma. Haced su traducción a C.

Solución:

algorithm sum

    var 
        a: integer;
        b: integer;
        s: integer;
    end var

    a:= readInteger();
    b:= readInteger();

    s:= a + b;

end algorithm

# include <stdio.h>

int main() {
   int a;
   int b;
   int s;

    scanf("%d", &a);
    scanf("%d", &b);

    s=a+b;

   return 0;
}

4.2. Ejemplo 05_02: salida

Enunciado:

Definid un algoritmo que, dadas dos variables a = 2 y b = 2, escriba por pantalla el mensaje: "La suma de a y b es 4". Haced su traducción a C.

Solución:

algorithm sumaSalida

    var 
        a: integer;
        b: integer;
    end var

    a:= 2;
    b:= 2;

   writeString("La suma d'a i b és :");
   writeInteger(a + b);

end algorithm

# include <stdio.h>

int main() {
   int a=2;
   int b=2;
  
    printf("La suma d'a i b és : %d", a + b);

   return 0;
}

4.3. Ejemplo 05_03: entrada y salida

Enunciado:

Definid un algoritmo que requiera tres enteros y muestre por pantalla el valor medio de los tres. Haced su traducción a C.

Solución:

algorithm sumaEntradaSalida

    var 
        a: integer;
        b: integer;
        c: integer;
        m: float;
    end var

    a:= readInteger();
    b:= readInteger();
    c:= readInteger();

    m=(a+b+c)/3.0;

   writeReal(m);

end algorithm

# include <stdio.h>

int main() {
   int a;
   int b;
   int c;
   float m;

    scanf("%d", &a);
    scanf("%d", &b);
    scanf("%d", &c);

    m=(a+b+c)/3.0;

    printf("%f", m);

   return 0;
}

Resumen

En esta guía hemos visto la utilización de los métodos scanf y printf para leer y escribir datos en los dispositivos estándar de entrada y salida. También hemos visto que se puede modificar el formato de los datos.

Etiquetas:
Creado por editor1 el 2018/09/17 10:31