martes, 27 de mayo de 2014

ESTRUCTURAS (Struct) & Archivos

Un registro o estructura es un tipo de dato estructurado y definido por el usuario que permite almacenar datos de diferente tipo en una sola variable; dichos datos pueden ser simples (caracteres, números enteros o de coma flotante etc) o compuestos  (vectores, estructuras, listas, etc). A los datos del registro se les denomina campos, elementos o miembros. Una estructura esta formada por variables que tienen relación entre si. También se llaman registros a los grupos de datos en la terminología de las bases de datos. 

Conceptos Básicos

  • Campo. Permite representar un atributo de alguna entidad (Edad, Nombre, Semestre, Teléfono, Carrera) 
  • Registro. Es un conjunto de campos que forman los atributos de cierta entidad (Alumno) 
  • Archivo. Es un conjunto de registros almacenados en un dispositivo externo  


Definición de una estructura 

Una estructura define una plantilla con la que posteriormente se puede declarar una variable. Una de las características de las estructuras es que hay que definirías antes de usarlas  en la declaración de las variables. En la definición no se declara ni reservando memoria para ninguna variable, solo se construye una estructura con determinadas características, para después poder declarar una variable de ese tipo.  
Para crear una estructura, primero comenzamos por definir el tipo de estructura, para ello se procede de manera parecida a la definición de una variable, con algunas modificaciones; en lenguaje C para definir una estructura, se utiliza la palabra reservada struct, normalmente seguida por un nombre y la apertura de las llaves; después se define el tipo y nombre para cada uno de los campos. Se permite cualquier definición de tipo habitual, incluso punteros y otras estructuras. Cada definición de campo acabara con un punto y coma. Por ultimo se cierran las llaves. Si hay campos del mismo tipo, se pueden declarar en la misma linea, separados por comas. 
A continuación se muestra un ejemplo de definición de una estructura: 

struct  identificador_estructura 
          tipo_dato_1  campo_1, campo_2 
          tipo_dato_2  campo_3, campo_4 
          tipo_dato_3  campo_5, campo_6 
}

Se ha definido el tipo de dato, el nombre de la estructura, pero aun no hay ninguna  variable declarada con este nuevo tipo. En lenguaje C es necesario incluir un carácter (;) después de cerrar las llaves. Para definir una variable de tipo registro se declara de la misma forma que una variable: 

identificador_estructura identificador_variable; 

struct  info
          char campo_1, campo_2 
          int    campo_3, campo_4 
          float campo_5, campo_6 
}

main ( )
{
       info estudiante; 
}

donde: 
  • info es el nombre del registro 
  • estudiante es el nombre de la variable
También es posible definir variables estructuras sin tipo especifico, para ello basta con omitir el identificador del tipo estructura en la definición de la estructura, dando solo el identificador de la variable estructura. De este modo la nueva variable va asociada al tipo creado. En ese caso, quizá no sea necesario dar un nombre a la estructura, con la siguiente sintaxis: 

struct  identificador_estructura 
          tipo_dato_1  campo_1, campo_2 
          tipo_dato_2  campo_3, campo_4 
          tipo_dato_3  campo_5, campo_6 
} nombre_variable; 

Quedando así definida la variable nombre_variable, de tipo de dato struct. En este caso, no se pueden crear nuevas variables de ese tipo, por lo que no se recomienda usar este tipo de declaraciones. 


Tipos de datos definidos por el usuario "typedef"

En el lenguaje C podemos dar un nuevo nombre a tipos de datos  que ya existen, a  fin de que estos sean mas afines con aquello que representan y haciendo que el código fuente sea mas claro. Una vez que se ha creado un tipo de dato y un nombre para hacer referencia a el, podemos usar ese identificador en la declaración de variables, como cualquier tipo de dato estándar en C. Para definir un tipo de dato se utiliza la palabra reservada define_tipo "typedef" con el siguiente formato:  

typedef       ident_tipo     ident_tipo_nuevo; 

Ejemplos: 
  • typedef   float kg 
  • typedef   float mts 
La palabra reservada typedef nos sirve para crear "sinónimos" de tipos de datos predefinidos. Una manera fácil de definir estructuras en Lenguaje C es mediante la combinación de la palabra struct y la palabra typedef . Una forma de definición de una estructura es la siguiente: 

 typedef struct 
{
            tipo_dato_1  campo_1, campo_2 
          tipo_dato_2  campo_3, campo_4 
          tipo_dato_3  campo_5, campo_6 
} nombre_variable


