Está en la página 1de 16

Null

Para otros usos de este trmino, vase Null (desambiguacin).


El trmino null, nulo es a menudo utilizado en la computacin para hacer referencia a la nada.
En programacin, null resulta ser un valor especial aplicado a un puntero (o referencia) usado
para indicar que no se apunta a un objeto o dato vlidos. Usualmente se utiliza el valor 0
(cero) para significar null, debido a que muchos sistemas operativos consideran el intentar
acceder a una direccin de memoria tan baja como un error. Null es tambin utilizado en
varias otras disciplinas y no nicamente en programacin.
En contexto de bases de datos, null se utiliza para indicar la ausencia de valor asociado a un
campo para un determinado registro.
Asimismo se definen los resultados para null en operaciones lgicas:
Operacin "O"
Verdadero O null = Verdadero
Falso O null = null
Operacin "Y"
Verdadero Y null = null
Falso Y null = Falso

EOF
En programacin, EOF es un concepto para determinar el final de un archivo. Muchos
lenguajes de programacin tienen formas de detectar el final de archivo como condicionante
para la lectura de un flujo de datos
El carcter EOF existe en la tabla ASCII aunque no es este el carcter que indica el fin-de-
archivo en la fuente de datos, ya que un fichero no contiene como ltimo byte el carcter EOF.
En la biblioteca estndar de C, el acceso a un fichero y otras funciones I/O pueden devolver
un valor igual al simblico EOF para indicar que la condicin end-of-file se ha cumplido. Ej:

/* Ejemplo en C */
/* Se abre el archivo o stream y demas tareas... */
....
/* Se procede a la lectura */
while (!feof(&fd))
{
/* Leyendo hasta que se termine */
op_result = fread ((void*)buffer, sizeof(int), 1, &fd);
/* Chequeamos el resultado de la operacion
if (op_result == EOF)
break;
/* Se trabaja con el buffer */
.....
}
La interpretacin de C como resultado de la operacin de lectura en caso de ser EOF es, por
lo general, -1.

El puntero FILE *

Todas las funciones de estrada/salida estndar usan este puntero para


conseguir informacin sobre el fichero abierto. Este puntero no apunta al
archivo sino a una estructura que contiene informacin sobre l. Esta
estructura incluye entre otras cosas informacin sobre el nombre del
archivo, la direccin de la zona de memoria donde se almacena el
fichero, tamao del buffer.

Apertura del fichero para lectura: fopen

Ahora es preciso abrir el fichero. Para ello usamos la funcin fopen. Esta
funcin tiene el siguiente formato:
FILE *fopen(const char *nombre_fichero, const char *modo);

En el ejemplo usbamos:
fichero = fopen("origen.txt","r");

El nombre de fichero se puede indicar directamente (como en el ejemplo)


o usando una variable y se puede abrir de diversas formas. Esto se
especifica con el parmetro modo. Los modos posibles son:

r Abre un fichero existente para lectura.


Crea un fichero nuevo (o borra su contenido si existe) y
w
lo abre para escritura.
Abre un fichero (si no existe lo crea) para escritura. El
a puntero se sita al final del archivo, de forma que se
puedan aadir datos si borrar los existentes.

Se pueden aadir una serie de modificadores siguiendo a los modos


anteriores:

b Abre el fichero en modo binario.


t Abre el fichero en modo texto.
+ Abre el fichero para lectura y escritura.
Ejemplos de combinaciones:

rb+ - Abre el fichero en modo binario para lectura y escritura.


w+ - Crea (o lo borra si existe) un fichero para lectura y escritura.
rt - Abre un archivo existente en modo texto para lectura.

Comprobacin de fichero abierto

Un aspecto muy importante despus de intentar abrir un fichero es


comprobar si realmente est abierto. El sistema no es infalible y pueden
producirse fallos: el fichero puede no existir, estar daado o no tener
permisos de lectura. Si intentamos realizar operaciones sobre un puntero
tipo FILE cuando no se ha conseguido abrir el fichero puede haber
problemas.

Si el fichero no se ha abierto, el puntero fichero (puntero a FILE) tendr el


valor NULL, si se ha abierto con xito tendr un valor distinto de NULL. Por
lo tanto, para comprobar si ha habido errores, nos fijamos en el valor del
puntero:

if (fichero == NULL) {
printf( "No se puede abrir el fichero.\n" );
exit( 1 );
}

Si fichero == NULL significa que no se ha podido abrir por alguna causa. Lo


