martes, 15 de diciembre de 2009

Apertura de Ficheros

Antes de que se pueda acceder a un fichero èste debe ser abierto mediante la funciòn fopen:

FILE *fopen (name mode) /* Abre un -fichero */

char name; /* Nombre del -fichero a abrir */

char *mode; /* Modo de acceso al -fichero */

El primer argumento de fopen es el nombre del fichero, enviado como una cadena de caracteres. El formato del nombre de fichero es dependiente del sistema operativo. Sin embargo, muchas (no todas) las implementaciones de la librería C estándar de E/S trasladan los nombres de ficheros especificados como en Unix al formato requerido por el sistema operativo.

Por ejemplo, el formato de un nombre de fichero en Unix es:

/directorio l/directorio2/ ... /fichero

Cada uno de los componentes del nombre del fichero (directorio 1, directorio2, fichero) pueden estar formados por cualquier secuencia de caracteres excepto por un slash "A Sólo son significativos los catorce primeros caracteres. No hay un límite para el número de directorios que se pueden especificar.

El "mode" (modo) puede ser de tres tipos:

• modo de acceso "r" indica que el fichero se va a abrir para lectura. Si el fichero no existe, se devolverá un error.
• modo "w" especifica que el fichero se va a abrir para escritura. Si el fichero ya existe no se tendrá en consideración el contenido anterior, perdiéndose por corajoleto. Si el fichero no existiese, entonces lo creará la propia Tunción fopen.
• modo "a"especifica que el fichero se va a abrir para añadirle texto (append). Si el fichero ya existe, los nuevos datos se grabarán al final del mismo, y si no existiese será creado por la función.

En caso de que se produzca un error, fopen devuelve el valor NULL, definido en como (char *)0.

jueves, 10 de diciembre de 2009

E/S básica

Las operaciones más sencillas que se pueden realizar sobre un fichero que ya esté abierto son getc y putc.

int getc(fp)

FILE *fp;

getc devuelve el siguiente caràcter del fichero especificado for fp, o EOF (definida en ). EOF se devuelve cuando se produce algún error o se alcanza el final de fichero.

Análogamente:

int putc(fp)

FILE *fp;

putc escribe el caràcter dado en el fichero fp, y retorna "c" o EOF (en caso de error).

feof(fp)

FILE *fp;

feof devuelve un valor distinto de cero si se ha llegado al final del fichero fp.

ferror(fp)

FILE *fp;

ferror devuelve un valor distinto de cero si se ha encontrado algùn error durante la lectura o escritura del fichero fp

fclose(fp)

FILE *fp;

fclose cierra el fichero fP' devolviendo un EOF si se produce algún error (por ejemplo, si el fichero fp no fue abierto previamente).

La funciòn freopen

FILE *freopen(name, mode, fp)

char *name;

char *mode;

FILE *fp;

en primer lugar cierra el fichero especificado por fp y abre un nuevo fichero, de modo que el fichero recién abierto reutiliza la estructura FILE apuntada por fp. Freopen devuelve fp si la apertura se ha realizado sin problemas, o NULL en caso contrario.

ungetc(c, fp)

char c;

FILE *fp;


ungetc provoca que la siguiente llamada a getc(fd) (así como scanf, getw, gets, y las restantes funciones de lectura) lea el carácter "c". Mediante el empleo dé úngete sólo se puede poner un carácter en el buffer del fichero fd.

jueves, 3 de diciembre de 2009

Ficheros Estándar

Cuando se inicia la ejecución de un programa C se produce la apertura automàtica de tres ficheros, antes de que llegue a producirse la llamada a main(). Estos ficheros son la entrada estándar "stdin" (standard input, normalmente el teclado) la salida estàndar "stdout" (standard output, normalmente la pantalla de vídeo) y el fichero estàndar de salida de errores "stederr" (standard error, normalmente la pantalla de video).

Este encaminamiento normal de los ficheros estándar (pantalla y teclado por defecto), puede verse modificado a través del intérprete de comandos de Unix y reencaminado hacia ficheros, "tuberías" (pipes) o regiones de memoria compartida.

La librería estándar de E/S declara stdin, stdout y stderr como punteros a estructuras FILE para los ficheros de ejitrada estándar, salida estándar y fichero estándar de errores, respectivamente.