Asignación de valores a los campos de una estructura

Una vez declarada una estructura, se pueden asignar valores iniciales a sus campos. Para ello se dan los valores iniciales escribiendo entre llaves los valores de sus campos en el mismo orden en que se declararon estos, al igual que hacemos con los arreglos. Pero ahora cada dato puede tener un tipo diferente. 
La sintaxis es la siguiente: 

struct fecha 
{
       int dia; 
       char mes [10];
       int año;  
} ; 

struct fecha fec_ant = { 15, "Abril", 2008 }; 

Acceso a los campos de un registro o estructura (struct)

Para acceder a cada campo de una estructura se usa el operador  punto ".", precedido por el nombre de la estructura y seguido del nombre del campo. Dicho operador, que sirve para representar la dependencia de cada uno de los campos con su estructura, es necesario, ya que al declararse varias estructuras del mismo tipo, debemos distinguir los correspondientes campos de unas y otras. Cada campo de una estructura designado mediante este operador se comporta como si se tratase de una variable del mismo tipo que el campo. Podemos realizar todas las operaciones habituales de las variables.  

identificador_variable.nombre_ campo

El tratamiento de cada uno de estos campos depende de su tipo (si es un entero lo asignaremos y trataremos como entero, si un vector, como un vector, si es string como string)
Ejemplo: 

struct persona
{
     long edad; 
     char nombre [40];
      char  sexo ; 
}
struct Persona usuario;  


struct fecha 
{
     int dia; 
     char mes [10];
      int año ; 
} fec_act = { 10, "Mayo", 1990} ; 

strcpy (usuario.nomb, "Hugo Jara"); 
usuario.edad = 20 ; 
usuario.sexo = M ; 


Archivos 

En el Lenguaje de programación C, un archivo puede ser cualquier cosa, desde un archivo de disco a una terminal o una impresora. Se asocia una secuencia con un archivo especifico realizando una operación de apertura. Una vez que el archivo esta abierto, la información puede ser intercambiada entre este y el programa. 
No todos los archivos tienen ñas misma posibilidades. Por ejemplo, un archivo de disco permite el acceso directo mientras que un teclado no. Esto saca a la luz un punto importante sobre el sistema E/S de C: todas las secuencias son iguales, pero no todos los archivos lo son. 
Si el archivo permite el acceso directo, abrir ese archivo también inicia el indicador de posición del archivo al comienzo del mismo. Según se leen o se escriben los caracteres en el archivo, el indicador de posición se incrementa asegurando la progresión sobre el mismo. 
Cada secuencia que se asocia con un archivo tiene una estructura de control del tipo FILE. Esta estructura se define en el archivo de cabecera STDIO.H (directivas al pre-procesador)


Elementos básicos del sistema de archivos 

El sistema de archivos ANSI esta compuesto por varias funciones interrelacionadas. Las mas comunes se encuentran en la siguiente tabla. 


              Nombre                                          Función 
           fopen ( )                                             Abre un  archivo 
           fclose ( )                                             Cierra un archivo 
           putc    ( )                                             Escribe un carácter en un archivo 
           fputc   ( )                                             Escribe un carácter en un archivo
           getc    ( )                                             Lee un carácter de un archivo 
           fprintf ( )                                             Tiene la misma función que printf ( ) en sintaxis                                                                             normal
           fscanf ( )                                             Misma función que scanf ( ) en sintaxis normal  
           ferror ( )                                             Devuelve el valor de cierto si se produce un error 
           rewind ( )                                           Coloca el localizador de posición del archivo al inicio                                                                           de este
           fflush ( )                                              Vacia un archivo
     

El puntero de un archivo 

El puntero de un archivo es el hilo común que unifica el sistema entrada/salida con buffer. Un puntero a un archivo es un puntero a una información que define varias cosas sobre el, incluyendo el nombre, el estado y la posición actual del archivo. En esencia, el puntero a un archivo identifica un archivo en disco especifico y utiliza la secuencia asociada para dirigir el funcionamiento de las funciones entrada/salida con el buffer. Es una variable de tipo puntero al tipo FILE. Un programa necesita utilizar punteros a archivos para leer o escribir sobre los mismos. La sintaxis para obtener una variable de este tipo es la siguiente: 

FILE *fp ; 

Apertura de un archivo 

La función fopen ( ) abre una secuencia para que pueda ser utilizada y la asocia a un archivo. Después, devuelve el puntero al archivo asociado con ese archivo. A menudo, el archivo es un archivo en disco. La función fopen ( ) tiene la siguiente sintaxis: 
    FILE *fopen (const char nombre_del_archivo  modo ) ; 