ms conveniente es salir del programa. Para salir utilizamos la
funcin exit(), donde el argumento 1 indica al sistema operativo que se han
producido errores. Esta funcin precisa del archivo de cabecera stdlib.h.

Lectura de caracteres del fichero: getc

Ahora ya podemos empezar a leer el fichero. Para ello podemos utilizar


la funcin getc, que lee los caracteres uno a uno. Se puede usar tambin
la funcin getc (son equivalentes: la diferencia es que getcest
implementada como macro). Adems de estas dos, existen otras
funciones como fgets, fread que leen ms de un carcter.
El formato de la funcin getc (y de fgetc) es:
int getc(FILE *fichero);

En este caso lo usamos como:

letra = getc( fichero );

Tomamos un carcter de fichero, lo almacenamos en letra y el puntero del


fichero se coloca en el siguiente carcter.

Comprobacin de fin de fichero: feof

Cuando entramos en el bucle while, la lectura se realiza hasta que se


encuentre el final del fichero. La deteccin del final del fichero se puede
llevar a cabo de dos formas:

con la funcin feof


comprobando si el valor de letra es EOF (el ltimo carcter de
cualquier archivo).

En el ejemplo hemos usado la funcin feof. Esta funcin es de la forma:


int feof(FILE *fichero);

Esta funcin comprueba si se ha llegado al final de fichero, en cuyo caso


devuelve un valor distinto de 0. Si no se ha llegado al final de fichero
devuelve un cero. Por eso lo usamos del siguiente modo:

while ( feof(fichero) == 0 )

while ( !feof(fichero) )

La segunda forma que comentaba arriba consiste en comprobar si el


carcter ledo es el de fin de fichero EOF:

while ( letra != EOF )


Sin embargo, cuando trabajamos con ficheros de texto no hay ningn
problema, pero si estamos manejando un fichero binario podemos
encontrarnos EOF antes del fin de fichero. Por eso es preferible usar feof.

Cierre del fichero: fclose

Una vez realizadas todas las operaciones deseadas sobre el fichero hay
que cerrarlo. Es importante no olvidar este paso pues el fichero podra
corromperse. Al cerrarlo se vacan los buffers y se guarda el fichero en
disco. Un fichero se cierra mediante la funcin fclose. Esta funcin tiene el
siguiente formato:
FILE *fclose(FILE * stream);

Aqu stream es el puntero a FILE devuelto por fopen cuando el archivo se


abri. Si todo va bien, devuelve un cero, si hay problemas, devuelve otro
valor. Estos problemas se pueden producir si el disco est lleno, por
ejempl

if (fclose(fichero)!= 0)
printf( "Problemas al cerrar el fichero\n" );

Lectura de lneas del fichero: fgets

Esta funcin es muy til para leer lneas completas desde un fichero. Su
formato es:
char *fgets(char *buffer, int longitud_max, FILE *fichero);

Esta funcin lee desde el fichero hasta que encuentra un carcter '\n' o
hasta que lee longitud_max-1 caracteres y aade '\0' al final de la cadena (y
retiene el carcter '\n'). La cadena leda la almacena en buffer. Si se
encuentra EOF antes de leer ningn carcter, o si se produce un error, la
funcin devuelve NULL; en caso contrario devuelve la direccin de buffer.

#include <stdio.h>
#include <stdlib.h>

main()
{
FILE *fichero;
char texto[100];

fichero = fopen("origen.txt","r");
if (fichero == NULL) {
printf( "No se puede abrir el fichero.\n" );
exit( 1 );
}

printf( "Contenido del fichero:\n" );


fgets(texto,100,fichero);
while (feof(fichero) == 0) {
printf( "%s",texto );
fgets(texto,100,fichero);
}

if (fclose(fichero)!=0)
printf( "Problemas al cerrar el fichero\n" );
}

La funcin fread

Esta funcin se tratar posteriormente, junto con la funcin fwrite. Ambas


permiten guardar y leer, respectivamente, cualquier tipo de dato,
incluso estructuras.

Escritura de archivos. Operaciones y funciones bsicas

Vamos a completar ahora la parte que faltaba en la seccin anterior:


escribir en un fichero. Vamos a hacerlo de nuevo mediante un ejemplo.
En ste, abrimos un fichero origen.txt y lo copiamos en otrodestino.txt.
Adems, el fichero se muestra en pantalla (las partes nuevas se han
destacado en negrita).

#include <stdio.h>

