UNIVERSIDAD INCA GARCILASO DE LA VEGA FACULTAD DE INGENIERIA DE SISTEM AS, COMPUTO Y TELECOMUNICACIONES
ASIGNATURA TEMA PROFESOR ALUMNO CODIGO FECHA CICLO TURNO SEMESTRE
1.
Estructura de Información Filas Secuenciales Carlos A. Ruiz De La Cruz Melo
2010-II
OBJETIVOS
Que el estudiante: •
•
2.
Aplique en los algoritmos los conceptos básicos de este TAD, aprendiendo a utilizar de forma adecuada y eficiente la notación y la semántica de sus operaciones o acciones elementales elementales a las cuales llamaremos “primitivas de acceso”. Implemente los algoritmos en C++, poniendo especial énfasis en un tipo de archivo denominado archivos binarios. INTRODUCCION TEORICA
Las estructuras de datos se dividen en dos grupos Estructuras de datos lineales • • • • •
Filas Secuénciales. Arreglos (Vectores, búsqueda y ordenamiento) Listas enlazadas (Simples, doble, circular) Pilas Colas
Estructuras de datos no lineales Árboles ( General, binario, balanceado, B, B+) Grafos. • •
Fila Secuencial
La Fila secuencial es una estructura de datos lineal usada principalmente para almacenamiento secundario(almacenamiento en disco duro, disquete, cinta, usb). Una Fila secuencial puede almacenar tipos de datos simples y estructurados(TAD). Características de una fila secuencial •
•
Para acceder a un elemento de la fila secuencial es preciso recorrer los elementos anteriores a el. La fila es secuencial uno después de otro. Después del ultimo elemento se encuentra la marca de fin de fila secuencial. Existe al final una marca de fin.
Primitivas básicas Inicio(F) Leer( F, V) Escribir(F, V) Ultimo( F) Cerrar(F)
Posiciona la fila F antes del primer elemento Lee el elemento de la fila F en una posición y lo almacena en la variable V luego avanza una posición Escribe el valor de V en la fila F siempre en la ultima posición, luego avanza una posición Primitiva de la estructura que retorna verdadero si encuentra la marca de fin de la fila y falso en otro caso. Cierra la fila secuencial
Implementación de las Filas secuenciales
La forma clásica de implementar las filas secuenciales es a través del empleo de archivos los cuales son estructuras de datos en memoria secundaria para almacenar los datos en forma permanente. Archivo
Se supone que las entradas y salidas (E/S) de información se producen hacia/desde archivos o ficheros ("files"). En C/C++ este es un concepto muy genérico, dado que un archivo puede ser un fichero en disco; una impresora; una cinta magnética; una colección de fichas perforadas; una consola, o un teclado. Es decir, desde el punto de vista del programa, el concepto de archivo puede entenderse como “dispositivo” externo hacia/desde el que puede fluir información. Es evidente que no todos los archivos soportan las mismas operaciones. Por ejemplo, una cinta magnética soporta acceso secuencial, mientras que un disco magnético soporta E/S aleatoria. Una impresora solo soporta operaciones de salida (desde el programa que imprime) mientras que un micrófono solo proporciona entradas (hacia el programa que recibe la señal). Tipos de archivos •
Archivos Secuenciales.- En este caso los datos se almacenan en forma consecutiva y no es
posible leer ningún registro directamente, es decir para leer el registro n se deberá recorrer o accesar los n-1 registros anteriores. •
Archivos Directos o Random.- Para este caso si se puede acceder o leer un renglón n cualquiera.
Flujo
Las operaciones de E/S de C y C++ se conceptualizan como corrientes de datos que entran y salen del programa hacia/desde distintos tipos de archivos (como hemos visto, dispositivos que pueden incluir teclado, consola, discos, cintas, Etc.) Aunque cada dispositivo es diferente, el programa utiliza un solo concepto de corriente de datos, denominado flujo, el cual se aplica a los diferentes sistemas de E/S de C y C++: Sistema de E/S definido por ANSI C/C++ Sistema de E/S tipo UNIX Sistema de E/S de bajo nivel
• • •
Tratar todos los sistemas de E/S seria demasiado largo para esta guía, así que solo trataremos la implementación de las filas secuenciales a través del sistema de E/S de C++ o mas conocidos como flujos streams dando a conocer las características y funciones mas importantes y comúnmente usadas Almacenamiento en archivos •
Modo Texto: en este caso los datos son almacenados usando Ascii y por tanto son plenamente
visibles usando cualquier editor.
•
Modo Binario: en este caso los datos son almacenados en notación hexadecimal y por tanto se
ocupa un editor binario para reconocerlos, sin embargo un archivo binario es mas compacto que un archivo texto. Un archivo binario almacena datos, todos de un mismo tamaño y pueden ser simples como datos compuestos(TAD). Cuando almacenamos datos compuesto hablamos de registros en los cuales se aplican dos conceptos: •
Campo.- un campo es un ítem o elemento de datos elementales, caracterizado por su
tamaño o longitud y su tipo de datos (cadena, entero, lógico, etc) •
Registro.- un registro es una colección de campos lógicamente relacionados que se
almacenan en un archivo en disco en forma de renglones consecutivos. Ejemplo 1:
Archivo de alumnos
3 campos
CODIGO
NOMBRE
NOTA
0980034 0970035 0781200 0891233
Carlos M. Rojas Sanchez Maria Trujillo Trejo Elena Alvarez Mattos Juan Ricra Gomez
10 12 14 11
4 registros
DISCO
Cuando almacenamos registros, estos tienen el mismo tamaño, constan del mismo numero de campos de tamaño fijo en un orden particular. Como se conocen la longitud y la posición de cada campo, solamente los valores de los campos se necesitan almacenarse; el nombre del campo y longitud de cada campo son atributos de la estructura de archivos. Un campo particular, generalmente el primero de cada registro se conoce como el campo clave. El campo clave identifica unívocamente al registro. así, los valores de la clave para registros diferentes son siempre diferentes. Los archivos secuenciales son típicamente utilizados en aplicaciones de proceso de lotes Y son óptimos para dichas aplicaciones si se procesan todos los registros. La organización secuencias de archivos es la única que es fácil de usar tanto en disco como en cinta. En un archivo organizado secuencialmente, los registros quedan grabados consecutivamente cuando el archivo se usa como entrada y tiene una marca final que indica el fin del archivo
Principio de archivo
Registro 1 Registro 2 : Registro n-1 Registro n FIN
Fin de archivo
Ubicación lógica y física de los registros en un archivo secuencial
En los archivos secuenciales distinguimos dos tipos de ubicación. •
Ubicación lógica .- se refiere a la estructura lógica de cómo se organiza la información. La
información lógica podría estar almacenadas físicamente en uno o más archivos de un disco rígido. •
Ubicación física .- es aquella donde el contenido de los datos del registro determina su posición
física La organización física del archivo en una cinta o disco se corresponde exactamente con la ubicación lógica del archivo Ejemplo
Ubicación lógica
Ubicación física
En este archivo los registros tienen la siguiente estructura:
0
0
907
Elena
1
52
789
Maria
2
104
123
Juan
3
156
786
Elena
4
208
567
Angela
class ALUMNO{ int codigo; // 2 bytes char nombre[50]; //50 bytes : }; Haciendo la suma encontramos que cada registro del archivo tiene un tamaño de 52 bytes
Archivos, manejo de flujos Primera parte C++
C++ provee las siguientes clases para realizar operaciones de entrada y salida de caracteres hacia o desde archivos: • • •
ofstream: El flujo para escribir archivos. ifstream: El flujo para leer archivos. fstream: Flujo de lectura/escritura sobre archivos
Abrir archivos
La primera operación que se realiza sobre un objeto de una de estas clases es asociarlo a un archivo físico. Este procedimiento es conocido como abrir archivo . Para realizar esta apertura utilizamos la función miembro de la clase open(archivo , modo);, dónde archivo es una secuencia de caracteres terminada en nulo del tipo const char * que representa el nombre del archivo físico a ser abierto, y mode son una serie de parámetros opcionales que se detallan en la siguiente tabla: ios::in Modo de operaciones de entrada. ios::out Modo de operaciones de salida. ios::binary Opera en modo binario. Ubica la posición inicial al final del archivo, sí este parámetro se omite, la posición inicial queda al ios::ate principio del archivo. las operaciones de salida son realizadas al final del archivo, haciendo append (agregar al ios::app Todas final). Sólo puede usarse en flujos abiertos sólo de salida. el archivo abierto para operaciones de salida ya existe físicamente, el contenido se borra y ios::trunc Si será reemplazado por el nuevo que se introduzca Las opciones de la tabla anterior pueden combinarse utilizando el operador OR ( | ). Por ejemplo si quisieramos abrir un archivo de ejemplo, llamado ejemplo.bin en modo binario, para agregar datos al final del archivo, podríamos utilizar la sentencia: ofstream SalidaBinaria; SalidaBinaria.open ("ejemplo.bin", ios::out | ios::app | ios::binary); Para las clases ifstream y ofstream, son asumidos automática y respectivamente los argumentos, ios::in y ios::out Podemos hacer la operación de apertura mediante el uso del constructor del objeto al momento de instanciarlo, por ejemplo: ofstream MiArchivo ("ejemplo.bin", ios::out | ios::app | ios::binary); Para verificar que un archivo fue abierto correctamente, podemos utilizar la función miembro de la clase member is_open() que devuelve un valor booleano, true si la apertura fue correcta, false en caso contrario. Por ejemplo: if (MiArchivo.is_open()) { /* operamos con el archivo */ } else { /* manejamos el error */ } Cerrar el archivo
Cuando terminemos de usar el archivo debemos cerrarlo, así nuestro programa devolverá el recurso al sistema operativo nuevamente. Para hacerlo nos valemos de la función miembro close(), esta función no toma parámetros y lo que hace es terminar de escribir todo lo que haya quedado en los buffers y luego cerrar el archivo:
MiArchivo.close() Archivos binarios
Hay dos formas de escribir y leer datos binarios a o desde un archivo. Primero se puede escribir un byte usando la función miembro put() y leer un byte usando la funcion miembro get() y la segunda forma que nos interesa aplicar en el tema de filas secuenciales es escribiendo y leyendo bloques de datos binarios, usando la funciones miembros read y write. /* Escribimos datos enteros en un archivo binario Observación: En versiones anteriores de dev C++ en lugar de usar reinterpret_cast(&x) se usa (unsigned char *)&x */ #include #include #include class ENTERO{ int num; public: void REGISTRAR(int x){ ofstream esc("ejemplo1",ios::app| ios::binary); if(!esc){ cout<<"archivos on problemas";getch(); } else{ esc.write(reinterpret_cast(&x),sizeof(ENTERO)); esc.close(); } } void MOSTRAR(){ int y; ifstream lec("ejemplo1"); if(!lec){ cout<<"archivos con problemas";getch(); } else { lec.read(reinterpret_cast(&y),sizeof(ENTERO)); while(!lec.eof()){ cout<<"\n"<(&y),sizeof(ENTERO)); } lec.close(); } } }; int main(){ char op; int dato; ENTERO e; for(;;){ cout<<" \n adicionar <1>"; cout<<" \n Mostrar <2>"; cout<<" \n salir <3>"; op=getch(); switch(op){ case '1':cout<<"\n Ing entero :";cin>>dato; e.REGISTRAR(dato);break; case '2':e.MOSTRAR();getch(); break; case '3':return 0; } } }
Archivos de texto
Los archivos de texto usan para leer y escribir los operadores << y >>. Estos archivos se usan para almacenar texto y otros valores como TABULACIONES y caracteres de nueva línea que tendrán interpretaciones especiales y no tomados literalmente como en un archivo en modo binario. Las operaciones son las mismas que podemos asociarle al flujo de salida estándar cout: #include #include #include "conio.h" class TEXTO{ char linea[100]; public: void escribir(char tira[]){ ofstream MiArchivo ("ejemplo.txt"); if (MiArchivo.is_open()){ MiArchivo <>linea; while (! MiArchivo.eof() ){ cout << linea << endl; MiArchivo>>linea; } MiArchivo.close(); } else cout << "No se pudo abrir el archivo."; } }; int main () { TEXTO t; t.escribir("Hola soy cachimbo "); t.leer(); getch(); } Este último ejemplo lee el archivo de texto e imprime su contenido en la pantalla. Notar como se llama a la función miembro eof() que devuelve verdadero en caso de que se haya alcanzado el fin de archivo. Ventajas de las filas secuenciales •
•
En cuanto a las ventajas, las filas secuenciales son más sencillas de manejar, ya que requieren menos funciones En ocasiones pueden ser útiles, por ejemplo, cuando sólo se quiere almacenar cierta información a medida que se recibe, y no interesa analizarla en el momento. Posteriormente, otro programa puede leer esa información desde el principio y analizarla.
Desventajas de las filas secuenciales •
Sin embargo, si el patrón de acceso al programa no es conforma al patrón de ordenamiento de los registros, entonces la eficiencia del programa puede ser terrible.
•
3.
Para las aplicaciones interactivas que incluyen peticiones o actualizaciones de registros individuales, las filas secuenciales ofrecen un rendimiento pobre. REQUERIMIENTOS O MATERIAL Y EQUIPO
• •
4.
Software Dev C++ 1 Diskete PROCEDIMIENTO
El procedimiento consiste en dos pasos • •
Especificación del TAD y los algoritmos Implementación del TAD
Ejercicio 1.
Hacer el algoritmo y el programa que permita concatenar dos archivos de alumnos Especificación del TAD y los algoritmos Especificación ALUMNO variable
entero : codigo cadena : nombre
operaciones
crear : no retorna valor IngresarAlumno : no retorna valor MostrarAlumno : no retornar valor REGISTRAR(fila, x) : no retornar valor VISUALIZAR(fila) : no retornar valor CONCATENAR(fila1,fila2, fila3): no retornar valor
significado
En REGISTRAR añadir x del tipo ALUMNO a fila En VISUALIZAR mostrar contenido de fila En CONCATENAR juntar contenidos de fila1, fila2 en fila3
Finespecificacion
procedimiento CONCATENAR(fila1, fila2, fila3) Inicio(fila1) Inicio(fila2) Inicio(fila3) Leer(fila1, valor) Mientras no Ultimo(fila1) hacer Escribir(fila3, valor) Leer(fila1, valor) Fin_mientras Cerrar(fila1) Leer(fila2, valor) Mientras no Ultimo(fila2) hacer Escribir(fila3, valor) Leer(fila2, valor) Fin_mientras Cerrar(fila2) Cerrar(fila3) Fin_CONCATENAR
Implementación del TAD
#include #include #include using namespace std; class ALUMNO{ int codigo; char nombre[40]; public: void IngresarAlumno(){ cout<<"\n leer codigo : ";cin>>codigo; cout<<"\n leer nombre : ";cin>>nombre; } void MostrarAlumno(){ cout<<"\n "<(&x),sizeof(ALUMNO)); esc.close(); } } void VISUALIZAR(char fila[]){ ALUMNO y; ifstream lec(fila); if(!lec){ cout<<"\n ERROR al abrir "<(&y),sizeof(ALUMNO)); while(!lec.eof()){ y.MostrarAlumno(); lec.read(reinterpret_cast(&y),sizeof(ALUMNO)); } lec.close(); } } void CONCATENAR(char fila1[],char fila2[],char fila3[]){ ALUMNO y; ifstream F1(fila1); ifstream F2(fila2); ofstream F3(fila3, ios::out|ios::trunc |ios::binary); if(!F3){ cout<<"\n ERROR al abrir "<(&y),sizeof(ALUMNO)); while(!F1.eof()){ F3.write(reinterpret_cast(&y),sizeof(ALUMNO)); F1.read(reinterpret_cast(&y),sizeof(ALUMNO)); } F1.close(); } F1.close(); if(!F2){
cout<<"\n ERROR al abrir "<
}
};
}
}
else { F2.read(reinterpret_cast(&y),sizeof(ALUMNO)); while(!F2.eof()){ F3.write(reinterpret_cast(&y),sizeof(ALUMNO)); F2.read(reinterpret_cast(&y),sizeof(ALUMNO)); } F1.close(); } F1.close(); F3.close();
int main(int argc, char *argv[]){ char op; ALUMNO a; for(;;){ cout<<" \n adicionar fila1 <1>"; cout<<" \n adicionar fila2 <2>"; cout<<" \n Mostrar filas <3>"; cout<<" \n Concatenar filas <4>"; cout<<" \n salir <5>"; op=getch(); switch(op){ case '1':a.IngresarAlumno(); a.REGISTRAR("fila1",a);break; case '2':a.IngresarAlumno(); a.REGISTRAR("fila2",a);break; case '3':a.VISUALIZAR("fila1"); a.VISUALIZAR("fila2"); a.VISUALIZAR("fila3"); getch(); break; case '4':a.CONCATENAR("fila1","fila2","fila3");break; case '5':return 0; } } } Ejercicio 2
Se desea hacer un programa que permita separar a los alumnos con promedio impar en un archivo y los que están con promedio par en otro archivo Especificación del TAD y los algoritmos Especificación ALUMNO variable
entero : codigo cadena : nombre real: promedio
operaciones
crear : no retorna valor IngresarAlumno : no retorna valor MostrarAlumno : no retornar valor REGISTRAR(fila, x) : no retornar valor VISUALIZAR(fila) : no retornar valor PAR(nota) : retorna un valor booleano SEPARAR(fila1,fila2, fila3): no retornar valor
significado
En REGISTRAR añadir x del tipo ALUMNO a fila En VISUALIZAR mostrar contenido de fila En SEPARAR registrar alumnos con promedio impar en fila2 y con promedio par en fila3 En PAR si nota del promedio es par retorna verdadero sino falso Fin_ALUMNO
Función PAR(nota): lógico real: nota mientras (nota >=2) nota nota - 2 finhacer si (nota= 0 ) entonces retornar verdadero sino retornar falso Finsi Fin_PAR procedimiento SEPARAR(fila1, fila2, fila3) inicio(fila1) inicio(fila2) inicio(fila3) leer(fila1, alum) mientras( no Ultimo(fila1)) hacer si(PAR(alum.promedio)) entonces escribir(fila3, alum) sino escribir(fila2, alum) finsi leer(fila1, alum) fin_mientras cerrar(fila1) cerrar(fila2) cerrar(fila3) fin_SEPARAR Implementación del TAD
#include #include #include using namespace std; class ALUMNO{ int codigo; char nombre[40]; float promedio; public: void IngresarAlumno(){ cout<<"\n leer codigo : ";cin>>codigo; cout<<"\n leer nombre : ";cin>>nombre; cout<<"\n leer promedio : ";cin>>promedio; } void MostrarAlumno(){ cout<<"\n "<
else{ esc.write(reinterpret_cast(&x),sizeof(ALUMNO)); esc.close(); }
} void VISUALIZAR(char fila[]){ ALUMNO y; ifstream lec(fila); if(!lec){ cout<<"\n ERROR al abrir "<(&y),sizeof(ALUMNO)); while(!lec.eof()){ y.MostrarAlumno(); lec.read(reinterpret_cast(&y),sizeof(ALUMNO)); } lec.close(); } } bool PAR(float nota){ while (nota>=2){ nota-=2; } if(nota==0) return true; else return false; }
};
void SEPARAR(char fila1[],char fila2[],char fila3[]){ ALUMNO y; ifstream F1(fila1); ofstream F2(fila2, ios::out| ios::trunc|ios::binary); ofstream F3(fila3, ios::out| ios::trunc|ios::binary); if(!F1){ cout<<"\n ERROR al abrir "<(&y),sizeof(ALUMNO)); while(!F1.eof()){ if(PAR(y.promedio)) F3.write(reinterpret_cast(&y),sizeof(ALUMNO)); else F2.write(reinterpret_cast(&y),sizeof(ALUMNO)); F1.read(reinterpret_cast(&y),sizeof(ALUMNO)); } F1.close(); F2.close(); F3.close(); } }
int main(int argc, char *argv[]){ char op; ALUMNO a; for(;;){ cout<<" \n adicionar fila1 <1>"; cout<<" \n Mostrar filas <2>"; cout<<" \n Separar filas <3>"; cout<<" \n salir <4>"; op=getch(); switch(op){ case '1':a.IngresarAlumno();
}
}
a.REGISTRAR("fila1",a);break; case '2':a.VISUALIZAR("fila1"); a.VISUALIZAR("fila2"); a.VISUALIZAR("fila3"); getch(); break; case '3':a.SEPARAR("fila1","fila2","fila3");break; case '4':return 0; }
Ejercicio 3.
Se desea hacer un programa que permita hacer una copia de los alumnos Especificación del TAD y los algoritmos Especificación ALUMNO variable
entero : código cadena : nombre
operaciones
IngresarAlumno : no retorna valor MostrarAlumno : no retornar valor REGISTRAR(fila, x) : no retornar valor VISUALIZAR(fila) : no retornar valor COPIAR(fila1,fila2) : no retornar valor
significado
En REGISTRAR añadir x del tipo ALUMNO a fila En VISUALIZAR mostrar contenido de fila
Fin_ALUMNO
procedimiento COPIAR(fila1 , fila2) inicio(fila1) inicio(fila2) leer(fila1, dato) mientras(no Ultimo(fila)) hacer escribir(fila2, dato) leer(fila1, dato) fin_mientras cerrar(fila1) cerrar(fila2) fin_COPIAR Implementación del TAD
#include #include #include using namespace std; class ALUMNO{ int codigo; char nombre[40]; public: void IngresarAlumno(){
cout<<"\n leer codigo : ";cin>>codigo; cout<<"\n leer nombre : ";cin>>nombre;
} void MostrarAlumno(){ cout<<"\n "<(&x),sizeof(ALUMNO)); esc.close(); } } void VISUALIZAR(char fila[]){ ALUMNO y; ifstream lec(fila); if(!lec){ cout<<"\n ERROR al abrir "<(&y),sizeof(ALUMNO)); while(!lec.eof()){ y.MostrarAlumno(); lec.read(reinterpret_cast(&y),sizeof(ALUMNO)); } lec.close(); } }
};
void COPIAR(char fila1[],char fila2[]){ ALUMNO y; ifstream F1(fila1); ofstream F2(fila2, ios::out| ios::trunc|ios::binary); if(!F1){ cout<<"\n ERROR al abrir "<(&y),sizeof(ALUMNO)); while(!F1.eof()){ F2.write(reinterpret_cast(&y),sizeof(ALUMNO)); F1.read(reinterpret_cast(&y),sizeof(ALUMNO)); } F1.close(); F2.close(); } }
int main(int argc, char *argv[]){ char op; ALUMNO a; for(;;){ cout<<" \n adicionar fila1 <1>"; cout<<" \n Mostrar filas <2>"; cout<<" \n Copiar filas <3>"; cout<<" \n salir <4>"; op=getch(); switch(op){ case '1':a.IngresarAlumno(); a.REGISTRAR("fila1",a);break; case '2':a.VISUALIZAR("fila1"); a.VISUALIZAR("fila2");
}
}
getch(); break; case '3':a.COPIAR("fila1","fila2");break; case '4':return 0; }
Ejercicio 4.
Se requiere un programa que permita insertar un alumno en un archivo de alumnos según una posición que especifique en el archivo Especificación ALUMNO variable
entero: código cadena: nombre
operaciones
IngresarAlumno : no retorna valor MostrarAlumno : no retornar valor REGISTRAR(fila, x) : no retornar valor VISUALIZAR(fila) : no retornar valor INSERTAR(fila1,fila2, x, posicion) : retornar booleano Ecuaciones En REGISTRAR añadir x del tipo ALUMNO a fila En INSERTAR se registrara el nuevo dato x en la fila2 en una ubicación de la fila1 especificada por la variable posición. Fin_ALUMNO
función insertaralumno(fila1, fila2, x, posición): lógico ALUMNO : x entero : posición insertar falso Indice 0 Inicio(fila1) Inicio(fila2) Leer(fila, dato) Mientras no ultimo(fila1) hacer Si posición = índice entonces insertar verdadero Escribir(fila2, x) finsi Escribir(fila2, dato) Leer(fila1, dato) indice indice + 1 Fin_mientras Cerrar(fila1) Cerrar(fila2) retornar insertar fininsertar Ejercicio 5.
Se requiere un programa que intercale los registros de dos archivos uno de alumnos varones y otro de damas. Los alumnos ambos damas y varones deben tener como datos el código, nombre y edad. Ejemplo
Entrada
Salida
Alumnos : A, D, C , E Alumnas : M, N Intercalado: A, M, D, N, C, E
Ejercicio 6
Se requiere un programa que genere la unión de dos archivos. Cada archivo contendrá alumnos los cuales tienen como información código, nombre y edad. Ejemplo
Entrada Salida
Alumnos1 : A, D, C , E, M Alumnos2 : M, N Unión
: A, D, C, E, M, N
Ejercicio 7
Escriba un programa que intercambie dos registros de un archivo de alumnos. El programa debe asegurarse que los registros existan y luego hacer el intercambio. Ejemplo
Entrada
Salida
Alumnos1 : A, D, C , E, M Leer : M Leer A Alumnos2 : M, D, C, E, A
Ejercicio 8
Escriba la especificación, los algoritmos y el programa que permita eliminar todos los números repetidos en una fila. Ejemplo entrada Fila 1: 2, 5, 2, 8, 3, 3, 9, 3 Salida Fila2: 5, 8, 9 Ejercicio 9
Escriba la especificación, los algoritmos y el programa que permita eliminar la redundancia de los números en una fila. Ejemplo entrada Fila 1: 2, 5, 2, 8, 3, 3, 9, 3 Salida Fila2: 2, 5, 8, 3, 9
5.
ANALISIS DE RESULTADOS •
• •
•
6.
En filas secuenciales, la información sólo puede leerse y escribirse empezando desde el principio de la fila. La escritura de nuevos datos siempre se hace al final de la fila. Para leer una zona concreta de la fila hay que avanzar siempre, si la zona está antes de la zona actual de lectura, será necesario "rebobinar" la fila. Las filas sólo se pueden abrir para lectura o para escritura, nunca de los dos modos a la vez. Esto es en teoría, por supuesto, en realidad C no distingue si los archivos que usamos son secuenciales o no, es el tratamiento que hagamos de ellos lo que los clasifica como de uno u otro tipo. BIBLIOGRAFIA
• •
Estructura de Datos, Un Enfoque Algorítmico. Manuel Gallardo O., Teodomiro Pérez C. Tenenbaum A. M., Langsam Y., Augenstein,M.A., (1993) Estructura de Datos en C , 2ª Ed. México D.F., Prentice Hall Hispanoamericana S.A.
• •
•
Joyanes Aguilar, L., Sanchez Garcia, L., Fernadez Azuela, M. Zahonero Martinez, I.,(2005) Estructura de Datos en C, Madrid, Mc Graw-Hill - Interoamericana. Cairó O., Guardati M.C. S., (2002) Estructura de Datos , 2ª. Ed. México D.F., Mc Graw-Hill / Interamericana Editores S.A.