Las funciones getchar y putehar son macros, en lugar de auténticas funciones, definidas en como:

#define getchar() getc(stdin)

#define putchar(c) putc(c, stdout)

Hay que advertir que stdin, stdout y stderr son constantes y no pueden ser reasingnados mediante fopen como podrìa parecer natural.

stdout = fopen("myfile", "w");

no es un procedimiento válido para redireccionar la salida estándar al fichero myfile. Sin embargo,

freopen("myfile", "w", stdout);


sí podría servir para este propósito, debido a que freopen cierra y abre el fichero, como comentamos anteriormente.

lunes, 1 de junio de 2009

Salida con formato

printf es la funciòn bàsica utilizada para salida con formato; es llamada en la forma:

printf(control, argl, arg2,...)

char *control;

Esta funciòn acepta un nùmero variable de argumentos, convirtièndolos, formateàndolos e imprimièndolos bajo las especificaciones incluidas en "control". Los caracteres del string de control se vuelcan en el fichero de salida estàndar, salvo el metacaràcter "%", que se emplea como una especificaciòn de formato para controlar la impresiòn de los argumentos.

• un signo menos "-", indicando que el siguiente argumento debe imprimirse justificando a la izquierda en su campo de salida;

• una cadena de dìgitos, especificando el tamaño mìnimo del campo de salida para ese argumento. Si el argumento ya formateado ocupa menos caracteres que la anchura del campo que le ha sido asignado se completará con caracteres por la izquierda (o por la derecha si se ha especificado justificación a la izquierda).

Si la especificación de la anchura del campo contiene un cero como primer carácter (por ejemplo OSd), la longitud total del campo se completará con ceros en lugar de con espacios en blanco. La inclusión de este cero por la izquierda no debe confundirse en ningún caso con la expresión de una constante en octal (por ejemplo, el carácter espacio en blanco, ASCII 32 en decimal, se expresa como 040 en octal).

A diferencia de la salida con formato en Fortran, printf no trunca la conversión de argumentos en caso de que necesiten una extensión mayor que la especificada para el campo de salida;

• un punto, separando el ancho del campo de salida, de la precisiòn;

• una cadena de dìgitos que puede especificar tanto el nùmero màximo de caracteres a imprimir de una cadena, como el nùmero de dìgitos a imprimir a la derecha del punto decimal cuando se están imprimiendo números en coma flotante (float o double);

• una ele "l", que indica que el siguiente argumento es un long it, en lugar de un int;

• algunas implementaciones de printf interpretan el caràcter asterisco "*" como una anchura de campo o precisión, con el significado de que el siguiente argumento indicará realmente la anchura del campo o precisión del argumento a imprimir. Por ejemplo:

printf("%.*s", longitud, cadena);

imprimirá al menos "longitud" caracteres de la cadena de caracteres "cadena".


Los caracteres de conversiòn de salida son:

d- Convierte el argumento entero a un número decimal con signo.

o- Convierte su argumento (entero) a base octal.

x- El argumento entero se convierte a hexadecimal.

u- El argumento entero se convierte a notación decimal sin signo.

c- Interpreta su argumento como un único carácter.

s- Considera su argumento una cadena (string).

e- Convierte su argumento en coma flotante (interpretado como double, porque C siempre pasa los números en coma flotante como double) a notación exponencial, con signo, mantisa y exponente:

[-]m.nnnnE[-]xx

La longitud de la cadena de enes "n" viene determinada por la precisión, que es de 6 por defecto. (Recordemos que float proporcionaba 6 dígitos de precisión y double 15.) * • ' - El argumento en coma flotante se expresa en notación de coma fija:

[-jmmm.nnnn

La longitud de la cadena de enes "n" se toma nuevamente de 6 por defecto.

g- Convierte su argumento en coma flotante a formato "%f o "%e", dependiendo de cuál de los dos proporcione una cadena de menor longitud.

Cualquier otro caràcter distinto de los especificados anteriormente y que siga a un signo "%" se imprimirá literalmente. Así:

printf("%%");

Imprimirá un único carácter"'%".

La apariciòn de los anteriores caracteres en mayùsculas (D, O, X, U, E, F o G) se interpreta como si una ele "l" precediese al caràcter correspondiente en, minúculas. Así

printf("%D", valor);

es equivalente a

printf("%ld", valor);

La salida con formato especificada por printf y enviada por esta función al fichero de salida estándar tambièn se puede enviar a otro fichero o a una cadena de caracteres, por medio de las funciones fprintf y sprintf, respectivamente.

fprintf(fp, control, argl, arg2,...)

FILE *fp;

char *cntrol;

realiza su salida sobre el fichero especificado por fp.

sprintf(string, control, argl, arg2,...)

lleva su salida al array string de acuerdo con las especificaciones de formato incluidas, en lugar de poner la salida en un fichero.

Entrada con formato

scanf es la funciòn bàsica de entrada con formato.

int scanf (control, argl, arg2, ...)

char *control;

Esta funciòn lee caracteres con formato a partir del fichero de entrada estàndar "stdin", interpretàndolos de acuerdo a las especificaciones de la cadena de control.

Cada uno de sus argumentos debe ser un puntero, especificando la dirección de la variable donde deberá almacenarse el resultado. Obviamente, scanf es una función que necesita "llamada por referencia", pues va a modificar las variables que se le pasan como argumentos. Un error frecuente en su uso consiste en la omisión de los "&" en cada uno de los argumentos.

Los caracteres de separación como espacios en blanco, fabuladores y caracteres de salto de línea que figuren en la cadena de control, serán ignorados.

Los restantes caracteres (excepto el"%") se corresponden con una especificación de formato de entrada, pudiendo consistir en:

• el carácter asterisco "*", indicando que el valor leído no debe almacenarse en la variable;

• una cadena de dìgitos, especificando la longitud màxima del campo de entrada (el número de caracteres a convertir);

• carácter "h , para indicar que el siguiente argumento debe ser considerado como un puntero a un short int, o el carácter "i' indicando que debe ser tratado como un puntero a un long int, o a un double (equivalente a long float);

• carácter de conversión.

Las conversiones de caracteres de entrada permitidas son:

d - Lee un entero decimal. El argumento debe ser un puntero a un entero (o un puntero a un short int o long int, si se hubiesen antepuesto "h" o "1" a la especificación de formato "d").

o - Lee un número entero octal.

x - Lee un número entero hexadecimal.

c - Lee un único carácter de* la entrada. El argumento debe ser un puntero a un carácter.

s - Acepta una cadena de caracteres terminada por un espacio en blanco o un carácter de salto de línea. El array de caracteres donde se guarde el resultado debejser lo bastante grande como para contener todos los caracteres y el carácter nulo terminador de cadena.

e - Lee un número en coma flotante. El argumento debeser un float (o un double, con especificación "le").

f - Análogo al anterior. Acepta un número en coma flotante.

[ - Lee una cadena de caracteres limitada por separadores arbitrarios, almacenándola en el array apuntado por el argumento. El corchete de apertura "[" va seguido por un conjunto de caracteres y un corchete de cierre "]". Si el carácter inmediatamente posterior a "[" no es un circunflejo "ó", entonces scanf leerá solamente los caracteres que aparezcan en el conjunto de caracteres entre corchetes. Por el contrario, si el carácter inmediatemente posterior a"[" es un circunflejoentonces scanf leerá caracteres hasta que encuentre algún carácter de los contenidos en el conjunto de caracteres entre corchetes.

Los caracteres de conversión d, o, x, e, y f pueden aparecer en mayúsculas o precedidos por una ele "i", para indicar que el correspondiente puntero apunta a un long int o long float.

scanf interrumpe la lectura cuando llega al final.de la cadena de control, o cuando la entrada no cumple la especificación, de formato impuesta (por ejemplo, intentar leer un literal con una especificación %d de número entero).

scanf devuelve un número entero indicando el número de asignaciones que ha realizado o EOF si ha encontrado un final de fichero y esperaba leer más caracteres.

Es importante aclarar que el valor cero no quiere decir que se haya alcanzado el final de fichero, sino que no se ha convertido correctamente ningún campo de entrada.

Análogamente a lo descrito para printf, scanf también permite que su entrada provenga de una cadena de caracteres o de un fichero.

int fscanf(fd, control, argl, arg2,...)

FILE *fd;

char *control;

es similar a scanf, con la diferencia de que toma su entrada del fichero fd, en lugar de "stdin".

int sscanf(control, argl, arg2,...)

char *control;

tomaría su entrada de una cadena de caracteres. Como la lectura de una cadena no viene acompañada de efectos laterales (side effects), sscanf es generalmente más útil que scanf o fscanf.

E/S orientada a lìneas

La funciòn fgets leerà la siguiente lìnea de entrada (incluido el carácter \n) del fichero "fp", guardando su entrada en el array "line" que deberá estar terminado en un carácter nulo. Se leerán al menos "n-1" caracteres, fgets devuelve line, salvó que se haya alcanzado el final de fichero antes de llegar a leer ningún carácter.

char *fgets(line, nchars, fp)

char *line;

int nchars;

FILE *fp;

La funciòn fputs escribe la cadena de caracteres "line" sobre el fichero especificado por fp.

fputs(line, fp)

char *line;

FILE *fp;

La librerìa estàndar tambièn incluye kas funciones gets y puts que leen y escriben de stdin y stdout, respectivamente. Sin embargo, no son equivalentes a fgets y fputs dirigidas a stdin y stdout.

La funciòn gets

char *gets(line)

char *line;

lee la siguiente lìnea de entrada en stdin (incluyendo el \n) sobre el array de caracteres "line", que se supone tendrá suficiente espacio para contener la entrada. El carácter \n no se almacena en "line". A diferencia de fgets, gets devuelve "line" a menos que se alcance el final de fichero antes de que se hayja podido leer ningún carácter.

La función puts

puts(line)

char *line;

escribe la cadena de caracteres "line" sobre stdout seguido por un caràcter \n.

Entrada/Salida binaria

Las funciones bàsicas de E/S gets y putc son capaces de leer y escribir cualquier tipo de fichero (al menos bajo Unix), no sòlo ficheros de texto.

Se puede escribir una "palabra" (tipo de dato entero) sobre un fichero utilizando:

int putw(word, fp)

int word;

FILE *fp;

putw devuelve la palabra escrita en el fichero, o EOF, si se ha producido algún error.

Se puede leer una palabra de un fichero utilizando

int-getw(fp)

FILE *fp;

getw devuelve la palabra, o EOF, si se ha alcanzado el final de fichero antes de leer la totalidad de la palabra. Como EOF es un valor permitido para un int "(pero no para un char), debería utilizarse feof para comprobar la condición de final de fichero después de getw.

Cualquier variable de C puede escribirse como si se tratase de un array de caractores. Por ejemplo, dada la declaraciòn:

union {

long int val;

char c[sizeof long];

} x;

Leyendo o escribiendo el array de caracteres x.c se transferirá exactamente el valor de x.val.

La funciòn general de lectura binaria es fread:

int fwrite(pointer, size, number, fp)

char *pointer;

unsigned int size;

unsigned int number;

FILE *fp;

Esta funciòn lee un nùmero "number" de objetos del fichero "fp", de un tamaño de "size" bytes cada uno de ellos, en el àrea de datos apuntada por "pointer" fread devuelve el número de objetos completos que ha podido leer. Así, cero equivale a un fin de fichero.

La funciòn general de escritura binaria es fwrite

int fread(pointer, size, number, fp)

char *pointer;

unsigned int size;

unsigned int number;

FILE *fp;

que escribe "number" objetos del fichero "fp", de "size" bytes cada uno de ellos, en el àrea apuntada por "pointer" fwrite devuelve el número de objetos completos escritos, que coincidirá con num-ber a menos que se haya producido algún error. Un ejemplo típico de utilización sería:

long int

FILE «írom, *to;

while (f read ( (char *)!

fwriteUchar *)&x, sizeof x, 1, to) ;

copiando un long del fichero "from" al fichero "to".

Es importante observar el empleo del cast &x para obtener un char *. La expresión &(char *)x que fuerza a que "x" sea del tipo char, no funcionaría porque (char)x no es una variable, y no se puede aplicar un &.

Aunque la utilización de fread y fwrite es portable, los ficheros manejados por ellos no tienen porqué serlo, pues estos ficheros son fiel reflejo del tamaño y formato de los objetos de datos representados por el ordenador en cuestión.

Si se necesita escribir ficheros portables es mejor emplear funciones de desplazamiento y máscaras de bits o utilizar datos con formato.