main()
{
FILE *origen, *destino;
char letra;

origen = fopen("origen.txt","r");
destino= fopen("destino.txt","w");
if (origen == NULL || destino == NULL) {
printf( "Problemas con la apertura de los ficheros.\n" );
exit( 1 );
}

letra = getc(origen);
while (feof(origen) == 0) {
putc(letra, destino);
printf( "%c",letra );
letra = getc(origen);
}

if (fclose(origen)!= 0)
printf( "Problemas al cerrar el fichero origen.txt\n" );
if (fclose(destino)!= 0)
printf( "Problemas al cerrar el fichero destino.txt\n" );
}

Como en el caso de la lectura de archivos, analizaremos este ejemplo


poco a poco detenindonos en:

El puntero FILE
Apertura del fichero para escritura: fopen
Escritura de caracteres en el fichero: putc
Comprobacin de fin de fichero
Cierre del fichero: fclose

y, posteriormente, nos referiremos a:

Escritura de lneas en el fichero: fputs


La funcin fwrite

El puntero FILE *

Como hemos visto en antes, el puntero FILE es la base de la


escritura/lectura de archivos. Por eso definimos dos punteros FILE:

el puntero origen donde vamos a almacenar la informacin sobre el


fichero origen.txt, y
destino donde guardamos la del fichero destino.txt (el nombre del
puntero no tiene por qu coincidir con el de fichero).

Apertura del fichero para escritura: fopen


El siguiente paso, como antes, es abrir el fichero usando fopen. La
diferencia es que ahora tenemos que abrirlo en modo escritura. Usamos
el modo w (crea el fichero, o lo vaca si existe) porque queremos crear un
fichero. Recordemos que despus de abrir un fichero hay que comprobar
si la operacin se ha realizado con xito. En este caso, como es un
sencillo ejemplo, hemos comprobado ambos a la vez:
if (origen==NULL || destino==NULL)

pero es ms correcto hacerlo por separado, de modo que separemos la


posible causa del fallo.

Escritura de caracteres en el archivo: putc

Como se puede observar en el ejemplo, la lectura del fichero se hace


igual que antes, con getc. Para la escritura usamos la funcin putc:, cuya
sintaxis es:
int putc(int c, FILE *fichero);

donde c contiene el carcter que queremos escribir en el fichero y el


puntero fichero es el fichero sobre el que trabajamos.

En este caso lo usamos como:

putc(letra, destino);

De esta forma vamos escribiendo en el fichero destino.txt el contenido del


fichero origen.txt.

Comprobacin fin de fichero

Como siempre que leemos datos de un fichero debemos comprobar si


hemos llegado al final. Slo debemos comprobar si estamos al final del
fichero que leemos. No tenemos que comprobar el final del fichero en el
que escribimos puesto que lo estamos creando y an no tiene final.

Cierre del fichero: fclose


Y, por fin, lo que nunca debemos olvidar al trabajar con
ficheros: cerrarlos. Debemos cerrar tanto los ficheros que leemos como
aquellos sobre los que escribimos.

Escritura de lneas en el fichero: fputs

La funcin fputs trabaja junto con la funcin fgets . La sintaxis es:


int fputs(const char *cadena, FILE *fichero);

Esta funcin escribe en el fichero una cadena y no le aade un


carcter '\n' ni el terminador de cadena '\0'. Devuelve el ltimo carcter
escrito o EOF si se produce un error.

Veamos un ejemplo en el que se escriben tres lneas de texto al fichero y


despus se muestra su contenido.

#include <stdio.h>
#include <stdlib.h>

main()
{
FILE *fichero;
char texto[100];

fichero = fopen("destino.txt","w");
if (fichero == NULL) {
printf( "No se puede crear el fichero.\n" );
exit( 1 );
}

/* Escribe en el fichero */
fputs("Esta es la primera lnea del fichero\n", fichero);
fputs("Esta es la segunda lnea\n", fichero);
fputs("Esta es la ltima lnea del fichero\n", fichero);

if (fclose(fichero)!=0)
printf( "Problemas al cerrar el fichero\n" );

fichero = fopen("destino.txt","r");
if (fichero == NULL) {
printf( "No se puede crear el fichero.\n" );
exit( 1 );
}
printf( "Contenido del fichero:\n" );
fgets(texto,100,fichero);
while (feof(fichero) == 0) {
printf( "%s",texto );
fgets(texto,100,fichero);
}

if (fclose(fichero)!=0)
printf( "Problemas al cerrar el fichero\n" );
}

fwrite

Esta funcin se tratar posteriormente, junto con la funcin fread. Ambas


permiten leer y guardar, respectivamente, cualquier tipo de dato,
incluso estructuras.

Otras funciones para el manejo de ficheros

Lectura y escritura genricas: fread y fwrite


