You are on page 1of 17

Archivos de acceso directo o aleatorio

La funcin fwrite transfiere a un archivo un nmero especificado de bytes empezando en una


posicin especificada de memoria. Los datos se escriben al principio de la posicin en el archivo
indicada mediante el apuntador de posicin de un archivo. La funcin fread transfiere un nmero
especificado de bytes de la posicin en el archivo, especificado por el apuntador de posicin de
archivo, a un rea en memoria empezando a partir de una direccin especificada. Por ejemplo,
para escribir un entero, en vez de especificar:

fprintf(cuentaPtr, %d, numero);

para escribir el mismo nmero de tipo int, se puede especificar:

fwrite( &numero, sizeof(int), 1, cuentaPtr);

ms adelante ese dato puede ser ledo con la funcin fread.

El primer parmetro de fprintf es la direccin de la variable a escribir en disco, el segundo el tamao


de bytes del dato que se va a escribir (devuelto por la funcin sizeof), el tercer parmetro es el
nmero de datos que se van a escribir del tamao especificado (por lo comn ser 1) y el ltimo es
el apuntador al archivo que se abri para escritura o modificacin.

Para tener datos de tamao fijo en los archivos y lo que formalmente sern registros del archivo se
crea una estructura, es decir, un nuevo tipo de dato definido por el usuario y compuesto por uno o
varios tipos de datos con sus nombres de campo respectivos.

La declaracin de un tipo struct se hace antes de la funcin main de la siguiente manera:

structnombreEstructura

tipo1 campo1;

tipo2 campo2;

tipo3 campo3;

};

Por ejemplo, para crear una estructura que permita almacenar los datos de un cliente puede
declararse de la siguiente manera:

structDatosCliente

int cuenta;

char apellido[15];

char nombre[10];

float saldo;

};
De este modo se crea una estructura de nombre DatosCliente con los campos descritos, en el
programa se podrn declarar variables de tipo DatosCliente y para acceder a cada uno de los
campos se utilizara la notacin registro.campo. La declaracin de una variable de este tipo se har:

structDatosClientemicliente;

De esta manera la variable micliente tiene los cuatro campos definidos para el tipo de estructura, y
el nombre del cliente se accede con la siguiente lnea:

micliente.nombre

El uso de una estructura y de las funciones fread, fwrite y fseek ser bsicamente la diferencia entre
programar para utilizar un archivo secuencial y un archivo de acceso directo.

Cmo crear un archivo de acceso directo:

/* Creacion de un archivo de acceso directo */

#include (stdio.h)

#include (conio.h)

structDatosCliente

int cuenta;

char apellido[15];

char nombre[10];

float saldo;

};

main( )

int i;

structDatosClienteclienteNulo = {0,"","",0.0};

FILE *cuentaPtr;

if ((cuentaPtr = fopen("cliente.dat","w")) == NULL)

printf("No se puede abrir el archivo\n");

else

/* Escritura de 100 registros en blanco*/

for (i=1; i<= 100; i++)

fwrite(&clienteNulo, sizeof(structDatosCliente),1, cuentaPtr);


fclose(cuentaPtr);

getch ( );

return 0;

Como abrir,modificar,eliminar,consultar un archivo de datos

#include <iostream.h>

#include <conio.h>

#include <stdio.h>

#include <fstream.h>

#include <iomanip.h>

#include <stdlib.h>

#include <ctype.h>

structDatos{

int control;

char nombre[40];

int edad;

chartelefono[15];

};

int *arrayCont;

char *rutaArch = {"c:test.TXT"};

char *rutaTemp = {"c:temp.txt"};

char *letrerosMenu[] = {"[1] ESCRIBIR.","[2] LEER.","[3] BUSCAR.","[4] ELIMINAR.","[5] MODIFICAR.","[6] SALIR."};

