Apéndice C: Bibliotecas estándar

Todos los compiladores C y C++ disponen de ciertas bibliotecas de funciones estándar que facilitan el a la pantalla, al teclado, a los discos, la manipulación de cadenas, y muchas otras cosas, de uso corriente.

Hay que decir que todas estas funciones no son imprescindibles, y de hecho no forman parte del C. Pueden estar escritas en C, de hecho en su mayor parte lo están, y muchos compiladores incluyen el código fuente de estas bibliotecas. Nos hacen la vida más fácil, y no tendría sentido pasarlas por alto.

Existen muchas de estas bibliotecas, algunas tienen sus características definidas según diferentes estándar, como ANSI C o C++, otras son específicas del compilador, otras del sistema operativo, también las hay para plataformas Windows. En el presente curso nos limitaremos a las bibliotecas ANSI C y C++.
Veremos ahora algunas de las funciones más útiles de algunas de estas bibliotecas, las más imprescindibles.

Biblioteca de entrada y salida fluidas "iostream"

En el contexto de C++ todo lo referente a "streams" puede visualizarse mejor si usamos un símil como un río o canal de agua.
Imagina un canal por el que circula agua, si echamos al canal objetos que floten, estos se moverán hasta el final de canal, siguiendo el flujo del agua. Esta es la idea que se quiere transmitir cuando se llama "stream" a algo en C++. Por ejemplo, en C++ el canal de salida es cout, los objetos flotantes serán los argumentos que queremos extraer del ordenador o del programa, la salida del canal es la pantalla. Sintaxis:

cout << <variable/constante> [<< <variable/constante>...]; 

Completando el símil, en la orden:

cout << "hola" << " " << endl; 

Los operadores "<<" representarían el agua, y la dirección en que se mueve. Cualquier cosa que soltemos en el agua: "hola", " " o endl, seguirá flotando hasta llegar a la pantalla, y además mantendrán su orden.

En esta biblioteca se definen algunas de las funciones aplicables a los "streams", pero aún no estamos en disposición de acceder a ellas. Baste decir de momento que existen cuatro "streams" predeterminados:

-cin, canal de entrada estándar.
-cout, canal de salida estándar.
-cerr, canal de salida de errores.
-clog, canal de salida de diario o anotaciones.

Sobre el uso de cin, que es el único canal de entrada predefinido, tenemos que aclarar cómo se usa, aunque a lo mejor ya lo has adivinado.

cin >> <variable> [>> <variable>...]; 

Donde cada variable irá tomando el valor introducido mediante el teclado. Los espacios y los retornos de línea actúan como separadores.
Ejemplo:
Escribir un programa que lea el nombre, la edad y el número de teléfono de un y los muestre en pantalla.

#include <iostream>
using namespace std;

int main() {
  char Nombre[30];  // Usaremos una cadena para almacenar 
                    // el nombre (29 caracteres)
  int Edad;         // Un entero para la edad
  char Telefono[8]; // Y otra cadena para el número de 
                    // teléfono (7 dígitos) 
  
  // Mensaje para el
  cout << "Introduce tu nombre, edad y número de teléfono" << endl;
  // Lectura de las variables
  cin >> Nombre >> Edad >> Telefono; 
  // Visualización de los datos leídos
  cout << "Nombre:" << Nombre << endl; 
  cout << "Edad:" << Edad << endl; 
  cout << "Teléfono:" << Telefono << endl;

  return 0; 
}
 

Biblioteca C de entrada y salida estándar "stdio.h"

En esta biblioteca están las funciones de entrada y salida, tanto de la pantalla y teclado como de ficheros. "stdio" puede y suele leerse como estándar Input/Output. De hecho la pantalla y el teclado son considerados como ficheros, aunque de un tipo algo peculiar. La pantalla es un fichero sólo de escritura llamado stdout, o salida estándar y el teclado sólo de lectura llamado stdin, o entrada estándar.
Se trata de una biblioteca ANSI C, por lo que está heredada de C, y ha perdido la mayor parte de su utilidad al ser desplazada por "iostream". Pero aún puede ser muy útil, es usada por muchos programadores, y la encontrarás en la mayor parte de los programas C y C++.
Veamos ahora algunas funciones.

Función getchar()

Sintaxis:

int getchar(void);  

Lee un carácter desde stdin.

getchar es una macro que devuelve el siguiente carácter del canal de entrada stdin. Esta macro está definida como getc(stdin)".
Valor de retorno:
Si todo va bien, getchar devuelve el carácter leído, después de convertirlo a un int sin signo. Si lee un Fin-de-fichero o hay un error, devuelve EOF.
Ejemplo:

do {
   a = getchar(); 
} while (a != 'q'); 

En este ejemplo, el programa permanecerá leyendo el teclado mientras no pulsemos la tecla 'q'.
 
Función putchar()
Sintaxis:

int putchar(int c); 

Envía un carácter a la salida stdout.
putchar(c) es una macro definida como putc(c, stdout).
Valor de retorno:
Si tiene éxito, putchar devuelve el carácter c. Si hay un error, putchar devuelve EOF.
Ejemplo:

while(a = getchar()) putchar(a); 

En este ejemplo, el programa permanecerá leyendo el teclado y escribirá cada tecla que pulsemos, mientras no pulsemos 'C', (CONTROL+C). Observa que la condición en el while no es a == getchar(), sino una asignación. Aquí se aplican, como siempre, las normas en el orden de evaluación en expresiones, primero se llama a la función getchar(), el resultado se asigna a la variable "a", y finalmente se comprueba si el valor de "a" es o no distinto de cero. Si "a" es cero, el bucle termina, si no es así continúa.
 
Función gets()

Sintaxis:

char *gets(char *s); 

Lee una cadena desde stdin.
gets lee una cadena de caracteres terminada con un retorno de línea desde la entrada estándar y la almacena en s. El carácter de retorno de línea es reemplazado con el carácter nulo en s.
Observa que la manera en que hacemos referencia a una cadena dentro de la función es char *, el operador * indica que debemos pasar como argumento la dirección de memoria donde estará almacenada la cadena a leer. Veremos la explicación en el capítulo de punteros, baste decir que a nivel del compilador char *cad y char cad[], son equivalentes, o casi.
gets permite la entrada de caracteres que indican huecos, como los espacios y los tabuladores. gets deja de leer después de haber leído un carácter de retorno de línea; todo aquello leído será copiado en s, incluido en carácter de retorno de línea.
Esta función no comprueba la longitud de la cadena leída. Si la cadena de entrada no es lo suficientemente larga, los datos pueden ser sobrescritos o corrompidos. Más adelante veremos que la función fgets proporciona mayor control sobre las cadenas de entrada.
Valor de retorno:
Si tiene éxito, gets devuelve la cadena s, si se encuentra el fin_de_fichero o se produce un error, devuelve tNULL. Ejemplo:

char cad[80]; 
do { 
   gets(cad); 
} while (cad[0] != '\000'); 

En este ejemplo, el programa permanecerá leyendo cadenas desde el teclado mientras no introduzcamos una cadena vacía. Para comprobar que una cadena está vacía basta con verificar que el primer carácter de la cadena es un carácter nulo.
 
Función puts()

Sintaxis:

int puts(const char *s); 

Envía una cadena a stdout.
puts envía la cadena s terminada con nulo a la salida estándar stdout y le añade el carácter de retorno de línea.
Valor de retorno:
Si tiene éxito, puts devuelve un valor mayor o igual a cero. En caso contrario devolverá el valor EOF.
Ejemplo:

char cad[80]; 
int i; 
do { 
   gets(cad); 
   for(i = 0; cad[i]; i++) 
      if(cad[i] == ' ') cad[i] = '_'; 
   puts(cad); 
} while (cad[0] != '\000'); 

Empezamos a llegar a ejemplos más elaborados. Este ejemplo leerá cadenas en "cad", mientras no introduzcamos una cadena vacía. Cada cadena será recorrida carácter a carácter y los espacios de sustituirán por caracteres '_'. Finalmente se visualizará la cadena resultante.

Llamo tu atención ahora sobre la condición en el bucle for, comparándola con la del bucle do while. Efectivamente son equivalentes, al menos para i == 0, la condición del bucle do while podría haberse escrito simplemente como while (cad[0]). De hecho, a partir de ahora intentaremos usar expresiones más simples.
Apéndice C: Bibliotecas estándar - Parte 2