Posicionamiento en el fichero: fseek y ftell
fprintf y fscanf

Lectura y escritura genricas: fread y fwrite

Las funciones que hemos visto anteriormente (getc, putc, fgets, fputs) son
adecuadas para trabajar con caracteres (1 byte) y cadenas. Pero, qu
sucede cuando queremos trabajar con otros tipos de datos?.
Supongamos que queremos almacenar variables de tipo int en un fichero.
Como las funciones vistas anteriormente slo pueden operar con
cadenas, deberamos convertir los valores a cadenas (funcin itoa,integer
to string). Para recuperar luego estos valores deberamos leerlos como
cadenas y pasarlos a enteros (atoi, string to integer). Pero existe una
solucin mucho ms fcil: las funciones fwrite y fread. stas nos permiten
tratar con datos de cualquier tipo, incluso con estructuras.

fwrite

sta nos permite escribir en un fichero. Tiene el siguiente formato:


size_t fwrite(const void *p_buffer, size_t tamao, size_t nmero, FILE *p_fichero);

donde:

p_buffer - puntero a la variable que contiene los datos que vamos a


escribir en el fichero.
tamao - tamao del tipo de dato a escribir. Puede ser un int, un float,
una estructura, etc. Para conocer su tamao usamos el
operador sizeof.
nmero - nmero de datos a escribir.
p_fichero - puntero al fichero sobre el que trabajamos.

Esta funcin devuelve el nmero de elementos de tamao tamao (no


bytes) escritos realmente al fichero, si no ha ocurrido algn error.

Para que quede ms claro, examinemos el siguiente ejemplo: un


programa de agenda que guarda el nombre, apellido y telfono de cada
persona:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct {
char nombre[20];
char apellido[20];
char telefono[15];
} registro;

main()
{
FILE *fichero;

if ((fichero = fopen( "nombres.txt", "a" )) == NULL) {


printf( "No se puede abrir el fichero.\n" );
exit( 1 );
}

do {
printf( "Nombre: " ); gets(registro.nombre);
if (strcmp(registro.nombre,"")) {
printf( "Apellido: " ); gets(registro.apellido);
printf( "Telfono: " ); gets(registro.telefono);

/* Guarda el registro en el fichero */


fwrite( &registro, sizeof(registro), 1, fichero );
}
} while (strcmp(registro.nombre,"")!= 0);

fclose( fichero );
}

Este programa guarda los datos personales mediante fwrite usando la


estructura registro. Abrimos el fichero en modo "a" (append, aadir), para
que los datos que introducimos se aadan al final del fichero.

Una vez abierto abrimos entramos en un bucle do-while mediante el cual


introducimos los datos. Estos se van almacenando en la
variable registro (que es una estructura). Cuando tenemos todos los datos
de la persona, los introducimos en el fichero con fwrite:

fwrite( &registro, sizeof(registro), 1, fichero );

&registro - es la direccin donde comienza la estructura que contiene


la informacin a escribir en el fichero.
sizeof(registro) - es el nmero de bytes que se escribirn, el tamao en
bytes que ocupa la estructura.
1 - indica que slo se guardar un elemento cada vez.
fichero - el puntero FILE al fichero nombres.txt donde vamos a escribir.

fread

Esta funcin se utiliza para extraer informacin de un fichero. Su formato


es:
size_t fread(void *p_buffer, size_t tamao, size_t nmero, FILE *p_fichero);

donde p_buffer es la direccin de la variable donde se almacenarn los


datos ledos del fichero designado por p_fichero.

El valor que devuelve la funcin indica el nmero de elementos de


tamao tamao que ha conseguido leer (podemos pedirle a fread que lea 10
elementos, pero si en el fichero slo hay 6 devolver el nmero 6).

Siguiendo con el ejemplo anterior, vamos a leer los datos que habamos
introducido en nombres.txt .

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct {
char nombre[20];
char apellido[20];
char telefono[15];
} registro;

main()
{
FILE *fichero;

if ((fichero = fopen( "nombres.txt", "r" )) == NULL) {


printf( "No se puede abrir el fichero.\n" );
exit( 1 );
}

while (!feof(fichero)) {
if (fread( &registro, sizeof(registro), 1, fichero )) {
printf( "Nombre: %s\n", registro.nombre );
printf( "Apellido: %s\n", registro.apellido);
printf( "Telfono: %s\n", registro.telefono);
}
}

fclose( fichero );
}

Abrimos el fichero en modo lectura, "r". Con el bucle while aseguramos el


recorrido del fichero hasta el final (y que no vamos ms all).

