Taller de Programación en C 2008-II Entrada/Salida Entrada/Salida • Funciones de entrada/salida no son parte del lenguaje propiamente tal )Bibliotecas Bibliotecas son parte del estándar ANSI C )Biblioteca estándar: <stdio.h> Daniel Herrera P. [email protected] • Bibliotecas no estándares implementan otras funciones de entrada/salida )Borland C: Console I/O (<conio.h>) Flujos de datos Flujos de texto • Entrada/Salida vista como flujos de bytes (streams) hacia y desde dispositivos • Dispositivos • Línea de texto: 0 o más caracteres terminadas por un caracter terminador (\n) )Teclado, T l d pantalla, t ll discos di duros, d adaptadores d t d gráficos, mouse, puertas de comunicación, redes, otros procesos, etc. )Terminador UNIX: \n )Terminador DOS/Windows: \r\n )Bibliotecas convierten automaticámente \r\n a \n • Todos son tratados de la misma manera! • Tamaño máximo de una línea: al menos 254 caracteres Flujos binarios Flujos estándares ANSI • Usados para todo tipo de datos • No se reconocen líneas en los datos • No hay conversión de terminadores • Todo programa ANSI C tiene 3 flujos de datos predefinidos )Entrada estándar (stdin) ` Generalmente, el teclado )Salida estándar (stdout) ` Generalmente, la consola )Salida de errores estándar (stderr) ` Generalmente, la consola )Pueden ser redirigidas a otro dispositivo ©Daniel Herrera P. 1 Taller de Programación en C 2008-II Estructura de datos FILE Usando flujos • Estructura de datos usada para acceso a flujos • Declarar punteros a FILE por cada flujo a utilizar • Abrir el flujo usando función fopen() )Cada flujo usado por el programa tiene una estructura FILE asociada )Funciones de manejo de flujos de datos reciben estructura FILE como argumento )stdin, stdout y stderr son punteros a FILE ` Flujos estándares están siempre abiertos Caracter Entrada fopen() Salida Descripcion getchar() putchar() Lee/escribe un caracter Línea gets() scanf() puts() printf() Sin formato Con formato Binario fread() fwrite() Lee/escribe flujo binario Modos de operación Leer Escribir FILE *fopen(char const *nombre, char const *modo); • Abre el flujo de datos nombre con el modo indicado )Nombre: ristra que identifica el archivo o dispositivo a abrir )Modo: ristra que indica el modo de operación del flujo Modos de operación Agregar Texto “r” “w” “a” Binario “rb” “wb” “ab” ©Daniel Herrera P. • Leer y/o escribir desde y hacia el flujo • Cerrar el flujo con fclose() )Libera estructura FILE Usando flujos Tipo de dato )Tipo Ti d de acceso d deseado d (lectura, (l t escritura, it ambos) • Archivo a leer debe existir; en caso contrario, es un error • Archivo a escribir es creado si no existe; o truncado si existe • Archivo a agregar (append) es creado si no existe. Si existe, datos nuevos se agregan al final del archivo 2 Taller de Programación en C 2008-II fopen() errno y perror() • Función fopen() retorna un puntero a una estructura FILE para el archivo • Funciones de entrada/salida pueden generar errores )NULL si hubo algún error )Variable errno refleja el tipo del error FILE *archivo; archivo = fopen(“datos”, “r”); if (archivo == NULL) exit(EXIT_FAILURE); perror() void perror(char const *mensaje) • Imprime )ristra mensaje, )un :,: y )una descripción del error derivada automáticamente del valor actual de errno Perror(“Tarea 1”); Tarea 1: no space left on device )Código de identificación del error se almacena en variable entera errno (definida en <errno <errno.h>) h>) )Ejemplo: error 28 ` Alias: ENOSPC ` Descripción: No hay espacio disponible en el dispositivo freopen() • Función freopen() permite reabrir un flujo con otro modo FILE *freopen(char const *nombre, char const modo, FILE *flujo); flujo); *modo )Función cierra el flujo dado y lo reabre con el nombre y modo indicados ` NULL si hubo algún error ` Si no, retorna un puntero al nuevo flujo fclose() getchar() • Función fclose() cierra un flujo • Función getchar() retorna el siguiente caracter disponible en el flujo stdin int fclose(FILE *flujo); )Función cierra el flujo dado )Vacia los buffers asociados al flujo ` EOF si hubo algún error )0 si no lo hubo )EOF : Constante que representa el fin del archivo (End Of File) ©Daniel Herrera P. int getchar(void); )Lee un unsigned char y lo convierte a int )Retorna EOF si no hay más caracteres a leer )EOF si hubo algún error • EOF no es un código ASCII! )No cabe en un unsigned char 3 Taller de Programación en C 2008-II getc() feof() • Función getc() retorna el siguiente caracter disponible en el flujo dado • Función feof() indica si se llegó al final del flujo int getc(FILE *flujo); )Lee un unsigned char y lo convierte a int )Retorna EOF si no hay más caracteres a leer )EOF si hubo algún error int feof(FILE *flujo); )Retorna 0 si aún hay más caracteres a leer )Retorna valor distinto de 0 si se llegó al final del flujo • Función fgetc() es idéntica • Válido para flujos de texto y binarios ferror() putchar() • Función ferror() indica si ocurrió un error en el flujo • Función putchar() envía el caracter c al flujo stdout int ferror(FILE *flujo); )Retorna 0 si no hubo error )Retorna valor distinto de 0 si ocurrió un error • Válido para flujos de texto y binarios int putchar(int c); )Convierte c de int a unsigned char )Retorna EOF si ocurrió un error )El caracter c en caso contrario putc() ungetc() • Función putc() envía caracter c al flujo f • Función ungetc() retorna caracter c al flujo f int putc(int c, FILE *f); )Convierte c de int a unsigned char )Retorna EOF si ocurrió un error ` Llamar a ferror() para flujos binarios )El caracter c en caso contrario )Función fputc() es idéntica ©Daniel Herrera P. int ungetc(int c, FILE *f); )Convierte c de int a unsigned char )Retorna EOF si ocurrió un error )El caracter c en caso contrario )Anula el flag EOF 4 Taller de Programación en C 2008-II Ejemplo fgets() • Procesar sólo los primeros dígitos de un flujo • Función fgets() lee buffer_size - 1 caracteres desde stream al buffer buffer int c; while((c = getchar()) != EOF && isdigit(c)) { /* Hacer algo con el dígito */ } ungetc(c, stdin); char *fgets(char *buffer, int buffer_size, FILE stream); *stream); )Lee sólo buffer_size – 1 caracteres ` Datos siguientes quedan en el flujo )Lectura se detiene al encontrar un \n ` En ambos casos, agrega \n al final del buffer fgets() fputs() • Función fgets() retorna NULL en caso de error o fin de archivo • Función fputs() escribe contenido de buffer buf a stream )Usar ferror() o feof() para distinguir entre estos casos • Tamaño mínimo del buffer es 2 )Último caracter es el \n agregado por la función int fputs(char *buf, FILE *stream); )Buffer debe contener una ristra terminada en NULL ` Contenido de ristra se imprime tal cual )En caso de error, función retorna EOF ` En caso de éxito, retorna valor no negativo gets() puts() • Función gets() lee caracteres desde stdin al buffer buffer • Función puts() escribe contenido de buffer buf a stdout char *gets(char *buffer); )gets() no almacena el caracter \n )gets() no define largo del buffer ` Fácil sobreescribir memoria int puts(char *buf); )puts() agrega un caracter \n al flujo ` En caso de error, función retorna EOF ` En caso de éxito, retorna valor no negativo )NUNCA USAR gets() ` Usar fgets(buffer, buffersize, stdin) ©Daniel Herrera P. 5 Taller de Programación en C 2008-II Ejemplo scanf() • Copiar líneas de stdin a stdout • Funciones scanf() leen caracteres con un formato dado desde un flujo #include <stdio.h> #define MAXLINE 1024 char buf[MAXLINE]; while(fgets(buf, MAXLINE, stdin) != NULL) { fputs(buf, stdout); } int scanf(char const *format, . . .); int fscanf(FILE *ff, char const *format format, . . .); ); int sscanf(char const *ristra, char const *format, . . .); scanf() scanf() • Función scanf() lee caracteres de la entrada estándar stdin • Función sscanf() lee caracteres de una ristra • Función ó fscanf() f f() lee caracteres de un flujo f dado • Función scanf() requiere punteros a áreas de memoria que reciben los datos leídos )Variables )Ristras )Punteros )Retornan el número de conversiones exitosas )EOF, al encontrar fin del flujo Formato de scanf() Códigos de formato scanf() • Función scanf() recibe un formato como argumento, que puede contener • Formato comienza con %, al que sigue: )Caracteres de espacio en blanco ` Espacio, Espacio tab, tab retorno de carro, carro avance de línea, línea etc. etc )Códigos de formato )Otros caracteres ` Entrada debe ajustarse a estos caracteres scanf(“ %d:%f\n”, &a, &b); ©Daniel Herrera P. )Asterisco (opcional): indica que valor leído es desechado )Ancho (opcional): no puede ser negativo ` Si no está presente, se lee hasta el siguiente espacio en blanco )Calificador (opcional) ` h, l ó L )Código de formato 6 Taller de Programación en C 2008-II Formato de scanf() printf() %c: caracter %d: entero decimal %i: decimal con base %u: decimal sin signo g %o: octal sin signo %x, %X: hexadecimal sin signo • %p: puntero • Funciones printf() escriben caracteres con un formato dado en un flujo • • • • • • • %f: punto flotante • %e, %E: punto flotante con formato E • %g, %G: punto flotante con formato G (%f ó %e) • %s: ristra • %: el caracter % printf() • Función printf() escribe caracteres en la salida estándar stdout • Función sprint() escribe caracteres en una ristra • Función fprintf() escribe caracteres en un flujo dado int printf(char const *format, . . .); int fprintf(FILE *ff, char const *format format, . . .); ); int sprintf(char const *ristra, char const *format, . . .); printf() • Función sprintf() no especifica el tamaño del buffer donde almacenar los datos )Puede causar problemas si buffer es muy pequeño • Códigos de formatos de printf() similares pero no iguales a scanf() )Posible fuente de erorres )Retornan el número de caracteres escritos )Si hubo error, retornan un número negativo fread() fwrite() • Función fread() lee count elementos desde el flujo stream al buffer buf • Función fwrite() escribe count elementos desde el buffer buf al flujo stream size_t fread(void *buf, size_t size, size_t count, FILE *stream); stream); )Cada elemento tiene tamaño size (en bytes) )Retorna número de elementos leídos ` Si es diferente de count, ocurrió un error ` Llamar a feof() o a ferror() ©Daniel Herrera P. size_t fwrite(void *buf, size_t size, size_t count, FILE *stream); stream); )Cada elemento tiene tamaño size (en bytes) )Retorna número de elementos escritos ` Si es diferente de count, ocurrió un error ` Llamar a feof() o a ferror() 7 Taller de Programación en C 2008-II Ejemplo struct VALOR { long a; float b; char h c[SIZE]; [SIZE] } datos[NUMERO]; numLeidos = fread(datos, sizeof(struct VALOR), NUMERO, input); ©Daniel Herrera P. 8