donde nombre_del_archivo es un puntero a una cadena de caracteres que representan un nombre valido del archivo y puede incluir una especificación de directorio. modo, determina como debe ser abierto el archivo. 
Como se muestra en la siguiente tabla, un archivo puede abrirse en modo texto o en modo binario.  

Modo                                Significado  

r                                        Abre un archivo de texto para lectura 
w                                       Crea un archivo de texto para escritura
a                                        Abre un archivo de texto para añadir 
rb                                      Abre un archivo binario para lectura 
wb                                    Crea un archivo binario para escritura
ab                                     Abre un archivo binario para añadir 
r+                                     Abre un archivo de texto para lectura/escritura 
w+                                    Crea un archivo de texto para lectura/escritura 
a+                                     Añade o crea un archivo de texto para lectura/escritura 
r+b                                   Abre un archivo binario para lectura/escritura
w+b                                 Crea un archivo binario para lectura/escritura
a+b                                  Añadir en un archivo binario en modo lectura/escritura

Si se quiere abrir un archivo llamado PRUEBA para escritura, puede escribir : 

 FILE *fp; 
 if  ( ( fp = fopen ("prueba", "w") ) == NULL) 
{
      printf ("No se puede abrir el archivo"); 

La instrucción NULL se define como \0. Si se abre un archivo utilizando este método, 
fopen( ) detecta cualquier erro al abrir el archivo, como puede ocurrir cuando el disco esta protegido contra escritura. Se utiliza el valor nulo para indicar un fallo porque ningún puntero a archivo puede tomar este valor. 
Si se utiliza fopen ( ) para abrir un archivo para escritura, cualquier archivo que ya existiese con ese nombre se borra y se crea uno nuevo y si no existe, se crea uno nuevo. Si se quiere añadir información al final del archivo, se debe utilizar el modo "a". Solo se pueden abrir archivos que ya existen para lectura, si no es así, se muestra un error. Finalmente, si se abre un archivo para realizar operaciones de lectura/escritura, si ya existía no sera borrado. 
El estándar ANSI especifica que pueden ser abiertos, por lo menos, ocho archivos en cualquier momento. Sin embargo, la mayoría de los compiladores y C permiten un numero mayor. 


Cierre de un archivo

La función fclose( ) cierra una secuencia que fue abierta mediante una llamada a fopen ( ). Escribe toda la información que todavía se encuentre en el buffer del disco y realiza un cierre formal del archivo a nivel del sistema operativo. Un error en el cierre de una secuencia puede generar todo tipo de problemas, incluyendo la perdida de datos, destrucción de archivos  y posibles errores intermitentes en el programa. Un fclose ( ) también libera el bloque de control de archivo asociado con la secuencia, dejándolo libre para su reutilizacion . En la mayoría de los casos, existe un limite del sistema operativo al numero de archivos abiertos que pueden haber simultáneamente, por lo que es necesario cerrar los archivos que ya no se estén utilizando. 

La función fclose ( )    tiene este prototipo 

int fclose (FILE *pf)          

donde pf es el puntero al archivo devuelto por la llamada fopen ( ). Si se devuelve un valor cero significa que la operación de cierre ha tenido éxito. Se puede utilizar la función estándar ferror(  ) para determinar y notificar cualquier problema. 
Generalmente, fclose ( ) solo falla cuando un disco se ha retirado antes de tiempo del dispositivo o cuando no queda espacio libre en el disco.




Escribir un registro en un archivo binario


Un registro se escribe en un archivo binario con la función fwrite ( ). 

fwrite(&buffer, bytes_buffer, n, arch); 
donde: 
  • &buffer es una estructura, 
  • bytes_buffer es el tamaño en bytes de la estructura, 
  • n es el número de estructuras a escribir en el archivo 
  • arch es el nombre lógico del archivo. 

Leer un registro de un archivo binario

Un registro se lee de un archivo binario con la función fread ( ).  

fread(&buffer, bytes_buffer, n, arch); 
donde: 
  • &buffer es una estructura, 
  • bytes_buffer es el tamaño en bytes de la estructura, 
  • n es el número de estructuras a escribir en el archivo 
  •  arch es el nombre lógico del archivo.

Tamaño de una estructura


La función sizeof(), regresa el número de bytes que ocupa una  estructura. 
int x; 
x= sizeof(tipo_estructura)

No hay comentarios:

Publicar un comentario