voidescribeArchivo(Datos dat,char ruta[]){

ofstream esc(ruta,ios::app);

esc <<setw(5)<<setiosflags(ios::right)<<dat.control<<" "

<<setw(40)<<setiosflags(ios::left)<<dat.nombre<<" "

<<setw(5)<<setiosflags(ios::right)<<dat.edad<<" "

<<setw(15)<<setiosflags(ios::left)<<dat.telefono<<endl;

esc.close();

Datos LeerDato(ifstream&leer){

Datos dat;

leer>>dat.control; leer.ignore(1,'n');

leer.getline(dat.nombre,40); leer.ignore(2,'n');

leer>>dat.edad; leer.ignore(1,'n');

leer.getline(dat.telefono,15); leer.ignore(2,'n');

returndat;

}
intBuscarRegistro(Datos&dat,intcont){

ifstream leer(rutaArch);

while(leer.peek()!=EOF){

dat = LeerDato(leer);

if(dat.control==cont) return 1;

leer.close();

return 0;

voidMostrar(Datosdat,intTipo){

if(Tipo == 0){

cout<<"Num. de control: "<<dat.control<<endl

<<" Nombre: "<<dat.nombre<<endl

<<" Edad: "<<dat.edad<<endl

<<" Telefono: "<<dat.telefono<<endl;

}else if(Tipo == 1){

cout<<setw(5)<<setiosflags(ios::right)<<dat.control<<" "

<<setw(40)<<setiosflags(ios::left)<<dat.nombre<<" "

<<setw(5)<<setiosflags(ios::right)<<dat.edad<<" "

<<setw(15)<<setiosflags(ios::left)<<dat.telefono<<endl;

Datos capturaDatos(intcont){

Datos dat;

dat.control = cont;

cout<<" Nombre: "; gets(dat.nombre);

cout<<" Edad: "; cin>>dat.edad;

cout<<" Telefono: "; gets(dat.telefono);

returndat;

Datos Altas(){

Datos dat;

intcont;

clrscr();

do{

cout<<"Num. de control: "; cin>>cont;

if(BuscarRegistro(dat,cont)){

cout<<"El registro ya existe..."<<endl;

Mostrar(dat,0); getch();

}
else break;

}while(1);

returncapturaDatos(cont);

voidBuscar(){

intcont;

Datosdat;

cout<<"Num. control: "; cin>>cont;

if(BuscarRegistro(dat,cont)) Mostrar(dat,0);

elsecout<<"No se encontro el registro...";

getch();

voidconsultaArchivo(){

ifstream leer(rutaArch);

clrscr();

cout<<setw(5)<<setiosflags(ios::right)<<"No."<<" "

<<setw(40)<<setiosflags(ios::left)<<"Nombre:"<<" "

<<setw(5)<<setiosflags(ios::right)<<"Edad:"<<" "

<<setw(15)<<setiosflags(ios::left)<<"Telefono:"<<endl;

while(leer.peek()!=EOF) Mostrar(LeerDato(leer),1);

leer.close();

getch();

voideliminarRegistro(){

ifstream leer(rutaArch);

Datosdat,aux;

intcont,bandEncontrado = 0;

cout<<"Num. control: "; cin>>cont;

while(leer.peek()!=EOF){

dat = LeerDato(leer);

if(dat.control==cont){

bandEncontrado = 1;

aux = dat; continue;

escribeArchivo(dat,rutaTemp);

leer.close();

if(bandEncontrado){

Mostrar(aux,0);

cout<<"seguro que deseas eliminar el registro S/N : ";


if(toupper(getch())== 'S'){

remove(rutaArch);

rename(rutaTemp,rutaArch); return;

}else{ cout<<"n accioncancelada..."; remove(rutaTemp);}

}elsecout<<"No se encontro el registro...";

getch();

voidmodificarRegistro(){

ifstream leer(rutaArch);

Datosdat;

intcont;

cout<<"Num. control: "; cin>>cont;

if(BuscarRegistro(dat,cont)){

Mostrar(dat,0);

while(leer.peek()!=EOF){

dat = LeerDato(leer);

if(dat.control==cont) escribeArchivo(capturaDatos(cont),rutaTemp);

elseescribeArchivo(dat,rutaTemp);

leer.close();

cout<<"seguroquedeseasmodificar el registro S/N : ";

if(toupper(getch())== 'S'){

remove(rutaArch);

rename(rutaTemp,rutaArch); return;

}else{ cout<<"n accioncancelada..."; remove(rutaTemp);}

}elsecout<<"No se encontro el registro...";

getch();

voidburbujaMejorada(inttotalReg){

for(int x=0; x<totalReg-1; x++)

for(int y=0; y<(totalReg-x)-1; y++)

if(arrayCont[y]>arrayCont[y+1]){

intaux = arrayCont[y];

arrayCont[y] = arrayCont[y+1];

arrayCont[y+1] = aux;

voidordenarRegistros(){

ifstream leer(rutaArch);

Datosdat;
leer.seekg(0L,ios::end);

int x = 0,totalReg = leer.tellg()/70;

leer.seekg(0L,ios::beg);

arrayCont = new int[totalReg];

while(leer.peek()!=EOF){

dat = LeerDato(leer);

arrayCont[x++] = dat.control;

burbujaMejorada(totalReg);

for(x=0; x<totalReg; x++) if(BuscarRegistro(dat,arrayCont[x])) escribeArchivo(dat,rutaTemp);

leer.close();

remove(rutaArch);

rename(rutaTemp,rutaArch);

int main(){

textmode(C80);

do{

clrscr();

for(int men = 0; men < 6; men++) cout<<letrerosMenu[men]<<endl;

switch(getch()){

case '1': escribeArchivo(Altas(),rutaArch); ordenarRegistros(); break;

case '2': consultaArchivo(); break;

case '3': Buscar(); break;

case '4': eliminarRegistro(); break;

case '5': modificarRegistro(); break;

case '6': exit(0);

}while(1);

Para qu sirve la funcin strcat en C?


En lenguaje C, no existe el operador concatenacin (+), que s existe en otros lenguajes. Sin embargo, para concatenar
cadenas, se puede utilizar la funcin strcat, que est disponible en la biblioteca estndar de C. La sintaxis de una
llamada a strcat es:

strcat( <cadena_destino>, <cadena_fuente> )

La funcin strcat aade el contenido de la <cadena_fuente> a la <cadena_destino>.

Ejemplo: Dadas las siguientes declaraciones de arrays de caracteres:


En pseudocdigo:

cadena nombre = "Ana", apellido = "Luz"

En lenguaje C:

char nombre[8] = "Ana", apellido[4] = "Luz";

es posible escribir la expresin:

En pseudocdigo:

nombre + apellido

En lenguaje C:

strcat( nombre, apellido )

Observe el efecto que tiene, en la memoria de la computadora, la ejecucin de la funcin strcat. El contenido del
array apellido se concatena (aade) al array nombre.

La declaracin de la funcin strcat se encuentra en el archivo de


cabecera string.h. Por tanto, para poder usar dicha funcin en un programa, hay
que escribir:

#include<string.h>
LIBRERIAS DE DEV C++

<assert.h> Contiene la macro assert (asercin), utilizada para detectar errores lgicos y otros tipos
de fallos en la depuracin de un programa.

< complex.h> Conjunto de funciones para manipular nmeros complejos (nuevo en C99).

< ctype.h> Contiene funciones para clasificar caracteres segn sus tipos o para convertir entre
maysculas y minsculas independientemente del conjunto de caracteres (tpicamente ASCII o
alguna de sus extensiones).

< errno.h> Para testar los cdigos de error devueltos por las funciones de biblioteca.

< fenv.h> Para controlar entornos en coma flotante (nuevo en C99).

< float.h> Contiene la definicin de constantes que especifican ciertas propiedades de la biblioteca
de coma flotante, como la diferencia mnima entre dos nmeros en coma flotante (_EPSOLON), el
nmero mximo de dgitos de precisin (_DIG), o el rango de valores que se pueden representar
(_MIN, _MAX).

< inttypes.h> Para operaciones de conversin con precisin entre tipos enteros (nuevo en C99).

< iso646.h> Para utilizar los conjuntos de caracteres ISO 646 (nuevo en NA1).

< limits.h> Contiene la definicin de constantes que especifican ciertas propiedades de los tipos
enteros, como rango de valores que se pueden representar (_MIN, _MAX).

< locale.h> Para la funcin setlocale() y las constantes relacionadas. Se utiliza para seleccionar el
entorno local apropiado (configuracin regional).

< math.h> Contiene las funciones matemticas comunes.

< setjmp.h> Declara las macros setjmp y longjmp para proporcionar saltos de flujo de control de
programa no locales.

< signal.h> Para controlar algunas situaciones excepcionales como la divisin por cero.

< stdarg.h> posibilita el acceso a una cantidad variable de argumentos pasados a una funcin.

< stdbool.h> Para el tipo booleano (nuevo en C99).

< stdint.h> Para definir varios tipos enteros (nuevo en C99).

< stddef.h> Para definir varios tipos de macros de utilidad.

< stdio.h> Proporciona el ncleo de las capacidades de entrada/salida del lenguaje C (incluye la
venerable funcin printf).

< stdlib.h> Para realizar ciertas operaciones como conversin de tipos, generacin de nmeros
pseudo-aleatorios, gestin de memoria dinmica, control de procesos, funciones de entorno, de
sealizacin (??), de ordenacin y bsqueda.
< string.h> Para manipulacin de cadenas de caracteres.

< tgmath.h> Contiene funcionalidades matemticas de tipo genrico (type-generic) (nuevo en


C99).

< time.h> Para tratamiento y conversin entre formatos de fecha y hora.

< wchar.h> Para manipular flujos de datos anchos y varias clases de cadenas de caracteres anchos
(2 o ms bytes por carcter), necesario para soportar caracteres de diferentes idiomas (nuevo en
NA1).

< wctype.h> Para clasificar caracteres anchos (nuevo en NA1).

Fstream: Permite la manipulacin de archivos desde el programador, tanto leer como escribir en
ellos.

Iosfud: Contienen declaraciones adelantadas de todas las plantillas de flujo y sus typedets estndar.
Por ejemplo: Ostream

Iostream:

List: Parte de la STL relativa a los contenedores tipo list, lista doblemente enlazada.

Math: contiene los prototipos de las funciones, otras definiciones para el uso y manipulacin de
funciones matemticas.

Memory: utilidades relativas a la gestin de memoria incluyendo asignadores y punteros inteligentes.

New: Manejo de memoria dinmica

Numeric: Parte de la librera numrica de la STL relativa a operaciones numricas.

Ostream: Algoritmos estndar para los flujos de salida

Queve: Parte de la STL relativa a contenedores tipoqueve (Colas de Objeto)

Studio: Contiene los prototipos de las funciones macros, para utilidades de uso general.

String: Parte de la STL relativa a contenedores tipo string, una generalizacin de las cadenas
alfanumricas para albergar cadenas de objetos, pues eliminan muchas de las dificultades que
generan las char.

Typcinto: Mecanismo de identificacin de tipo en tiempo de ejecucin.

Vector: Parted e la STL relativa a los contenedores tipo vector, una generacin de las matrices
unidimensionales.

COMO HACER ESTRUCTUAS SE GUARDA EN ARCHIVOS


1.2. Estructuras (struct)

Supongamos que tenemos la siguiente estructura para cada registro de libro:

--------------------------------------------------

ISBN | TITULO | AUTOR |ANIO EDICION | EDITORIAL

--------------------------------------------------

Lo primero es determinar el tipo de dato de cada elemento de la estructura, cada elemento se


denomina campo, en el ejemplo hay 5 campos.

2 CAPITULO 1. MANIPULACION DE ARCHIVOS ESTRUCTURADOS

Figura 1.1: Vista lgica de un archivo de registros de libros.

ISBN: un entero

TITULO: cadena de 20

AUTOR: cadena de 20

ANIO EDICION: entero

EDITORIAL: cadena de 20

La implementacin en C o C++ es como sigue:

typedef struct Libro

int ISBN;

char titulo[20];

char autor[20];

int anio;

char editorial[20];

}TLibro;

donde TLibro se utiliza como un nuevo tipo de dato que representa un tipo para cada libro,
entonces un libro en particular se puede definir como:

LIBRO miLibro; y para acceder a cada uno de sus campos utilizaremos el operador punto (.), por
ejemplo:
miLibro.ISBN=2344;

miLibro.titulo="C y C++";

miLibro.autor="D. Ritchie";

miLibro.anio=1999;

miLibro.editorial="Alfa";

Ahora, utilizaremos un archivo para guardar cada registro, esto lo veremos

en la siguiente seccion.

1.3. OPERACIONES CON ARCHIVOS 3

1.3. Operaciones con archivos

Para manipular un archivo utilizaremos el tipo FILE (en realidad crearemos un puntero de tipo FILE) y
usaremos las siguientes funciones de stdlib.h.

fopen: Para abrir un archivo y asociarlo con un puntero de tipo FILE. La sintaxis es como sigue:

FILE *fopen(char *nombre, char *modo) donde nombre es el nombre del archivo, en el que se
puede incluir la ruta y modo indica la forma en que puede usarse el archivo: w Para crear un
archivo. r Para leer un archivo. a Para aadir datos al archivo.

Ejemplo:

FILE *f = fopen("libros.txt","r");

fread: Lee datos del archivo y los pasa a la memoria principal.

fread(void *puntero, size_t tamanyo, size_t nmemb, FILE *f) donde puntero indica el espacio de
memoria en dnde se almacenarn los datos, tamanyo es la cantidad de bytes a leer, nmemb es la
cantidad de veces que se leera (asumiremos igual a 1), y f representa el archivo.

fwrite: Lee datos de la memoria principal y los pasa al archivo.

fwrite(void *puntero, size_t tamanyo, size_t nmemb, FILE *f) donde puntero indica el espacio de
memoria desde dnde se leern los datos, tamao es la cantidad de bytes a escribir, nmemb es la
cantidad de veces que se escribirn (asumiremos igual a 1), y f representa el archivo.

fseek: Permite ubicarnos en cualquier posicion del archivo para actualizar datos.

int fseek(FILE *f, long int desplazamiento, int origen);

La funcin fseek activa el indicador de posicin de ficheros de f y los desplaza seun el parmetro
desplazamiento donde la posicin inicial es origen. Se puede utilizar las constantes SEEK SET para
indicar como origen el inicio, SEEK CUR en caso de que origen sea la posicin actual y SEEK END si es
el final. Frecuentemente desplazamiento es un valor obtenido mediante una llamada a la funcin
ftell. Por ejemplo, si se tiene la posicin de un registro X, entonces en cualquier momento podemos
regresar a ubicarnos en ese registro y actualizar sus datos. ftell: La funcin ftell obtiene el valor actual
del indicador de posicin de fichero para un determinado archivo. long int ftell(FILE *f);

4 CAPITULO 1. MANIPULACION DE ARCHIVOS ESTRUCTURADOS

1.4. Implementacion de las operaciones

Siguiendo con nuestra poltica de implementar un programa modularmente, crearemos dos


mdulos, uno para guardar un registro y otro para reportar todos los registros del archivo.

GUARDAR

void guardarLibro(TLibro L, FILE *f)

fwrite(&L,sizeof(TLibro),1,f);

REPORTAR

void reportarLibro(char *file)

FILE *f=fopen(file,"r");

TLibro L;

if (f!=NULL)

fread(&L,sizeof(TLibro),1,f);

while(!feof(f))

imprimir(L);

fread(&L,sizeof(TLibro),1,f);

else

{
printf( "Error al abrir el archivo \n" );

exit(1);

fclose(f);

En el mdulo anterior usamos la funcin feof() para determinar si ya se ha ledo el final del archivo.
Adems usamos el mdulo imprimir para mostrar los datos:

Void imprimir(TLibro L)

printf("ISBN : %s \n", L.ISBN);

printf("Titulo: %s \n", L.titulo);

printf("Anio : %s \n", L.autor);

printf("Anio : %d \n", L.anio);

printf("Anio : %s \n", L.editorial);

LIBRERA DE STRING.H

String.h es un archivo de la Biblioteca estndar del lenguaje de programacin C que contiene la


definicin de macros, constantes, funciones y tipos y algunas operaciones de manipulacin de
memoria.

Las funciones declaradas en string.h se han hecho muy populares, por lo que estn garantizadas
para cualquier plataforma que soporte C. Sin embargo, existen algunos problemas de seguridad
con estas funciones, como el desbordamiento de buffer (buffer overflow), que hacen que algunos
programadores prefieran opciones ms seguras frente a la portabilidad que estas funciones
ofrecen. Adems, las funciones para cadenas de caracteres slo trabajan con conjuntos de
caracteres ASCII o extensiones ASCII compatibles.

MANEJO DE CADENAS

Las cadenas de caracteres (string) son arreglos que se componen de caracteres alfanumricos. El
final de una cadena se indica con un caracter especial, ste es un byte compuesto por 8 ceros
binarios, es decir

0x00.

void main() {
char cad[10];

El tamao de la cadena debe ser lo suficientemente grande para contener dicho caracter
inclusive. Una cadena declarada como cad[10], podr contener como mximo 9 caracteres, el
ltimo ser ocupado por

0x00.

El archivo de cabecera string.h string.h string.h proporciona una serie de funciones que permiten el
manejo de cadenas de caracteres. No existen operadores que permitan comparar cadenas o
copiar una cadena en otra, por lo que se debe hacer uso de las funciones definidas en string.h
string.h.

FUNCION DESCRIPCION
strcpy Copia cadena en otra cadena
strcmp Compara dos cadenas
strlen Determina el largo de una cadena
strncpy Copia n caracteres de una cadena a
otra

La funcin strcpy es una contraccin de la operacin string c stropy. El uso de estas funciones
requiere de un buen manejo de punteros. Por otro lado, dado que la cadena se define como tipo
char, es importante hacer la diferencia por ejemplo entre 'A' y "A", el primero es el caracter A que se
codifica en un byte (0x41) y el segundo elemento es una cadena que contiene un caracter A y
ocupa dos bytes (0x41, 0x00), el carcter y el fin de cadena. Dado que el final de la cadena
contiene el carcter 0x00, si se quiere borrar la cadena, se puede asignar al primer elemento de la
cadena dicho carcter cad[0]=0x00.

Variantes del uso de cadenas

Debido a que el uso de punteros es fundamental es importante establecer su uso en el manejo de


cadenas. En las implementaciones de C la variable puntero se especifica mediante el tipo
*identificador luego se tiene y la asignacin de la direccin se hace mediante el operador &. De
esta forma se tiene

#include <string.h>

void main()

char cad[10], buf[10]; /* cadenas de caracteres */

char *p; /* puntero a char */

p=&cad[0]; /* Asigna la direccion del elemento 0 */


p=cad; /* Idem */

strcpy(cad,HOLA); /* son lo mismo */

strcpy(cad[0],HOLA);

strcpy(&cad[0],HOLA);

strcpy(p,HOLA); /* Idem debido a que el argumento de strcpy es un puntero */

strcpy(buf[0],p); /* */

void main()

char cad[10], buf[10]; /* cadenas de caracteres */

strcpy(cad,HOLA); /* inicializando cad */

strcpy(buf[0],cad[2]); /* copiando parte de cad en buf */

void main()

char cad[10]={HOLA}; /* Declarando e iniicalizando */

strcpy(buf,cad); /* copiando de cad en buf */

NUMEROS ALEATORIOS

Si quieres generar un numero aleatorio debers utilizar srand() y rand(). Para hacer uso de ellas
debes incluir stdlib.h

El uso consiste en llamar una solo vez a la funcin srand(semilla) donde semilla es un numero que vos
quieras. Luego cada vez que llames a rand() obtendrs el numero aleatorio.

Por ejemplo printf("el numero es %i", rand() );

Nota importante: hazte un programa que cree un numero aleatorio y luego lo imprima 20 veces.
Observaras que el nmero escrito es siempre el mismo. Esto se debe a que srand genera un numero
aleatorio a partir de la semilla y siempre generara el mismo nmero si tiene la misma semilla (como
ves no es muy aleatorio) Para resolver esto: en vez de srand(semilla) donde semilla es un numero
constante pone srand(time(0))
En otras palabras la semilla ya no ser un numero constante sino un nmero que va variando con el
tiempo (justamente la funcin time(0) devuelve la hora)

para incluir esta funcin debes incluir time.h