Download Documentación externa

Document related concepts
no text concepts found
Transcript
Índice
Introducción........................................................... ......................................2
1. Descripción del problema..................................................................3
1.1 Planteo del problema...................... .................................................3
1.2 Objetivos...........................................................................................3
1.3 Requerimientos ................................................................................3
2. Abstracción........................................................................................4
2.1 Especificación de la clase................................................................4
2.2 Operaciones y métodos...................................................................6
2.3 Eficiencia del programa...................................................................6
2.4 Especificación del programa............................................................7
2.5 Arquitectura del programa................................................................8
3. Implementación..................................................................................9
3.1 Modelo de la clase............................................................................9
3.2 Invariante de la clase......................................................................10
3.3 Arquitectura interna del programa...................................................10
3.4 Compilador usado...........................................................................12
3.5 ¿Cómo compilar el programa? .......................................................12
4. Guía de uso del programa................................................................13
5. Datos de prueba...............................................................................14
6. Código fuente...................................................................................16
Reconocimientos.........................................................................................17
Bibliografía...................................................................................................18
1
Introducción
El presente programa pretende leer los nombres de los archivos y
subdirectorios que tienen como raíz otro subdirectorio, el cual es especificado por
parte del usuario, de manera tal que se pueda desplegar en pantalla los nombres
de esos archivos y subdirectorios de forma ordenada.
Tanto la documentación interna y externa de este programa, así como el
código fuente del mismo, pueden ser accesados en la siguiente dirección:
http://www.angelfire.com/ak5/juancho/tareas_p2/tarea6/tarea_6.htm
1. Descripción del problema
2
1.1 Planteo del problema
El problema radica en el siguiente aspecto específico:
-
Implementar un programa que logre leer los nombres de archivos y
subdirectorios de un subdirectorio raíz, el cual lo determina el usuario; esto
mediante el uso de procesos recursivos y un árbol binario.
1.2 Objetivos
El objetivo del programa es:
-
Lograr realizar la lectura de los archivos y subdirectorios mediante el uso de
métodos o funciones recursivas y un contenedor de datos abstracto (árbol
binario).
1.3 Requerimientos
Para poder concretar los objetivos, se requiere:
-
-
Implementar un programa que realice la lectura de los subdirectorios y
archivos, esto bajo la premisa que los nombres de los mismos deben
aparecer ordenadamente en la pantalla.
Utilizar métodos recursivos tanto en el árbol binario como en la lectura de
los nombres de los archivos y los subdirectorios.
Utilizar un árbol binario, el cual va a almacenar los nombres de los archivos
y subdirectorios.
2. Abstracción
3
2.1 Especificación de la clase
La especificación de la clase FolderReader es la siguiente:
Los atributos privados de la clase son:
-
string source;
Tree< string > FileTree;
Las funciones públicas de la clase FolderReader son:
-
FolderReader (const char* argv1);
FolderReader ();//constructor por defecto
~FolderReader(){};
-
void FolderReader::replaceSymbol(string& s);
void getInformation (const string& source);
void getInfo(const string& src);
-
Esta clase es la que realiza realmente las funciones del programa. Contiene
como atributos un string, él cual la información con la cual se trabaja en ese
momento, y un árbol binario, en él cual se guarda la información para luego
desplegarla de forma ordenada. Entre sus métodos están el constructor y
constructor por defecto que inicializan los objetos de tipo FolderReader y el
destructor. Además contiene dos métodos que realizan la función de leer los
archivos y insertarlos en l árbol. El primero es void getInformation (const
string& source) que se encarga de los casos donde la información esta vacía o
nula. El segundo void getInfo(const string& src) que se encarga de insertar
toda la información en el árbol de forma ordenada para su posterior despliegue
en pantalla. Hay que tomar en cuenta que dentro de este método es necesario
el uso de métodos creados en la tarea anterior de manejo de archivos para
poder leer con facilidad la información requerida. Por ultimo esta void
replaceSymbol(string& s) que cambia todos los símbolos para que estos
puedan ser leídos por los métodos, ya que algunos solo aceptan símbolos
definidos y cesan de funcionar o funcionan erróneamente sin estos.
4
La especificación de la clase Tree es la siguiente:
Los atributos privados de la clase son:
-
TreeNode< NODETYPE > *rootPtr;
Las funciones públicas de la clase Tree son:
-
Tree();
void insertNode( const NODETYPE & );
void preOrderTraversal() const;
void inOrderTraversal() const;
void postOrderTraversal() const;
Las funciones privadas de la clase Tree son:
-
void insertNodeHelper(
TreeNode< NODETYPE > **, const NODETYPE & );
void preOrderHelper( TreeNode< NODETYPE > * ) const;
void inOrderHelper( TreeNode< NODETYPE > * ) const;
void postOrderHelper( TreeNode< NODETYPE > * ) const;
Esta clase fue tomada del libro de Deitel para asegurar que su funcionamiento
no tuviera ningún error, en el programa se utiliza para guardar los nombres de los
subdirectorios y archivos. Después por medio de un recorrido se puedan
desplegar en forma ordenada los archivos. La clase en si contiene dos tipos de
métodos uno para insertar nodos al árbol (void insertNode( const NODETYPE &
))y los otros que son diferentes modos de recorrer el árbol. La raíz del árbol es el
directorio donde el usuario decide empezar y para el funcionamiento de esta clase
es necesaria la clase Treenode(nodos que se utilizan en la construcción del
árbol).
5
La especificación de la clase Treenode es la siguiente:
Los atributos privados de la clase son:
-
TreeNode< NODETYPE > *leftPtr;
NODETYPE data;
TreeNode< NODETYPE > *rightPtr;
Las funciones públicas de la clase Treenode son:
-
TreeNode( const NODETYPE &d )
-
NODETYPE getData() const { return data; }
La clase friend de la clase Treenode es:
-
friend class Tree< NODETYPE >;
Esta clase se incluye en el programa, porque es necesaria para el
funcionamiento de la clase Tree(mencionada anteriormente), ya que esta provee
los nodos necesarios para la construcción del árbol y el funcionamiento de los
mismo.
2.2 Operaciones y métodos
En este programa, se especifican la siguiente función:
a44239_a45214.cpp
- void readFiles (const char* argv1);
2.3 Eficiencia del programa
La arquitectura lógica del programa va a responder, principalmente, a 3
módulos, en los cuales se trata de realizar un manejo eficiente de la memoria, por
cuanto en el programa se opta por la creación de un objeto del tipo FolderReader,
el cual va a determinar como se realizan las operaciones, el orden en que se
ejecutan los métodos y el ciclo de vida de las variables que se necesitan para
concretar los métodos.
A nivel de tiempo de ejecución, no se puede garantizar que el programa corra
de forma rápida o lenta, ya que esto dependerá fuertemente de los distintos
métodos recursivos que se ejecutan en el programa, que, dependiendo de la
profundidad del directorio fuente escrito en la línea de comandos (no es lo mismo
que lea desde c: que desde un subdirectorio que solamente tiene archivos),
pueden producir una gran cantidad de llamados a métodos, por lo que haría muy
lento el programa.
6
2.4 Especificación del programa
La especificación del programa responde a este esquema, en el cual se
pasa el directorio raíz – el cual va a fungir como la raíz del árbol binario -, el cual
se obtiene por medio de la línea de comandos (argv[1]):
El programa va a tomar un solo argumento de la línea de comandos, el cual
se va a referir a locación del subdirectorio desde donde va a iniciar la lectura de
archivos. Este argumento se pasa a la clase FolderReader, el cual se va a
encargar de leer el contenido de ese subdirectorio y los subdirectorios que
dependan del mismo (subdirectorios hijos), consecuentemente este módulo se
encarga de recopilar los nombres de los archivos y subdirectorios que dependan
del subdirectorio padre especificado por el argumento escrito en la línea de
comandos, además de almacenar esos nombres en un árbol binario. Este árbol
binario posee 2 módulos, la clase propia del árbol, la cual contiene los métodos de
insertar, eliminar y de recorrido, igualmente, se tiene a la clase Treenode, la cual
representará a los nodos del árbol.
7
2.5 Arquitectura del programa
El presente esquema, va a responder, básicamente, a la arquitectura del
programa:
<iostream>
<iostream.h>
<string>
<string>
<io.h>
+----------+
|Treenode.h|
+----------+
+------+
|Tree.h|
+------+
+----------------+ +----------------+
|44239_a45214.cpp| |FolderReader.cpp|
+----------------+ +----------------+
+-----------------+ +----------------+
|a44239_a45214.obj| |FolderReader.obj|
+-----------------+ +----------------+
+-----------+
| read.exe |
+-----------+
8
3. Implementación
3.1 Modelo de las clases
El modelo UML de la clase FolderReader es:
Class FolderReader
- string source;
- Tree< string > FileTree;
+
+
+
+
+
+
FolderReader (const char* argv1);
FolderReader ();//constructor por defecto
~FolderReader(){};
void FolderReader::replaceSymbol(string& s);
void getInformation (const string& source);
void getInfo(const string& src);
El modelo UML de la clase Tree es:
Class Tree
- TreeNode< NODETYPE > *rootPtr;
+
+
+
+
+
-
Tree();
void insertNode( const NODETYPE & );
void preOrderTraversal() const;
void inOrderTraversal() const;
void postOrderTraversal() const;
void insertNodeHelper(TreeNode< NODETYPE > **, const
NODETYPE & );
- void preOrderHelper( TreeNode< NODETYPE > * ) const;
- void inOrderHelper( TreeNode< NODETYPE > * ) const;
- void postOrderHelper( TreeNode< NODETYPE > * ) const;
El modelo UML de la clase Treenode es:
Class Treenode
- TreeNode< NODETYPE > *leftPtr;
- NODETYPE data;
- TreeNode< NODETYPE > *rightPtr;
+ TreeNode( const NODETYPE &d )
: leftPtr( 0 ), data( d ), rightPtr( 0 );
+ NODETYPE getData() const { return data; }
9
3.2 Invariante de la clase
La invariante de este programa va a girar en torno al árbol binario, cuya
propiedad principal es tener un nodo padre con 2 hijos señalando,
respectivamente, a los subárboles izquierdo y derecho; por lo tanto, la invariante
del programa verificará si existe el nodo padre y si ese nodo posee un valor
determinado.
bool Check_Ok(const Tree& tree){
if (tree.rooPtr == 0){
return false;
}else{
if (tree.rooPtr->data == 0){
return false;
}else{
return true;
}
Se verifica si existe un nodo raíz en el
árbol
---------------------------------------------------Se verifica si ese nodo raíz tiene algún
valor
--------------------------------------------------Si el nodo raíz del árbol existe y tiene un
valor, entonces el objeto está construido
correctamente.
}
}
Nota: Debido a razones de diseño (ya que se contempla al objeto FolderReader
como el ente encargado de recolectar, dirigir y manipular la información referente
a los nombres de archivos y subdirectorios) y al hecho que este programa
solamente lee una vez los nombres de archivos y subdirectorios desde una
ubicación determinada (es por esta razón que se opta por llamar a todos los
métodos de la clase FolderReader necesarios para la lectura de los nombres de
los archivos y subdirectorios desde el constructor del objeto de la clase
FolderReader; consecuentemente, toda invariante va a retornar falso en el
constructor de algún objeto, ya que estos objetos se encuentra en su proceso de
creación e inicialización durante la ejecución del constructor – no vale la pena
verificar que los mismos estén correctamente creados en esta etapa, porque no lo
van a estar hasta que se termine la ejecución del constructor – ), no es necesario
verificar la invariante del objeto reader de la clase FolderReader.
3.3 Arquitectura interna del programa
Básicamente, el programa esta compuesto por las clases FolderReader, Tree
y Treenode y por la siguiente función:
a44239_a45214.cpp
- void readFiles (const char* argv1);
10
La arquitectura interna del programa va girar en torno a la función
la cual se invoca en la función main, dentro del
archivo a44239_a45214.cpp:
void readFiles (const char* argv1 ),
void readFiles (const char* argv1){
FolderReader* reader = new FolderReader(argv1);
delete reader;
}
Obtiene el directorio destino por medio de
la línea de comandos
---------------------------------------------Se crea el objeto reader, el cual se
encargará de leer los nombres de los
archivos y subdirectorios que tengan al
argumento de la línea de comandos como
padre.
---------------------------------------------Se borra ejecuta el objeto FolderReader
reader
Complementariamente, se adjuntan explicaciones de los siguientes métodos:
void getInfo(const string& src) – método que obtiene el nombre de los archivos en los subdirectorios
fuente y los subdirectorios que dependan de este void FolderReader::getInfo(const string& src){
const char* actualDirectory = src.c_str();
char* directory = new char[strlen(actualDirectory) + strlen("*.*")
+ 1];
strcpy(directory, actualDirectory);
strcpy(directory + strlen(actualDirectory), "*.*");
_finddata_t FILE_BLOCK;
long hFile;
if ( (hFile = _findfirst( directory, &FILE_BLOCK )) == -1L) {
} else {
char* name;
string subdirectory;
string sname;
while( _findnext( hFile, &FILE_BLOCK ) == 0) {
if( FILE_BLOCK.attrib & _A_SUBDIR ) {
Se convierte el subdirectorio a leer de
string a const char* .
---------------------------------------------Se crea un char*, ya que _findfirst sólo
acepta char*. Poner atención en la longitud
de este char*.
---------------------------------------------Se copia el nombre del subdirectorio a leer
en char* directory.
---------------------------------------------Se copia “*.*”(leer todos los archivos) al
nombre del subdirectorio a leer en char*
directory.
---------------------------------------------Se crea un “objeto” de la struct
_finddata_t
---------------------------------------------Si el subdirectorio que se está leyendo
tiene archivos o más subdirectorios, se
genera un número identificador y se le
asigna a hFile, de lo contrario se devuelve
-1L
---------------------------------------------Mientras existan archivos o subdirectorios,
se leen los archivos
---------------------------------------------Si es un subdirectorio, se convierte el
11
sname = string(FILE_BLOCK.name);
if (sname == ".." || sname == "."){
}else{
subdirectory = src;
name = FILE_BLOCK.name;
FileTree.insertNode(string(name));
subdirectory += string(name);
subdirectory += "/";
nombre a string, se analiza si es un nombre
válido, se almacena el nombre del
subdirectorio en el árbol y se vuelve a
invocar el método con un nuevo
subdirectorio
getInfo(subdirectory);
Aquí se da la recursividad
---------------------------------------------Condición de parada de la recursividad(que
no se esté procesando un subdirectorio)
name = FILE_BLOCK.name;
Se convierte el nombre del archivo a string
y se almacena en el árbol
}
}else{
FileTree.insertNode(string(name));
}
----------------------------------------------
}//fin del while
}
_findclose( hFile );
delete directory;
Se borra el char* creado con new .
}
3.4 Compilador usado
Se uso el compilador Microsoft Visual C++ 6.0 .
3.5 ¿Cómo compilar el programa?
Para compilar el programa, se deben seguir las siguientes instrucciones:
-
-
Descomprimir el archivo ea44239.zip en el escritorio.
Abrir Microsoft Visual C++ 6.0 ó superior y crear un nuevo proyecto.
Agregar los archivos de encabezado - Header Files - (Tree.h, Treenode.h
y FolderReader.h ) que se encuentran en la carpeta codigo_fuente.
Agregar los archivos fuente – Source Files - (a44239_a45214.cpp, y
FolderReader.cpp) que se encuentran en la carpeta codigo_fuente.
Buscar el menú Build / Compile
12
4. Guía de uso del programa
Para poder usar el programa, se deben seguir los siguientes pasos:
- Descomprimir el archivo ea44239.zip en el escritorio.
- Buscar y accesar la carpeta a44239_a45214.
- Buscar y acceder la carpeta Debug.
- Cargar el Command Prompt de Windows y buscar la carpeta donde se
ubica el archive synch.exe mediante el comando cd.
- Escribir en DOS read + el directorio donde se inicia la lectura de
archivos.
Ej: read “f:\ci-1201\respaldo”
Nota:
1- El programa emite error si no se respeta la sintaxis planteada
5. Datos de prueba
13
5.1 Formato de los datos de prueba
El formato de los datos de prueba va a radicar en 2 campos específicos:
-
Errores de digitación por parte del usuario.
Subdirectorios con archivos y vacíos.
5.2 Entradas vs Salidas esperadas
Las entradas y salidas esperadas para los errores de digitación de usuario
son:
ENTRADA
SALIDA
read “f:\ci-1201\respaldo”
Read
DOS – Archivos y subdirectorios
leídos
Error – programa
read “ñ:/respaldo”
Error DOS – no existe unidad ñ
read “ci-1201\respaldo”
Error DOS – no se especifica unidad
read “4312kjfblk”
Error DOS – sintaxis incorrecta
Las entradas y salidas esperadas para los subdirectorios con archivos y
vacíos son:
ENTRADA
Directorio fuente
SALIDA
Subdirectorios
dependientes del
directorio fuente ( se
toma en cuenta que estos
subdirectorios puedan tener
archivos)
1 archivo
0 subdirectorios
25 archivos
0 subdirectorios
1 archivo
1 subdirectorios
26 archivos
25 subdirectorio
0 archivos
0 subdirectorios
1 archivo leído
0 subdirectorios leídos
25 archivos leídos
0 subdirectorios leídos
1 archivo leído
1 subdirectorio leído
26 archivos leídos
25 subdirectorios leídos
0 archivos leídos
0 subdirectorios leídos
Nota: Las pruebas referentes al ordenamiento correcto de los nombres de los
archivos y subdirectorios no se realizan, ya que el ordenamiento depende
exclusivamente de los operadores de comparación de los strings de STL, por lo
que no se tiene ninguna injerencia en los criterios de comparación que ahí se
utilizan.
14
6. Código fuente
15
El código fuente del programa se encuentra disponible en la dirección
electrónica:
http://www.angelfire.com/ak5/juancho/tareas_p2/tarea6/tarea_6.htm
Además, el código ha sido comentado, en su mayoría, en este trabajo, por lo que
se obvia la impresión del mismo.
Reconocimientos
16
Cabe destacar el aporte del profesor Adolfo Di-Mare, ya que este facilito la
mayoría de la implementación del método void getInfo(const string& src) de la clase
Folder.
Igualmente, se debe reconocer el código referente al árbol binario del libro
de texto del señor Deitel.
Bibliografía
17
-
Deitel y Deitel. ¿Cómo programar en C ++?. Editorial Prentice Hall.
Segunda Edición.1998
http://www.cs.ndsu.nodak.edu/~kvanhorn/Fall2002/cs474/javatoc.html.
Java to C++ transition tutorial. 1997.
http://ourworld.compuserve.com/homepages/ronald_fischer/ . ANSI/ISO
C++ Incompatibility Page. Fischer, Ronald. 2002
http://www.fz-juelich.de/zam/cxx/extmain.html#learn
.
Forschungszentrum Jülich. Última modificación: 19 de julio de 2004.
18