| INSTITUTO POLITÉCNICO NACIONAL ESCUELA SUPERIOR DE CÓMPUTO |

Introducción | Contenido | Bibliografía

Introducción
Contenido
UNIDAD I
UNIDAD II
UNIDAD III
UNIDAD IV
UNIDAD V
UNIDAD VI
UNIDAD VII Introducción 7.1 Diseño, implementación y administración de la tabla de símbolos 7.2 Implantación de bloques y tipos de datos 7.3 Especificación de alcance de variables

7.4 Funciones y procedimientos

7.5 Registros de activación

7.6 Paso de parámetros

7.7 Llamada por valor

7.8 Llamada por referencia

UNIDAD VIII
UNIDAD IX
PROBLEMARIO
Bibliografía

7.2 Implantación de bloques y tipos de datos

> En el bloque de datos se depositan valores a los que deba acceder su máquina o instalación. Contrariamente al bloque lógico, programado con uno de los lenguajes de programación (KOP, FUP o AWL), el bloque de datos sólo contiene la parte de declaración de variables. No requiere un área de instrucciones y, por tanto, tampoco la programación de segmentos. Tras abrir un bloque de datos, éste se puede visualizar en la vista "Declaración" o "Datos". Para conmutar de una vista a otra, elija los comandos de menú Ver >

> Declaración y Ver >Datos, respectivamente.

> Lectura y escritura de bloques de datos.

> ¿Qué sucede cuando los tipos de datos que escribimos y leemos en un archivo binario no son caracteres o cadenas de caracteres?

> Para realizar esta tarea, tenemos a nuestra disposición las funciones read y write que trabajan sobre descriptores de archivos.

> Write

> La función write escribe una zona de memoria a un archivo identificado por su correspondiente descriptor.

> descriptor.write(puntero_a_memoria, tamaño_memoria)

> Como se puede apreciar, esta función trabaja con un puntero a la zona de memoria. Esto quiere decir que, ante variables definidas de forma estática, se le ha de pasar su dirección usando el operador &.

> Además, el puntero que acepta la función como argumento es de tipo char *, por lo que habrá que convertir cualquier puntero de otro tipo (devuelto por &) a aquel. Esta operación es muy sencilla, y se hace mediante una conversión o casting:

> char * puntero_a_byte = (char *) &variable_de_un tipo_no_char;

> Tomar en cuenta el (char *) delante de la dirección de la variable. A continuación se muestra un programa 1 completo con escritura en archivo de varios tipos de datos.

> #include <fstream>
> #include <iostream>
> using namespace std;
> struct Point{
> float x;
> float y;
> };
> typedef int TVector[2];
> int main(){
> int i; //una variable estatica tipo entero
> Point punto; //una variable estructura estatica, tipo Point
> TVector array; //un array de enteros
> int * p_i = new int; // un puntero a un entero obtenido a traves del Heap
> fstream fd;
> fd.open("ejemplo.dat", ios::out | ios::binary);
> //escritura variable estatica de tipo primitivo
> i=1;
> fd.write((char *)&i,sizeof(int));
> //escritura variable estatica de tipo estructura
> punto.x = 2.0; punto.y = 3.0;
> fd.write((char *)&punto,sizeof(Point));
> //escritura de un array. OJO, NO SE PONE &
> array[0] = 4 ; array[1] = 5;
> fd.write((char *)array,sizeof(TVector));
> //escritura de variable dinamica (logicamente tampoco se usa & sobre un
> // puntero)
> *p_i = 6;
> fd.write((char *)p_i,sizeof(int));
> fd.close();
> system("pause");
> return 0;
> }

> Ejemplo de escritura de bloques de bytes en archivos binarios. Mucho cuidado. Si nos fijamos, hay algo distinto en el caso de usar arrays: no he utilizado el operador & para extraer su dirección. La solución a este enigma también es muy sencilla. En C y C++, por norma, el nombre del array indica al compilador la dirección de memoria de su primer elemento. Es decir, el nombre de un array es un puntero:

> read

> La función read, de forma equivalente, lee de un archivo y deposita el contenido en una zona de memoria concreta.

> descriptor.read(puntero_a_memoria, tamaño_a_leer)

> Tal y como veíamos para la función write, de nuevo se utiliza un puntero aquí. Todo lo explicado con anterioridad es válido en este caso. Y recordad que si utilizáis variables de tipo puntero, debe existir una zona de memoria reservada previamente, que pueda almacenar los datos provenientes del archivo.

> Se muestra un programa 2 completo dedicado a lectura en bloque de los datos almacenados en un archivo mediante el ejemplo anterior (programa 1).

> #include <fstream>
> #include <iostream>
> using namespace std;
> struct Point{
> float x;
> float y;
> };
> typedef int TVector[2];
> int main(){
> int r;
> Point rpunto;
> TVector rarray;
> int * p_r = new int; //Ojo! hay que suministrar memoria para almacenar
> // el resultado devuelto por la funcion "read"
> fstream fd;
> fd.open("ejemplo.dat", ios::in | ios::binary);
> //Hay que leer EN ORDEN (ver ejemplo en programa 1)
> fd.read((char *)&r,sizeof(int));
> cout << r << endl;
> fd.read((char *)&rpunto,sizeof(Point));
> cout << rpunto.x << " " << rpunto.y << endl;
> fd.read((char *)rarray,sizeof(TVector)); //array: OJO, NO SE PONE &
> cout << rarray[0] << " " << rarray[1] << endl;
> fd.read((char *)p_r,sizeof(int));
> cout << *p_r << endl;
> fd.close();
> system("pause");
> return 0;
> }

> Ejemplo de lectura de bloques de bytes desde archivos binarios.

> Aunque el párrafo anterior da a entender que se puede declarar una variable en cualquier momento, el estándar ANSI C obliga a realizar las declaraciones al principio de cada bloque. En el caso se variables globales la sintaxis es más flexible, para poder utilizar el "Scope" en nuestro provecho.

> main()
> {
> int numero;

> numero = 20;
> }

> Podemos también declarar variables fuera del bloque main( ). Estas variables se conocen como variables globales y cualquier función puede acceder a ellas, como sólo tenemos una función (main) en este caso nos daría igual declarar las variables dentro o fuera de main.

> Atrás Siguiente

##### Introducción / Contenido / Unidad I / Unidad II / Unidad III / Unidad IV / Unidad V / Unidad VI / Unidad VII / Unidad VIII / Unidad IX / Problemario / Bibliografía

##### Inicio

##### Créditos

José Sánchez Juárez, Andrés Ortigoza Campos, Fabiola Ocampo Botello