La funcin fread lee 1 registro del tamao de la estructura registro. Si


realmente ha conseguido leer un registro, la funcin devolver 1, en cuyo
caso la condicin del if ser verdadera y se imprimir el registro en la
pantalla. En caso de que no queden ms registros en el
fichero, fread devolver 0 y no se mostrar nada en la pantalla.

Posicionamiento en el fichero: fseek y ftell

fseek

Esta funcin permite situarnos en la posicin deseada de un fichero


abierto. Cuando leemos un fichero existe un puntero o cursor que indica
en qu lugar del fichero nos encontramos. Cada vez que leemos datos
del fichero este puntero se desplaza. Con la funcin fseek podemos situar
este puntero en el lugar que se precise.

El formato de fseek es el siguiente:


int fseek(FILE *p_fichero, long desplazamiento, int modo);
Como siempre, p_fichero es un puntero de tipo FILE que apunta al
fichero con el que queremos trabajar.
desplazamiento es el nmero de posiciones (o bytes) que queremos
desplazar el puntero. Este desplazamiento puede ser de tres tipos,
dependiendo del valor de modo:

El puntero se desplaza desde el principio del


SEEK_SET
fichero.
El puntero se desplaza desde la posicin actual
SEEK_CUR
del fichero.
SEEK_END El puntero se desplaza desde el final del fichero.

Estas tres constantes estn definidas en el fichero <stdio.h>. Como


curiosidad, se indican a continuacin sus definiciones:

#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2

Si se produce algn error al intentar posicionar el puntero, la funcin


devuelve un valor distinto de 0. Si todo ha ido correctamente el valor
devuelto es 0.

En el siguiente ejemplo se muestra el funcionamiento de fseek. Se trata de


un programa que lee la letra que hay en la posicin que especifica el
usuario.

#include <stdio.h>
#include <stdlib.h>

main()
{
FILE *fichero;
long posicion;
int resultado;

if ((fichero = fopen( "origen.txt", "r" )) == NULL) {


printf( "No se puede abrir el fichero.\n" );
exit( 1 );
}

printf( "Qu posicin quieres leer? " );


scanf( "%li", &posicion );
resultado = fseek( fichero, posicion, SEEK_SET );
if (!resultado)
printf( "En la posicin %li est la letra %c.\n", posicion, getc(fichero) );
else
printf( "Problemas al posicionar el cursor.\n" );
fclose( fichero );
}

NOTA: la primera posicin del fichero es la 0, no la 1.

ftell

Esta funcin es complementaria a fseek. Devuelve la posicin actual


dentro del fichero.

Su formato es el siguiente:
long ftell(FILE *p_fichero);

El valor que devuelve puede ser usado por fseek para volver a la posicin
actual.

fprintf y fscanf

Estas dos funciones trabajan igual que sus equivalentes printf y scanf. La
nica diferencia es que podemos especificar el fichero sobre el que
operan (si se desea, puede ser la pantalla para fprintf o el teclado
para fscanf).

Los formatos de estas dos funciones son:


int fprintf(FILE *p_fichero, const char *formato, ...);
int fscanf(FILE *p_fichero, const char *formato, ...);

Modo de apertura de los


archivos
La funcin open recibe un parmetro opcional para indicar el modo en
que se abrir el archivo. Los tres modos de apertura que se pueden
especificar son:
Modo de slo lectura (r). En este caso no es posible realizar
modificaciones sobre el archivo, solamente leer su contenido.

Modo de slo escritura (w). En este caso el archivo es truncado


(vaciado) si existe, y se lo crea si no existe.

Modo slo escritura posicionndose al final del archivo (a). En


este caso se crea el archivo, si no existe, pero en caso de que exista
se posiciona al final, manteniendo el contenido original.

Por otro lado, en cualquiera de estos modos se puede agregar un + para


pasar a un modo lectura-escritura. El comportamiento de r+ y de w+ no es
el mismo, ya que en el primer caso se tiene el archivo completo, y en el
segundo caso se trunca el archivo, perdiendo as los datos.

NOTA Si un archivo no existe y se lo intenta abrir en modo lectura, se


generar un error; en cambio si se lo abre para escritura, Python se
encargar de crear el archivo al momento de abrirlo, ya sea
con w, a, w+ o con a+).
En caso de que no se especifique el modo, los archivos sern abiertos en
modo slo lectura (r).

ADVERTENCIA Si un archivo existente se abre en modo escritura


(w o w+), todos los datos anteriores son borrados y reemplazados por lo
que se escriba en l.

También podría gustarte