Algoritmos y Lenguaje de Programación, Sección 1 Entrada/Salida Entrada/Salida • Funciones de entrada/salida no son parte del lenguaje propiamente tal )Bibliotecas son parte del estándar ANSI C )Biblioteca estándar: <stdio.h> Mario Medina C. [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, pantalla, discos duros, adaptadores 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 ©Mario Medina C. 1 Algoritmos y Lenguaje de Programación, Sección 1 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” ©Mario Medina C. • Leer y/o escribir desde y hacia el flujo • Cerrar el flujo con fclose() )Libera estructura FILE Usando flujos Tipo de dato )Tipo de acceso deseado (lectura, escritura, 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 Algoritmos y Lenguaje de Programación, Sección 1 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.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); )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) ©Mario Medina C. 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 Algoritmos y Lenguaje de Programación, Sección 1 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 • Qué pasa si flujo es binario? • 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 ©Mario Medina C. 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 Algoritmos y Lenguaje de Programación, Sección 1 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); )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) ©Mario Medina C. 5 Algoritmos y Lenguaje de Programación, Sección 1 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 *f, char const *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() lee caracteres de un flujo 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, tab, retorno de carro, avance de línea, etc. )Códigos de formato )Otros caracteres ` Entrada debe ajustarse a estos caracteres scanf(“ ©Mario Medina C. %d:%f\n”, &a, &b); )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 Algoritmos y Lenguaje de Programación, Sección 1 Formato de scanf() %c: caracter %d: entero decimal %i: decimal con base %u: decimal sin signo %o: octal sin signo %x, %X: hexadecimal sin signo • %p: puntero • • • • • • • %f: punto flotante • %e, %E: punto flotante con formato E • %g, %G: punto flotante con formato G (%f ó %e) • %s: ristra • %: el caracter % printf() • Funciones printf() escriben caracteres con un formato dado en un flujo int printf(char const *format, . . .); int fprintf(FILE *f, char const *format, . . .); int sprintf(char const *ristra, char const *format, . . .); Ejemplo int a, b, c; scanf(“%4d %4d %4d”, &a, &b, &c); Ante la entrada 12345 67890, retorna a = 1234 b = 5 c = 6789 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 )Retornan el número de caracteres escritos )Si hubo error, retornan un número negativo printf() Formato de printf() • Función sprintf() no especifica el tamaño del buffer donde almacenar los datos • Función printf() recibe un formato como argumento, que puede contener )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 )Caracteres de espacio en blanco ` Espacio, tab, retorno de carro, avance de línea, etc. )Códigos de formato )Otros caracteres ` Son impresos sin cambios printf(“Hora = %h:%m%s\n”, h, m, s); ©Mario Medina C. 7 Algoritmos y Lenguaje de Programación, Sección 1 Códigos de formato de printf Formatos de printf() • Formato comienza con %, al que sigue: • %c: caracter sin signo • %d, %i: entero decimal • %u: decimal sin signo • %o: octal sin signo • %x, %X: hexadecimal sin signo • %p: puntero )Modificador de conversión (opcional) ` h, l ó L )Ancho (opcional): no puede ser negativo ` Especifica el número mínimo de caracteres )Precisión (opcional) )Modificador (opcional) )Código de formato Formatos de printf() Formatos de printf() Código 1 -12 12345 1234567 %d 1 -12 12345 1234567 %6d 1 -12 12345 1234567 %.4d 0001 -0012 12345 %6.4d 0001 -0012 12345 %-4d 1 -12 12345 1234567 %04d 0001 -012 12345 1234567 %+d +1 -12 +12345 +1234567 Código A ABC ABCDEFGH %s A ABC ABCDEFGH 1234567 %5s A ABC ABCDEFGH 1234567 %.5s A ABC ABCDE %5.5s A ABC ABCDE %-5s A ABC ABCDEFGH fread() Formatos de printf() Código 1 0.01 0.00012345 12345.6789 %f 1.000000 0.010000 0.000123 12345.678900 %10.2 f 1.00 0.01 0.00 12345.68 %e 1.000000e+00 1.000000e-02 1.234500e-04 1.234568e+04 %.4e 1.0000e+00 1.0000e-02 1.2345e-04 1.2346e+04 %g 1 0.01 0.00012345 12345.7 ©Mario Medina C. • %f: punto flotante • %e, %E: punto flotante con formato E • %g, %G: punto flotante con formato G (%f ó %e) • %s: ristra • %: el caracter % • Función fread() lee count elementos desde el flujo stream al buffer buf size_t fread(void *buf, size_t size, size_t count, FILE *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() 8 Algoritmos y Lenguaje de Programación, Sección 1 fwrite() • Función fwrite() escribe count elementos desde el buffer buf al flujo stream size_t fwrite(void *buf, size_t size, size_t count, FILE *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() Ejemplo struct VALOR { long a; float b; char c[SIZE]; } datos[NUMERO]; numLeidos = fread(datos, sizeof(struct VALOR), NUMERO, input); fflush() ftell() • Función fflush() fuerza escritura de los datos en buffers del sistema al flujo stream • Función ftell() retorna la posición actual del puntero al flujo stream int fflush(FILE *stream); )Garantiza la consistencia de los datos ` Buffers son también escritos al cerrar el archivo long ftell(FILE *stream); )Retorna la posición en el archivo en bytes )Retorna -1 en caso de error )Retorna 0 en caso de éxito ` EOF si ocurrió un error fseek() fseek() • Función fseek() cambia la posición actual del puntero al flujo stream • Cambiando el puntero al archivo int fseek(FILE *stream, long offset, int from); )Campo from: ` SEEK_SET: desde el comienzo del archivo ` SEEK_CUR: desde la posición actual ` SEEK_END: desde el final del archivo ` Retorna 0 en caso de éxito ©Mario Medina C. )Cambiar posición a antes del comienzo del archivo genera un error )Escribir a posición después del final del archivo lo hace crecer )Leer de posición después del final del archivo genera un error )fseek() limpia flag EOF 9 Algoritmos y Lenguaje de Programación, Sección 1 rewind() fgetpos() • Función rewind() hace que el puntero apunte al comienzo del flujo stream • Función fgetpos() lee la posición actual del puntero en el flujo stream void rewind(FILE *stream); )Limpia flags de error y EOF int fgetpos(FILE *stream, fpos_t *posicion); )Posición actual del puntero queda almacenada en posicion )Retorna 0 si no ocurrieron errores fsetpos() clearerr() • Función fsetpos() define la posición actual del puntero en el flujo stream • Función clearerr() limpia el flag de error void clearerr(FILE *stream); int fsetpos(FILE *stream, fpos_t const *posicion); )Posición actual del puntero es leída desde posicion )Retorna 0 si no ocurrieron errores remove() rename() • Función remove() borra un archivo • Función rename() renombra un archivo void remove(char const *nombre); )Retorna 0 si hubo éxito ©Mario Medina C. void rename(char const *nombreViejo, char const *nombreNuevo); )Retorna 0 si hubo éxito 10