Permite el diseño de paradigmas orientados a objetos, mediante:
- DESARROLLO RAPIDO:
- CODIFICACIÓN MANUAL:
|
||||
Vector |
||||
Arbol |
Datos |
|||
Hanoi |
ESTRUCTURA del PROGRAMA C++BUILDER
Para no entrar en una aburrida teorización, vayámos al grano..!!! y para ello sigue los siguientes pasos
Claro que hacer un programa para ello, no tiene sentido..!!, pero la idea, es que si esta es tu primera vez, que no sea tán traumática y solo veas, analices y saques tus conclusiones sobre la operativa y el funcionamiento de esta magnífica herramienta de programación.
Es de vital importancia que, si eres novel en programación, que pongas en marcha la propuesta siguiente, cuya finalidad es comenzar a familiarizarte con el entorno de programación visual de C++, el cual te permite tanto la codicación manual total o la utilización de generadores de código.
El programa C++ Builder tiene la siguiente estructura sintáctica
// C++ Builder Wilucha 06.09.99 #include vcl\dialogs.hpp> WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { Tu primera instrucción; .................. más instrucciones; .................. .................. return 0; }
////////////////////////////////////////////////////////////// // PROGRAMA MODELO Wilo Carpio // Visual C++ 28/5/2000 // TIPOS DE DATOS Y OPERADORES ////////////////////////////////////////////////////////////// #include vcl\dialogs.hpp> /////////////////////////////////////////// // Declaración de Tipos de Datos Globales /////////////////////////////////////////// const char Titulo[] = "MI PRIMER PROGRAMA C++Visual Wilo Carpio"; const char Raya[] = "============================="; const char Tema[] = "\n Cálculo del Círculo \n"; const char SaltoRenglon = '\n'; int Radio; float NumeroPi, Circulo; char UnaLetra; bool DeseaSeguir;
/////////////////////////////////////////////// // FUNCION PRINCIPAL /////////////////////////////////////////////// WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { ////////////////////////////// // Variables Locales ////////////////////////////// NumeroPi = 3.1416; AnsiString Valor; char ElRadio; ////////////////////////////// // Ingreso de Datos ////////////////////////////// Valor = InputBox("Ingresa el valor del Radio"," Número entre 1 a 20",""); ElRadio = (char)atoi(Valor.c_str()); ////////////////////////////// // Cálculos ////////////////////////////// Circulo = 2*NumeroPi*ElRadio; ////////////////////////////// // Salidas por Monitor ////////////////////////////// ShowMessage(Titulo+AnsiString(SaltoRenglon)+Raya+Tema +"\n El número Pi = "+AnsiString(NumeroPi) +"\n Pi Ocupa = "+AnsiString(sizeof(NumeroPi))+" bytes" +"\n Para Radio = "+AnsiString(Valor.c_str())+" --> Circulo = "+AnsiString(Circulo) ); return 0; }
FUNCIONES del PROGRAMA C++BUILDER
:////////////////////////////////////////// // C ++ Visual Wilo Carpio // TIPOS DE DATOS Y OPERADORES ////////////////////////////////////////// #include vcl\dialogs.hpp> /////////////////////////////////////////// // Declaración de Tipos de Datos Globales /////////////////////////////////////////// const char Titulo[] = "MI PRIMER PROGRAMA C++Visual Wilo Carpio"; const char Raya[] = "============================="; const char Tema[] = "\n Cálculo del Círculo \n"; const char SaltoRenglon = '\n'; int Radio, Salir; float NumeroPi, Circulo; char UnaLetra; bool OpcionSalir; /////////////////////////////// // Estructura de la función /////////////////////////////// int LeerRadio() { AnsiString Valor; char ElRadio; Valor = InputBox("LONGITUD DEL CIRCULO ","Digita valor del radio ( 0 --> Salir ) ","0"); ElRadio = atoi(Valor.c_str()); return ElRadio; } /////////////////////////////////////////////// // FUNCION PRINCIPAL /////////////////////////////////////////////// WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { ////////////////////////////// // Variables Locales ////////////////////////////// NumeroPi = 3.1416; AnsiString Valor; char ElRadio; ////////////////////////////// // Bucle Operativo ////////////////////////////// do { ////////////////////////////// // Ingreso de Datos // Aplicación de la función ////////////////////////////// ElRadio = LeerRadio(); ///////////////////////////////////////////// // Si el dato ingreasado es mayor que cero // se calcula, sino termina el programa //////////////////////////////////////////// if (ElRadio>0) { ////////////////////////////// // Cálculos ////////////////////////////// Circulo = 2*NumeroPi*ElRadio; ////////////////////////////// // Salidas por Monitor ////////////////////////////// ShowMessage(Titulo+AnsiString(SaltoRenglon)+Raya+Tema +"\n El número Pi = "+AnsiString(NumeroPi) +"\n Pi Ocupa = "+AnsiString(sizeof(NumeroPi))+" bytes de memoria" +"\n Para Radio = "+AnsiString(ElRadio)+" -> Circulo = "+AnsiString(Circulo) ); } } while (ElRadio !=0); return 0; }
Para no entrar en una aburrida teorización, vayámos al grano..!!! y para ello sigue los siguientes pasos
////////////////////////////////////////// // C ++ Visual Wilo Carpio // MANEJO DE MATRICES ////////////////////////////////////////// #include vcl\dialogs.hpp> /////////////////////////////////////////// // Declaración de Tipos de Datos Globales /////////////////////////////////////////// const char Titulo[] = "MANEJO DE MATRICES Visual C++ Wilo Carpio"; const char Raya[] = "============================="; const char Datos[] = "\n\t Datos de la matríz \n"; const char Calculos[] = "\n\n\t Cálculos Numéricos \n"; const char SaltoRenglon = '\n'; int i,j,n,m,s,Mayor,Menor,Suma; int matriz[20][20]; float Promedio;
FUNCIONES: ESTRUCTURAS C++BUILDER
///////////////////////////////////// // Estructuras de las funciones ///////////////////////////////////// int LeerFilas() { AnsiString ValorFilas; char Filas; ValorFilas = InputBox("REGISTRO DE FILAS de A(m,n) ","Digita Nº de filas: Hasta m = 20 ","2"); Filas = atoi(ValorFilas.c_str()); return Filas; } int LeerColumnas() { AnsiString ValorColumnas; char Columnas; ValorColumnas = InputBox("REGISTRO DE FILAS de A(m,n) ","Digita Nº de columnas: Hasta n = 20 ","2"); Columnas = atoi(ValorColumnas.c_str()); return Columnas; } int LeerElemento() { AnsiString ValorElemento; char Elemento; ValorElemento = InputBox("INGRESO DE ELEMENTOS de A(m,n) ","Digita valor del elemento ","2"); Elemento = atoi(ValorElemento.c_str()); return Elemento; } int Seguir() { AnsiString Valor; char Si; Valor = InputBox("DESEAS CONTINUAR ","Para SALIR -> 0 ","0"); Si = atoi(Valor.c_str()); return Si; }
FUNCIONES en C++BUILDER: MAIN
/////////////////////////////////////////////// // FUNCION PRINCIPAL /////////////////////////////////////////////// WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { ////////////////////////////// // Variables Locales ////////////////////////////// ////////////////////////////// // Bucle Operativo ////////////////////////////// do {
FUNCIONES en C++BUILDER: ALTAS
////////////////////////////// // Ingreso de Datos // Aplicación de la función ////////////////////////////// m = LeerFilas(); n = LeerColumnas(); ///////////////////////////////////////////// // Carga del valor de cada elemento ///////////////////////////////////////////// for(j=1;j<=m;j++) for(i=1;i<=n;i++) { matriz[i][j]=LeerElemento(); };
FUNCIONES en C++BUILDER: OPERACIONES
///////////////////////////////////////////// // Si el dato ingreasado es mayor que cero // muestra la matriz, sino termina el programa //////////////////////////////////////////// if (m>0) { ////////////////////////////// // Cálculos ////////////////////////////// Mayor=0; Menor=matriz[1][1]; Suma=0; for(j=1;j<=m;j++) for(i=1;i<=n;i++) { if (matriz[i][j]>Mayor) Mayor=matriz[i][j]; if (matriz[i][j] < Menor) Menor=matriz[i][j]; Suma=Suma+matriz[i][j]; }; Promedio=Suma/(m*n);
VER PARA CREER
Para simplificar solo usaremos el fomulario Message...!!
///////////////////////////////// // Salidas por Monitor A(m,n) //////////////////////////////// ShowMessage ( Titulo + AnsiString(SaltoRenglon) + Raya + Datos +" \ n Número de Filas = " + AnsiString(AnsiString(j-1)) +" \ n Número de Columnas = " + AnsiString(AnsiString(i-1)) +" \ n Primer elemento A(1,1) = " + AnsiString(matriz[1][1]) +" \ n Ultimo elemento A("+AnsiString(j-1) + ","+AnsiString(i-1)+") = "+ AnsiString(matriz[i-1][j-1]) + Calculos +" \ n Mayor elemento = "+ AnsiString(Mayor) +" \ n Menor elemento = "+ AnsiString(Menor) +" \ n Promedio Valores = "+ AnsiString(Promedio) ); } s= Seguir(); } while (s !=0); return 0; }
Para los otros tipos de archivos, como es de esperar, también nos permite almacenar cualquier información, desde los datos simples tipo int o char hasta las esructuras propias de datos que podemos crear, para otras necesidades especiales, tales como el manejo de ficheros.
Colega algorítmico en estos links te propongo evaluar tus conocimientos sobre los archivos operados con Builder como estructuras organizadas de datos, quienes los agrupamos como temporarios y permanentes:
Si deseas ampliar estos temas te recomiendo la siguiente..
BIBLIOGRAFIA: LIBRO AUTOR EDITORIAL AÑO C++Builder - Francisco Charte - Anaya 2001 Programación C++ - Luis Joyanes - Mc Graw Hill 1999 C++ Cómo programar - Deitel y Deitel - Prentice Hall 1999 Sintaxis y Semántica - Wilo Carpio - Biblioteca UTN 2000
La gestión de un archivo, puede resumirse en las siguientes etapas:
Ej: fstream F ("Agenda", ios : :int | ios : :out );
Abrir un archivo existente y si no existe no lo crea
Ej: fstream F ("Agenda", ios : :nocreate );
Ej: ifstream F ("Agenda");
Ej: ofstream F ("Agenda");
Seekg( ): Se usa para determinar posicionamiento forzado:
APERTURA Y CIERRE DEL ARCHIVO SECUENCIAL
En archivos secuenciales de datos, es necesario establecer un área de buffer, donde la información se almacena temporalmente mientras se está transfiriendo entre la memoria de la computadora y el archivo de datos. Esta área de buffer permite leer y escribir información del archivo más rápidamente de lo que sería posible de otra manera.
La sintaxis para el área de buffer es: FILE *VariablePuntero;
Donde FILE es un tipo de dato estructurado que establece el área de buffer y VariablePuntero es la variable puntero que indica el principio de esta área. Tal puntero generalmente define un puntero a archivo secuencial, o simplemente como archivo secuencial.
Previo a ser creado o procesado el archivo de datos debe ser abierto, de modo de asociar el nombre de archivo con el área de buffer y especificar si se va a usar el archivo como sólo para lectura, o sólo para escritura, o para lectura / escritura.
La sintaxis para abrir el archivo es: VariablePuntero = fopen (NombreArchivo, ModoDeUso);
Donde NombreArchivo es la cadena que identifica el nombre del archivo y ModoDeUso es la manera en la que el archivo será utilizado y debe ser una de las cadenas de la siguiente tabla.
La función fopen retorna un puntero al principio del área de buffer asociada con el archivo si este se puedeabrir y caso contrario, retorna un valor NULL si no se puede abrir el archivo, por ejemplo si un archivo existente no ha sido encontrado.
Para terminar el archivo debe cerrarse al final de un programa, aplicando la función de biblioteca fclose.
La sintaxis para cerrar es: fclose(VariablePuntero);
PROCESAMIENTO DE UN ARCHIVO
Si no tienes experiencia en el manejo de archivos con C++Builder, te recomiendo copiar textualmente el siguiente código, compila y ejecuta y podrás ver que el funcionamiento es simple y que puedes usarlo para tus proyectos.
C++Builder: PROCESAMIENTO DEL ARCHIVO
///////////////////////////////////////////////// // BUILDER C++ Wilo Carpio // Manejo de Archivos 26/9/2000 //////////////////////////////////////////////// #include#pragma hdrstop #include ///////////////////////////////////////////////// // El archivo "Agenda.h" registra la declaración // de la estructura del registro a usar: // struct TRegistro // { // char Nombre[30],Email[20]; // }; // private: // User declarations // fstream Archivo; // TRegistro Registro; // // int NumeroRegistro(); // void NumeroRegistro(int); // int NumeroRegistros(); // void Actualiza(); ////////////////////////////////////////////////////////////// #include "Agenda.h" #pragma package(smart_init) #pragma resource "*.dfm" TMiFormulario *MiFormulario; __fastcall TMiFormulario::TMiFormulario(TComponent* Owner): TForm(Owner) { Archivo.open("EMAIL.DAT",ios::in|ios::out|ios::binary|ios::ate); if (!Archivo) { ShowMessage("No hay archivo che..!!"); throw; } Actualiza(); } void __fastcall TMiFormulario::BotonGrabarClick(TObject *Sender) { strcpy(Registro.Nombre,BoxNombre->Text.c_str()); strcpy(Registro.Email, BoxEmail->Text.c_str()); Archivo.write((char *)&Registro, sizeof(Registro)); if (!Archivo) ShowMessage("No existe el archivo..!!"); Actualiza(); BoxNombre->SetFocus(); } void __fastcall TMiFormulario::BotonSalirClick(TObject *Sender) { int OpcionSalir; MiFormulario->Caption = "ELEGISTE BOTON CANCELAR"; OpcionSalir= Application->MessageBox("Sales del Sistema..", "ESTAS POR CERRAR EL PROGRAMA", MB_OKCANCEL+ MB_DEFBUTTON1|MB_ICONQUESTION); if (OpcionSalir== IDOK) { MiFormulario->Close(); } if (OpcionSalir == IDCANCEL) { MiFormulario->Caption = "Wilo Carpio PROGRAMA MODELO C++"; } } void __fastcall TMiFormulario::BotonAntClick(TObject *Sender) { if (NumeroRegistro() > 1) NumeroRegistro(NumeroRegistro()-1); Actualiza(); } void __fastcall TMiFormulario::BotonSigClick(TObject *Sender) { if (NumeroRegistro() <= NumeroRegistros()) NumeroRegistro(NumeroRegistro()+1); Actualiza(); } void TMiFormulario::Actualiza() { if (NumeroRegistro()<=NumeroRegistros()) { Archivo.read((char *)&Registro, sizeof(Registro)); NumeroRegistro(NumeroRegistro()-1); BoxNombre->Text = Registro.Nombre; BoxEmail->Text = Registro.Email; } else { BoxNombre->Text = ""; BoxEmail->Text = ""; } MiFormulario->Caption = "AGENDA de WILO: Fichas TOTAL: " + AnsiString(NumeroRegistros())+ " ACTUAL: " + AnsiString(NumeroRegistro()); } int TMiFormulario::NumeroRegistro() { return Archivo.tellg()/sizeof(Registro)+1; } int TMiFormulario::NumeroRegistros() { int PosicionActual = Archivo.tellg(); Archivo.seekg(0, ios::end); int N = NumeroRegistro()-1; Archivo.seekg(PosicionActual); return N; } void TMiFormulario::NumeroRegistro(int NuevoNumero) { Archivo.seekg((NuevoNumero-1)*sizeof(Registro)); } void __fastcall TMiFormulario::BotonConsultaClick(TObject *Sender) { MiFormulario->Caption = "AGENDA de WILO: Fichas TOTAL: " + AnsiString(NumeroRegistros()) + " ACTUAL: " + AnsiString(NumeroRegistro()); if (BotonConsulta->Caption=="&Consulta") { if (NumeroRegistro() <= NumeroRegistros()) NumeroRegistro(NumeroRegistro()+2); Actualiza(); GrupoDatos->Visible=True; BotonConsulta->Caption="&Cerrar"; BotonModifica->Visible=False; GrupoVer->Visible=True; } else { MiFormulario->Caption = "AGENDA de WILO: Fichas TOTAL: " + AnsiString(NumeroRegistros()); BotonConsulta->Caption="&Consulta"; BotonModifica->Visible=True; GrupoVer->Visible=False; GrupoDatos->Visible=False; } } void __fastcall TMiFormulario::BotonModificaClick(TObject *Sender) { MiFormulario->Caption = "AGENDA de WILO: Fichas TOTAL: " + AnsiString(NumeroRegistros()) + " ACTUAL: " + AnsiString(NumeroRegistro()); if (BotonModifica->Caption=="&Modificar") { BotonModifica->Caption="&Cerrar"; BotonConsulta->Visible=False; GrupoModifica->Visible=True; GrupoDatos->Visible=True; } else { MiFormulario->Caption = "AGENDA de WILO: Fichas TOTAL: " + AnsiString(NumeroRegistros()); BotonModifica->Caption="&Modificar"; BotonConsulta->Visible=True; GrupoModifica->Visible=False; GrupoDatos->Visible=False; GrupoVer->Visible=False; } } void __fastcall TMiFormulario::BotonCambiosClick(TObject *Sender) { MiFormulario->Caption = "Selecciona una ficha, modifica y luego graba.!!" ; if (BotonCambios->Caption=="&Cambios") { BotonCambios->Caption="&Cerrar"; BotonConsulta->Visible=False; GrupoVer->Visible=True; GrupoDatos->Visible=True; } else { MiFormulario->Caption = "AGENDA de WILO: Fichas TOTAL: " + AnsiString(NumeroRegistros()); BotonModifica->Caption="&Modificar"; BotonCambios->Caption="&Cambios"; BotonConsulta->Visible=True; GrupoModifica->Visible=False; GrupoDatos->Visible=False; GrupoVer->Visible=False; } }
ARCHIVOS SIN FORMATO
Para estas aplicaciones es necesario leer o escribir el bloque entero del archivo de datos en vez de leer o escribir separadamente las componentes individuales de cada bloque.
Estas funciones son operadas con cuatro argumentos: un puntero al bloque de datos, el tamaño del bloque de datos, el número de bloques a transferir y el puntero a un archivo secuencial.
La sintaxis es: fwrite(&VariableTipoRegistro, sizeof(Registro), 1, PunteroArchivoSecuencial);
Donde VariableTipoRegistro es una variable estructura de tipo registro y PunteroArchivoSecuencial es un puntero a archivo secuencial asociado a un archivo de datos abierto para salida.
ARCHIVOS DE ACCESO DIRECTO
También llamados aleatorios, están distribuidos de manera que se puede acceder directamente conociendo su dirección.
En C no existen archivos de acceso directo, sin embargo, existen funciones como fseek() y fgetpos() que permiten tratar los archivos como arrays, moviéndose directamente a un byte determinado del archivo abierto por fopen().
Para el acceso de estos archivos se usa el puntero asociado con el archivo, el cual a diferencia de los punteros de C++ , es un índice que apunta a una posición dada o a la posición actual es el punto en el que comienza el siguiente acceso archivo. El puntero puede ser:
Cada vez que se realiza una transacción de entrada o salida, el puntero correspondiente avanza automáticamente. Pero, si se usan las funciones seekg ( ) y seekp ( ) se puede acceder al archivo de modo directo, no secuencial.
fseek() usa tres argumentos:
La función fgetpos devuelve la posición actual del puntero a FILE, para ello necesita dos argumentos
LECTURA DE UN ARCHIVO TEXTO
Ejemplo que lee un Archivo de texto y lo muestra en la pantalla:
////////////////////////////////////// // Leer un archivo // C WiloCarpio ////////////////////////////////////// #includeint main() {
Puntero FILE *: Todas las funciones de estrada/salida estándar usan este puntero para conseguir información sobre el Archivo abierto. No apunta al archivo sino a la estructura que contiene información sobre él.
Esta estructura incluye entre otras cosas información sobre el nombre del archivo, la dirección de la zona de memoria donde se almacena el Archivo, tamaño del buffer.
FILE *Archivo; char letra;
Abrir el archivo:
Sintaxis de fopen.: FILE *fopen(const char *nombre_Archivo, const char *modo); El nombre de Archivo se puede indicar directamente o usando una variable. Se puede abrir de diversas formas
Se puede agregar: b Para abrir en modo binario, t modo texto y + modo lectura y escritura
Ejemplo:
Archivo = fopen("origen.txt","r");
Comprobar si el archivo está abierto: Después de abrir un Archivo es comprobar si realmente está abierto, para evitar fallos: el archivo puede no existir, estar dañado o no tener permisos de lectura
Si el Archivo no se ha abierto el puntero Archivo (puntero a FILE) tendrá el valor NULL y significa que no se abrió por algún error y se debe salir del programa, usando exit( 1 ), el 1 indica al sistema operativo que se han producido errores.
if (Archivo==NULL) { printf( "No se puede abrir el Archivo.\n" ); exit( 1 ); }
Leer el Archivo
La función getc, lee los caracteres uno a uno. Se puede usar también la función fgetc (son equivalentes, la diferencia es que getc está implementada como macro).
Además de estas dos existen otras funciones como fgets, fread que leen más de un carácter.
Sintaxis: getc (y de fgetc) es: int getc(FILE *Archivo);
Ej. letra = getc( Archivo ); Toma un carácter de Archivo, lo almacena en letra y el puntero se coloca en el siguiente carácter.
printf ( "Contenido del Archivo:\n" ); letra = getc ( Archivo);
Fin de Archivo: Cuando entramos en el bucle while, la lectura se realiza hasta que se encuentre el final del Archivo. Para detectar el final del Archivo se pueden usar dos formas: con la función feof() o comprobando si el valor de letra es EOF.
En el ejemplo hemos usado la función feof. Esta función es de la forma: int feof ( FILE *Archivo); Esta función comprueba si se ha llegado al final de Archivo en cuyo caso devuelve un valor distinto de 0.
Si no se ha llegado al final de Archivo devuelve un cero.
Por eso lo usamos del siguiente modo: while ( feof(Archivo)==0 ) o while ( !feof(Archivo) )
La segunda forma consiste en comprobar si el carácter leído es el de fin de Archivo EOF: while ( letra!=EOF ) Cuando trabajamos con Archivos de texto no hay ningún problema, pero si estamos manejando un Archivo binario podemos encontrarnos EOF antes del fin de Archivo. Por eso es mejor usar feof.
while (feof(Archivo)==0) { printf( "%c",letra ); letra=getc(Archivo); }
Una vez realizadas todas las operaciones deseadas sobre el Archivo hay que cerrarlo. Es importante no olvidar este paso pues el Archivo podría corromperse.
Al cerrarlo se vacían los buffers y se guarda el Archivo en disco. Un Archivo se cierra mediante la función fclose(Archivo). Si todo va bien fclose devuelve un cero, si hay problemas devuelve otro valor.
Estos problemas se pueden producir si el disco está lleno, por ejemplo.
if (fclose(Archivo)!=0) printf( "Problemas al cerrar el Archivo\n" ); }
LEER LINEAS COMPLETAS
Sintaxis: char *fgets(char *buffer, int longitud_max, FILE *Archivo);
Esta función lee desde el Archivo hasta que encuentra un carácter '\n' o hasta que lee longitud_max-1 caracteres y añade '\0' al final de la cadena.
La cadena leída la almacena en buffer. Si se encuentra EOF antes de leer ningún carácter o si se produce un error la función devuelve NULL, en caso contrario devuelve la dirección de buffer.
////////////////////////////////////// // Leer un archivo // C WiloCarpio ////////////////////////////////////// #includeint main() { FILE *Archivo; char MiTexto[100]; Archivo=fopen("Origen.txt","r"); if (Archivo==NULL) { printf( "No se puede abrir el Archivo.\n" ); exit( 1 ); } printf( "Contenido del Archivo:\n" ); fgets(MiTexto,100,Archivo); while (feof(Archivo)==0) { printf( "%s",MiTexto ); fgets(MiTexto,100,Archivo); } if (fclose(Archivo)!=0) printf( "Problemas al cerrar el Archivo\n" ); }
ESCRITURA EN ARCHIVOS
////////////////////////////////////// // Escribir en un archivo // C WiloCarpio ////////////////////////////////////// #includeint main() {
Como el puntero FILE es la base de la escritura/lectura de archivos, definimos dos punteros FILE:
Puntero 'origen' para almacenar la información sobre el Archivo origen.txt
Puntero 'destino' para guardar la información del Archivo destino.txt (el nombre del puntero no tiene por qué coincidir con el de Archivo).
FILE *origen, *destino; char letra;
Abrir el Archivo usando fopen. La diferencia es que ahora tenemos que abrirlo para escritura. Usamos el modo 'w' (crea el Archivo o lo vacía si existe) porque queremos crear un Archivo.
Después de abrir un Archivo hay que comprobar si la operación se ha realizado con éxito. En este caso, como es un sencillo ejemplo, los he comprobado ambos a la vez: if (origen==NULL || destino==NULL) pero es más correcto hacerlo por separado así sabemos dónde se está produciendo el posible fallo
origen=fopen("origen.txt","r"); destino=fopen("destino.txt","w"); if (origen==NULL || destino==NULL) { printf( "Problemas con los Archivos.\n" ); exit( 1 ); }
Lectura del origen y escritura en destino- getc y putc
Para la escritura usamos la función putc: int putc(int c, FILE *Archivo); donde c contiene el carácter que queremos escribir en el Archivo y el puntero Archivo es el Archivo sobre el que trabajamos.
De esta forma vamos escribiendo en el Archivo destino.txt el contenido del Archivo origen.txt.
letra=getc(origen); while (feof(origen)==0) { putc(letra,destino); printf( "%c",letra ); letra=getc(origen); } if (fclose(origen)!=0) printf( "Problemas al cerrar el Archivo origen.txt\n" );
Leemos datos de un Archivo debemos comprobar si hemos llegado al final. Sólo debemos comprobar si estamos al final del Archivo que leemos.
No tenemos que comprobar el final del Archivo en el que escribimos puesto que lo estamos creando y aún no tiene final.
Cerrar el Archivo – fclose
Y por fin lo que nunca debemos olvidar al trabajar con Archivos: cerrarlos. Debemos cerrar tanto los Archivos que leemos como aquellos sobre los que escribimos.
if (fclose(destino)!=0) printf( "Problemas al cerrar el Archivo destino.txt\n" ); }
Escritura de líneas – fputs: La función fputs trabaja junto con la función fgets
int fputs(const char *cadena, FILE *Archivo);
SIMPLIFICANDO LA VIDA..!!
Como las funciones getc, putc, fgets, fputs son adecuadas solo para operar con caracteres (1 byte) y cadenas. Si quisiéramos trabajar con otros tipos de datos, como almacenar variables de tipo int en el archivo, sería necesario convertir los valores a cadenas (con la función itoa), luego, para recuperar estos valores deberíamos leerlos como cadenas y pasarlos a enteros (atoi).
Para simplificar esta tarea conviene usar las funciones fread y fwrite que nos permiten tratar con datos de cualquier tipo, incluso con estructuras.
Fwrite: Permite escribir en un Archivo. La sintaxis es
size_t fwrite(void *buffer, size_t tamano, size_t numero, FILE *pArchivo);
Ejemplo:
////////////////////////////////////// // Archivo // C WiloCarpio ////////////////////////////////////// #includestruct { char nombre[20]; char apellido[20]; char telefono[15]; } registro; int main() { FILE *Archivo; Archivo = fopen( "nombres.txt", "a" ); do { printf( "Nombre: " ); fflush(stdout); gets(registro.nombre); if (strcmp(registro.nombre,"")) { printf( "Apellido: " ); fflush(stdout); gets(registro.apellido); printf( "Teléfono: " ); fflush(stdout); gets(registro.telefono); fwrite( ®istro, sizeof(registro), 1, Archivo ); } } while (strcmp(registro.nombre,"")!=0); fclose( Archivo ); }
NOTA: El bucle termina cuando el 'nombre' se deja en blanco.
Este programa guarda los datos personales mediante fwrite usando la estructura registro. Abrimos el Archivo en modo 'a' (append, añadir), para que los datos que introducimos se añadan al final del Archivo.
Una vez abierto abrimos estramos en un bucle do-while mediante el cual introducimos los datos. Los datos se van almacenando en la variable registro (que es una estructura).
Una vez tenemos todos los datos de la persona los metemos en el Archivo con fwrite:
fwrite( ®istro, sizeof(registro), 1, Archivo );
Fread: se utiliza para sacar información de un Archivo. Su formato es:
size_t fread(void *buffer, size_t tamano, size_t numero, FILE *pArchivo);
Siendo buffer la variable donde se van a escribir los datos leídos del Archivo pArchivo.
El valor que devuelve la función indica el número de elementos de tamaño 'tamano' que ha conseguido leer. Podemos pedirle a fread que lea 10 elementos (numero=10), pero si en el Archivo sólo hay 6 elementos fread devolverá el número 6.
LOCALIZANDO REGISTROS
#includestruct { char nombre[20]; char apellido[20]; char telefono[15]; } registro; int main() { FILE *Archivo; Archivo = fopen( "nombres.txt", "r" ); while ( ! feof ( Archivo ) ) { if (fread( ®istro, sizeof ( registro ) , 1, Archivo ) ) { printf( "Nombre: %s\n", registro.nombre ); printf( "Apellido: %s\n", registro.apellido); printf( "Teléfono: %s\n", registro.telefono); } } fclose( Archivo ); }
Abrimos el Archivo nombres.txt en modo lectura. Con el bucle while nos aseguramos que recorremos el Archivo hasta el final (y que no nos pasamos).
La función fread lee un registro (numero=1) del tamaño de la estructura registro. Si realmente ha conseguido leer un registro la función devolverá un 1, en cuyo caso la condición del 'if' será verdadera y se imprimirá el registro en la pantalla.
En caso de que no queden más registros en el Archivo, fread devolverá 0 y no se mostrará nada en la pantalla.
Fseek: Permite situarnos en la posición que queramos de un Archivo abierto. Cuando leemos un Archivo hay un 'puntero' que indica en qué lugar del Archivo nos encontramos.
Cada vez que leemos datos del Archivo este puntero se desplaza.
Con la función fseek podemos situar este puntero en el lugar que deseemos.
Sintaxis de fseek: int fseek(FILE *pArchivo, long desplazamiento, int modo);
Como siempre pArchivo es un puntero de tipo FILE que apunta al Archivo con el que queremos trabajar. desplazamiento son las posiciones (o bytes) que queremos desplazar el puntero.
Este desplazamiento puede ser de tres tipos dependiendo del valor de modo:
SEEK_SET El puntero se desplaza desde el principio del Archivo.
SEEK_CUR El puntero se desplaza desde la posición actual del Archivo
SEEK_END El puntero se desplaza desde el final del Archivo
Si se produce algún error al intentar posicionar el puntero, la función devuelve un valor distinto de 0. Si todo ha ido bien el valor devuelto es 0.
LOCALIZACION ACTUAL
#includeint main() { FILE *Archivo; long posicion; int resultado; Archivo = fopen( "origen.txt", "r" ); printf( "¿Qué posición quieres leer? " ); fflush(stdout); scanf( "%D", &posicion ); resultado = fseek( Archivo, posicion, SEEK_SET ); if (!resultado) printf( "En la posición %D está la letra %c.\n", posicion, getc(Archivo) ); else printf( "Problemas posicionando el cursor.\n" ); fclose( Archivo ); }
ftell: Esta función es complementaria a fseek, devuelve la posición actual dentro del Archivo.
Su formato es el siguiente: long ftell(FILE *pArchivo);
El valor que nos da ftell puede ser usado por fseek para volver a la posición actual. fprintf y fscanf:
Estas dos funciones trabajan igual que sus equivalentes printf y scanf. La única diferencia es que podemos especificar el Archivo sobre el que operar (si se desea puede ser la pantalla para fprintf o el teclado para fscanf).
Los formatos de estas dos funciones son:
int fprintf(FILE *pArchivo, const char *formato, ...);
int fscanf(FILE *pArchivo, const char *formato, ...);
LIO FAMILIAR:
Aquellos nodos que tienen el mismo padre se llaman "Hermanos" y los hijos de estos son
"Nietos" del "Padre". Está claro no.???
ARBOL DE EXPRESION: (a + b * c ) + (( d * e + f ) * g )
Los árboles pueden ser usados para representar expresiones de
memoria; para ello se usan árboles binarios que tienen operaciones binarias y están constituidos por hojas que son
operandos y los demás nodos contienen operadores.
En este ejemplo, a + (d * c) se evalúa en el subárbol izquierdo y ((d * e) + f ) se evalúa en el subárbol derecho.
Este esquema "Izquierda, Nodo, Derecha" se denomina de "Recorrido simétrico"
RECURSIVIDAD
Recordemos que un proceso es recursivo cuando está parcial o totalmente definido en términos de sí mismo; de modo que algo que sea infinito pueda ser definido de forma finita; así, un programa recursivo podrá llamarse a sí mismo y deberá tener dos partes:
DECLARAR NODOS DEL ÁRBOL
Usa y analiza la sintaxis y la semántica del siguiente ejemplo para que aprendas a operar tus árboles
//////////////////////////////////////////////////// // C++ Builder Wilo Carpio // MANEJO DE ARBOLES CON ARCHIVO //////////////////////////////////////////////////// #include#pragma hdrstop #include #include "Agenda.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TMiFormulario *MiFormulario; //////////////////////////////////////////////////// // ESTRUCTURA DEL ARBOL //////////////////////////////////////////////////// struct Arbol { char CampoNombre[30]; char CampoEmail[40]; int borrado; struct Arbol *Derecha; struct Arbol *Izquierda; }; //////////////////////////////////////////////////// // ESTRUCTURA DEL ARCHIVO //////////////////////////////////////////////////// struct Archivo { char CampoNombre[30]; char CampoEmail[40]; }; //////////////////////////////////////////////////// // ESTRUCTURAS DE DATOS //////////////////////////////////////////////////// typedef struct Arbol NodoArbol; typedef struct Archivo Registro; //////////////////////////////////////////////////// // DECLARACION DE VARIABLES GLOBALES //////////////////////////////////////////////////// int i; NodoArbol *RaizArbol,*Elejido = NULL,*Papito; int bandera; FILE *archi; Registro Ficha;
ALTA DE NODOS EN EL ÁRBOL
//////////////////////////////////////////////////// // BOTON ALTAS //////////////////////////////////////////////////// void __fastcall TMiFormulario::Altas1Click(TObject *Sender) { bandera=0; PanelAltas->Visible=true; BotonGrabar->Visible=true; BotonCambios->Visible=false; BotonEliminar->Visible=false; BotonLimpiar->Visible=true; BoxNombre->ReadOnly=false; BoxEmail->ReadOnly=false; BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); } //////////////////////////////////////////////////// // BOTON GRABAR //////////////////////////////////////////////////// void __fastcall TMiFormulario::BotonGrabarClick(TObject *Sender) { NodoArbol *q; q = buscar(BoxNombre->Text.c_str()); if (q == NULL) { BotonGrabar->Enabled= true; agregar_nodo(BoxNombre->Text.c_str(), BoxEmail->Text.c_str()); ShowMessage(" DATOS SE GRABARON"); BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); } else { ShowMessage(" EL DATO YA SE ENCUENTRA"); BoxNombre->SetFocus(); } } //////////////////////////////////////////////////// // PROCEDIMIENTO PARA AGREGAR UN NODO EN EL ARBOL //////////////////////////////////////////////////// void agregar_nodo(char Nombre[30], char Email[40] ) { NodoArbol *NodoAuxiliar, *Nodo2Auxiliar; NodoAuxiliar = (NodoArbol *) malloc(sizeof(NodoArbol)); strcpy(NodoAuxiliar->CampoNombre,Nombre); strcpy(NodoAuxiliar->CampoEmail,Email); NodoAuxiliar->borrado = 1; NodoAuxiliar->Izquierda = NULL; NodoAuxiliar->Derecha = NULL; if (RaizArbol == NULL) RaizArbol = NodoAuxiliar; else { Nodo2Auxiliar = RaizArbol; while (Nodo2Auxiliar != NULL) { Papito = Nodo2Auxiliar; if (strcmp(NodoAuxiliar->CampoNombre,Nodo2Auxiliar->CampoNombre) < 0) Nodo2Auxiliar = Nodo2Auxiliar->Izquierda; else Nodo2Auxiliar = Nodo2Auxiliar->Derecha; } if (strcmp(NodoAuxiliar->CampoNombre,Papito->CampoNombre) < 0) Papito->Izquierda = NodoAuxiliar; else Papito->Derecha = NodoAuxiliar; } } //////////////////////////////////////////////////// // PROCEDIMIENTO PARA AGREGAR UN REGISTRO //////////////////////////////////////////////////// void agregar_registro(char Nombre[30], char Email[40]) { archi = fopen("Arbol.dat","a+b"); if (archi != NULL) { strcpy(Ficha.CampoNombre,Nombre); strcpy(Ficha.CampoEmail,Email); fwrite(&Ficha,sizeof(Registro),1,archi); fclose(archi); } } //////////////////////////////////////////////////// // GRABAR EL ARBOL EN EL ARCHIVO //////////////////////////////////////////////////// void cargar_archivo(NodoArbol *r) { if (r != NULL) { cargar_archivo(r->Izquierda); if (r->borrado == 1) agregar_registro(r->CampoNombre,r->CampoEmail); cargar_archivo(r->Derecha); } } //////////////////////////////////////////////////// // CARGAR EL ARBOL //////////////////////////////////////////////////// void cargar_arbol(void) { archi = fopen("Arbol.dat","rb"); RaizArbol = NULL; if (archi != NULL) { fread(&Ficha,sizeof(Registro),1,archi); while(!feof(archi)) { agregar_nodo(Ficha.CampoNombre,Ficha.CampoEmail); fread(&Ficha,sizeof(Registro),1,archi); } } }
VER NODOS DEL ÁRBOL
//////////////////////////////////////////////////// // BOTON CONSULTAS //////////////////////////////////////////////////// void __fastcall TMiFormulario::Consultas1Click(TObject *Sender) { PanelCombo->Visible=true; combo->Clear(); cargar_combo(RaizArbol); BotonCambios->Visible=false; BotonEliminar->Visible=false; BoxNombre->ReadOnly=true; BoxEmail->ReadOnly=true; } //////////////////////////////////////////////////// // PROCEDIMIENTO PARA BUSCAR UN NODO DEL ARBOL //////////////////////////////////////////////////// NodoArbol *buscar(char Nombre[20]) { NodoArbol *busca, *encontrado; bandera = 0; busca = RaizArbol; while(busca != NULL && bandera == 0) { if (strcmp(Nombre,busca->CampoNombre) == 0 && busca->borrado == 1) bandera = 1; else { if (strcmp(Nombre,busca->CampoNombre) < 0) busca = busca->Izquierda; else busca = busca->Derecha; } } if (bandera == 1) encontrado = busca; else encontrado = NULL; return encontrado; }
BORRAR NODO
PROCEDIMIENTO PARA ELIMINAR UN NODO DEL ARBOL
//////////////////////////////////////////////////// // PROCEDIMIENTO PARA ELIMINAR UN NODO DEL ARBOL //////////////////////////////////////////////////// void eliminar(char Nombre[30], char Email [40]) { NodoArbol *busca; busca = buscar(Nombre); busca->borrado = 0; } //////////////////////////////////////////////////// // BOTON ELIMINAR //////////////////////////////////////////////////// void __fastcall TMiFormulario::BotonEliminarClick(TObject *Sender) { int respuesta; respuesta=Application->MessageBox("Confirme eliminacion de datos","Eliminar??",MB_OKCANCEL); if (respuesta==IDOK) { eliminar(BoxNombre->Text.c_str(),BoxEmail->Text.c_str()); BoxNombre->Clear(); BoxEmail->Clear(); } } //////////////////////////////////////////////////// // BOTON BAJAS //////////////////////////////////////////////////// void __fastcall TMiFormulario::Bajas1Click(TObject *Sender) { PanelCombo->Visible=true; combo->Clear(); cargar_combo(RaizArbol); BotonEliminar->Visible=true; BoxNombre->ReadOnly=true; BoxEmail->ReadOnly=true; }
CAMBIAR NODOS
MODIFICAR: Recuerda que puedes modificar todos los campos del nodo, excepto el campo llave.
//////////////////////////////////////////////////// // BOTON MODIFICAR //////////////////////////////////////////////////// void __fastcall TMiFormulario::Modificaciones1Click(TObject *Sender) { PanelCombo->Visible=true; combo->Clear(); cargar_combo(RaizArbol); BotonCambios->Visible=true; BotonEliminar->Visible=false; BoxNombre->ReadOnly=false; BoxEmail->ReadOnly=false; } //////////////////////////////////////////////////// // BOTON CAMBIOS //////////////////////////////////////////////////// void __fastcall TMiFormulario::BotonCambiosClick(TObject *Sender) { strcpy(Elejido->CampoNombre,BoxNombre->Text.c_str()); strcpy(Elejido->CampoEmail,BoxEmail->Text.c_str()); }
TAREA INICIAL
ACTIVAR EL FORMULARIO
//////////////////////////////////////////////////// // ACTIVAR EL FORMULARIO //////////////////////////////////////////////////// __fastcall TMiFormulario::TMiFormulario(TComponent* Owner) : TForm(Owner) { } //////////////////////////////////////////////////// // BOTON SALIR //////////////////////////////////////////////////// void __fastcall TMiFormulario::Salir1Click(TObject *Sender) { int opcion; opcion=Application->MessageBox("¿Quieres cerrar este programa?","Salir", MB_OKCANCEL+MB_ICONQUESTION); if (opcion== IDOK) { Close(); } } //////////////////////////////////////////////////// // BOTON RETORNAR //////////////////////////////////////////////////// void __fastcall TMiFormulario::BotonRetornarClick(TObject *Sender) { PanelVisualizar->Visible = false; } //////////////////////////////////////////////////// // CARGAR EL FORMULARIO //////////////////////////////////////////////////// void __fastcall TMiFormulario::FormCreate(TObject *Sender) { RaizArbol = NULL; cargar_arbol(); } //////////////////////////////////////////////////// // CERRANDO EL ARCHIVO //////////////////////////////////////////////////// void __fastcall TMiFormulario::FormClose(TObject *Sender, TCloseAction &Action) { archi = fopen("Arbol.dat","wb"); fclose(archi); cargar_archivo(RaizArbol); } //////////////////////////////////////////////////// // CERRANDO PANEL DEL COMBO //////////////////////////////////////////////////// void __fastcall TMiFormulario::BotonCerrarClick(TObject *Sender) { PanelCombo->Visible=false; } //////////////////////////////////////////////////// // BOTON ACEPTAR //////////////////////////////////////////////////// void __fastcall TMiFormulario::BotonAceptarClick(TObject *Sender) { Elejido=buscar(combo->Text.c_str()); if (Elejido != NULL) { PanelCombo->Visible=false; BotonGrabar->Visible=false; BotonLimpiar->Visible=false; PanelAltas->Visible=true; BoxNombre->Text = Elejido->CampoNombre; BoxEmail->Text = Elejido->CampoEmail; } } //////////////////////////////////////////////////// // BOTON ORDENAR //////////////////////////////////////////////////// void __fastcall TMiFormulario::Ordenar1Click(TObject *Sender) { Application->MessageBox("Se Ordenarán los Elementos de la Lista","ORDENAR",MB_ICONEXCLAMATION+MB_OKCANCEL); } //////////////////////////////////////////////////// // BOTON LIMPIAR //////////////////////////////////////////////////// void __fastcall TMiFormulario::BotonLimpiarClick(TObject *Sender) { BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); } //////////////////////////////////////////////////// // BOTON REGRESAR //////////////////////////////////////////////////// void __fastcall TMiFormulario::BotonRegresarClick(TObject *Sender) { PanelAltas->Visible = false; }
PREPARA TU IMPRESORA
No olvides cargar papel en tu impresora
//////////////////////////////////////////////////// // BOTON IMPRIMIR //////////////////////////////////////////////////// void __fastcall TMiFormulario::Imprimir1Click(TObject *Sender) { int respuesta; { respuesta=Application->MessageBox("Tu impresora esta prendida?","Atencion",MB_OKCANCEL); if (respuesta==IDOK) PrintDialog->Execute(); } }
TE OFREZCO UN COMBO..!!
Pero para simplificar tu vida
//////////////////////////////////////////////////// // PROCEDIMIENTO PARA CARGAR EL COMBO //////////////////////////////////////////////////// void cargar_combo(NodoArbol *r) { if (r != NULL) { cargar_combo(r->Izquierda); if (r->borrado == 1) MiFormulario->combo->Items->Add(r->CampoNombre); cargar_combo(r->Derecha); } }
DATOS POR GRILLA
Este vendría a ser otro combo programático..!!!
//////////////////////////////////////////////////// // DATOS POR GRILLA //////////////////////////////////////////////////// void __fastcall TMiFormulario::Visualizacion1Click(TObject *Sender) { PanelVisualizar->Visible=true; Grilla->Cells[0][0]="CampoNombre"; Grilla->Cells[1][0]="CampoEmail"; i = 1; cargar_grilla(RaizArbol); } //////////////////////////////////////////////////// // PROCEDIMIENTO PARA CARGAR LA GRILLA //////////////////////////////////////////////////// void cargar_grilla(NodoArbol *r) { if (r != NULL) { cargar_grilla(r->Izquierda); if (r->borrado == 1) { MiFormulario->Grilla->Cells[0][i] = r->CampoNombre; MiFormulario->Grilla->Cells[1][i] = r->CampoEmail; i++; } cargar_grilla(r->Derecha); } while ( MiFormulario->Grilla->Cells[0][i+1]!="") { MiFormulario->Grilla->Cells[0][i+1]=""; MiFormulario->Grilla->Cells[1][i+1]=""; } }
Las estructuras dinámicas de datos son colecciones de elementos llamados NODOS, intervinculados por medio de PUNTEROS que permiten estructuras con capacidad de variar su tamaño y ocupar solo la memoria necesaria, creadas y se destruidas durante la ejecución.
Tales nodos de la estructura, generalmente del tipo registro, se enlazan o encadenan de modo que se establece un vículo o puntero asociando a cada nodo, que apunta al nodo siguiente de la estructura.
Existen diferentes tipos de estructuras dinámicas de datos, siendo las más usadas:
Para programarla debemos recordar los siguientes conceptos...
LOS PUNTEROS
Con el fin de simplificar el manejo de punteros, se utilizan nombres de variables en lugar de direcciones, pues los nombres son simples de recordar. Aunque en la realidad, en la máquina cada posición de la pila de memoria tiene una dirección y un valor específico almacenado en esa posición.
Para almacenar un nuevo valor en memoria se asigna a una variable, y la computadora envía una dirección a la memoria seguida por el valor a almacenar en esa posición.
DECLARACION de PUNTEROS
Para declarar un tipo puntero se indica el tipo de valor que se almacenará en la posicion designada por el puntero. Así cada puntero apunta a una variable particular, que es otra posición de memoria.
Dado que el puntero es una variable que registra la dirección de otra variable almacenada en una celda de memoria, es preciso diferenciar entre las dos entidades implicadas en el apuntamiento:
C++, Usa el asterisco (*) que sigue a los nodos, para indicar que "apunta a"; es decir el tipo de dato es una variable puntero que puede contener una dirección a un tipo de dato llamado nodo.
EJEMPLO: Para simplificar el tema, se ha tomado una agenda elemental de dos campos, nombre y email al que se le asignan los mecanismos de altas, bajas, modificaciones y consultas, en el que se incluye los algoritmos de búsqueda.
//////////////////////////////////////////////////////// // C++BUILDER 5 LISTA SIMPLE CON ARCHIV0 // ListaPrograma.cpp Wilucha 17/09/98 // Graba sobre en archivo Simple.txt //--------------------------------------------------------------------------- #include < vcl.h > #include < fstream.h > #include < stdlib.h > #pragma hdrstop #include "ListaPrograma.h" #pragma package(smart_init) #pragma resource "*.dfm" //--------------------------------------------------------------------------- TMiFormulario *MiFormulario; struct MiNodo { char CampoNodoNombre[30]; char CampoNodoEmail[40]; int FlagNodoBaja; struct MiNodo *SiguienteNodo; }
En este link desarrollaremos una agenda sin archivo físico, por lo tanto cuando cierres el programa tus datos se volatilizan.
La lista enlazada es una secuencia de nodos enlazados o conectados con el siguiente formando una estructura de datos dinámica. Tales nodos suelen ser normalmente registros y que no tienen un tamaño fijo.
La ventaja de una lista enlazada sobre un arreglo es que la lista enlazada puede crecer y decrecer en tamaño y que fácil insertar o suprimir un nodo en el centro de una lista enlazada.
La lista enlazada es una estructura muy versátil, cuyos algoritmos para inserción y eliminación de datos constan de dos pasos:
Esta es una tarea divertida, por que me recuerda cuando niño enganchaba un nuevo vagón en mi trencito de juguete..!!. Para ello es necesario tener en cuenta que...
Este proceso ha sido aplicado en el siguiente algoritmo..
//////////////////////////////////////////////////////// // C++BUILDER 5 LISTA SIMPLE SIN ARCHIV0 // ListaPrograma.cpp Wilucha 17/09/98 //--------------------------------------------------------------------------- *PrimerNodo,*NodoActual,*NuevoNodo,*UltimoNodo; MiNodo *FichaAuxiliar,FichaTrucha; int MensajePorBox,ParametroOrdenar,FlagBaja,Fila; int BuscarCodigo(AnsiString); void AltaDeNuevoNodo(char ParamNombre[30],char ParamEmail[40]) { NuevoNodo = new MiNodo[sizeof(MiNodo)]; strcpy(NuevoNodo->CampoNodoNombre,ParamNombre); strcpy(NuevoNodo->CampoNodoEmail,ParamEmail); NuevoNodo->FlagNodoBaja=0; NuevoNodo->SiguienteNodo=NULL; UltimoNodo=NuevoNodo; if(PrimerNodo==NULL) PrimerNodo=NuevoNodo; else { NodoActual=PrimerNodo; while(NodoActual->SiguienteNodo != NULL) NodoActual=NodoActual->SiguienteNodo; NodoActual->SiguienteNodo=NuevoNodo; } }
..Ojito observa que este proceso inserta nuevos nodos en la lista, pero no en el archivo..!!
//--------------------------------------------------------------------------- __fastcall TMiFormulario::TMiFormulario(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::FormActivate(TObject *Sender) { FlagBaja=0; } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::Altas1Click(TObject *Sender) { MiFormulario->Caption="INGRESO DE DATOS"; Panel->Visible=true; BotonGrabar->Visible=true; BotonLimpiar->Visible=true; BotonEliminar->Visible=false; BotonModificar->Visible=false; BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); Simple1->Enabled=false; } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonLimpiarClick(TObject *Sender) { BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); }
Por supuesto que los nodos dados de alta están vacios..!!!, por lo tanto veamos cómo les grabamos los datos en cada uno de sus campos...
void __fastcall TMiFormulario::BotonGrabarClick(TObject *Sender) { char Nombre[30], Email[40]; if((BoxNombre->Text=="")||(BoxEmail->Text=="")) Application->MessageBox("Introduzca datos","Atencion",MB_OK); else { strcpy(Nombre,BoxNombre->Text.c_str()); strcpy(Email,BoxEmail->Text.c_str()); if(BuscarNombre(Nombre)==0) { AltaDeNuevoNodo(Nombre,Email); LlenarCombo(); BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); } else { MensajePorBox=Application->MessageBox("Desea ingresarlo nuevamente","Dato existente",MB_OKCANCEL); if(MensajePorBox==IDOK) { strcpy(NodoActual->CampoNodoNombre,BoxNombre->Text.c_str()); strcpy(NodoActual->CampoNodoEmail,BoxEmail->Text.c_str()); BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); } else { BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); } } } } //---------------------------------------------------------------------------
Ahora ya tenemos nuestro trencito con los vagones cargados.. Oohh.!! perdón, tenemos la lista enlazada con sus nodos con datos en sus campos.
En los siguientes links, veremos las operaciones más comunes que podemos efectuar con estos nodos.
En este link encontrarás la codificación de los algoritmos para visualizar los datos que cargaste en cada uno de los nodos de tu estructura dinámica.
//--------------------------------------------------------------------------- void __fastcall TMiFormulario::Consultas1Click(TObject *Sender) { MiFormulario->Caption="Consulta de datos"; if(PrimerNodo != NULL) { PanelCombo->Visible=true; Combo->Clear(); BotonGrabar->Visible=false; BotonLimpiar->Visible=false; BotonEliminar->Visible=false; BotonModificar->Visible=false; LlenarCombo(); } else Application->MessageBox("No hay datos para consultar","Lista Vacia",MB_OK); } //---------------------------------------------------------------------------
Te ofrezco un combo..!!
//--------------------------------------------------------------------------- void TMiFormulario::LlenarCombo() { Combo->Clear(); Combo->Items->Clear(); NodoActual=PrimerNodo; while(NodoActual != NULL) { Combo->Items->Add(NodoActual->CampoNodoNombre); NodoActual=NodoActual->SiguienteNodo; } } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonAceptarClick(TObject *Sender) { int LoHalle; char DatoBuscado[40]; AnsiString DatoDelCombo; LoHalle=0; NuevoNodo=PrimerNodo; DatoDelCombo=Combo->Items->Strings[Combo->ItemIndex]; strcpy(DatoBuscado,DatoDelCombo.c_str()); while(NuevoNodo!=NULL) { if(stricmp(NuevoNodo->CampoNodoNombre,DatoBuscado)==0) { LoHalle=1; if(NuevoNodo->FlagNodoBaja!=1) { Panel->Visible=true; PanelCombo->Visible=false; BoxNombre->Text=NuevoNodo->CampoNodoNombre; BoxEmail->Text=NuevoNodo->CampoNodoEmail; NodoActual=NuevoNodo; NuevoNodo=NULL; } } else NuevoNodo=NuevoNodo->SiguienteNodo; } if(LoHalle==0) { ShowMessage("La ficha que busca no ha sido ingresada"); PanelCombo->Visible=false; } } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::Visualizar1Click(TObject *Sender) { Fila=1; if(PrimerNodo==NULL) { Application->MessageBox("No hay datos en la lista","Atencion...",MB_OK); } PanelVisualizar->Visible = true; if (PrimerNodo!=NULL) { Grilla->Cells[0][0]="Nombre"; Grilla->Cells[1][0]="Email"; NuevoNodo = PrimerNodo; while (NuevoNodo->SiguienteNodo!= NULL) { Grilla->Cells[0][Fila]=NuevoNodo->CampoNodoNombre; Grilla->Cells[1][Fila]=NuevoNodo->CampoNodoEmail; Fila=Fila+1; while ( Grilla->Cells[0][Fila+1]!="") { Grilla->Cells[0][Fila+1]=""; Grilla->Cells[1][Fila+1]=""; } NuevoNodo=NuevoNodo->SiguienteNodo; } Grilla->Cells[0][Fila]=NuevoNodo->CampoNodoNombre; Grilla->Cells[1][Fila]=NuevoNodo->CampoNodoEmail; } else { PanelVisualizar->Visible = false; } }
Si nos equivocamos.. no hay drama..!!, buscamos dónde está el error, lo borramos y a otra cosa.!!!
//--------------------------------------------------------------------------- int BuscarNombre(AnsiString UnNombre) { int HayDato=0; NodoActual=PrimerNodo; if (NodoActual!=NULL) while (NodoActual != NULL) { if ((UnNombre)==NodoActual->CampoNodoNombre) { HayDato=1; break; } NodoActual=NodoActual->SiguienteNodo; } return(HayDato); } void __fastcall TMiFormulario::Bajas1Click(TObject *Sender) { MiFormulario->Caption="Eliminacion de datos"; if(PrimerNodo != NULL) { PanelCombo->Visible=true; BotonGrabar->Visible=false; BotonLimpiar->Visible=false; BotonModificar->Visible=false; BotonEliminar->Visible=true; Simple1->Enabled=false; LlenarCombo(); FlagBaja=1; } else Application->MessageBox("No hay datos para eliminar","Lista vacia",MB_OK); } //---------------------------------------------------------------------------
//--------------------------------------------------------------------------- //BOTON PARA ELIMNAR LOS DATOS void __fastcall TMiFormulario::BotonEliminarClick(TObject *Sender) { if(PrimerNodo != NULL) { MensajePorBox=Application->MessageBox("Desea Eliminar estos datos","Eliminacion de datos",MB_OKCANCEL); if(MensajePorBox==IDOK) { FichaAuxiliar=NodoActual; if(NodoActual==PrimerNodo) PrimerNodo=NodoActual->SiguienteNodo; else { NodoActual=PrimerNodo; while(NodoActual->SiguienteNodo != NULL) { if(NodoActual->SiguienteNodo==FichaAuxiliar) { FichaTrucha,NodoActual; break; } NodoActual=NodoActual->SiguienteNodo; } FichaTrucha,FichaAuxiliar->SiguienteNodo; } delete(FichaAuxiliar); LlenarCombo(); Application->MessageBox("Los datos fueron eliminados","Eliminacion de datos",MB_OK); } } else Application->MessageBox("No hay datos a eliminar","La lista HayDato vacia",MB_OK); BoxNombre->Clear(); BoxEmail->Clear(); } //---------------------------------------------------------------------------
Si deseas corregir el contenido de un nodo en particular, lo ubicas a este y luego activas el siguiente algoritmo
//--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonModificarClick(TObject *Sender) { strcpy(NodoActual->CampoNodoNombre,BoxNombre->Text.c_str()); strcpy(NodoActual->CampoNodoEmail,BoxEmail->Text.c_str()); Application->MessageBox("Los datos ya han sido modificados","Modificacion de datos",MB_OK); BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::Modificaciones1Click(TObject *Sender) { MiFormulario->Caption="Modificacion de datos"; if(PrimerNodo != NULL) { PanelCombo->Visible=true; Combo->Clear(); BotonGrabar->Visible=false; BotonLimpiar->Visible=true; BotonModificar->Visible=true; BotonEliminar->Visible=false; Simple1->Enabled=false; LlenarCombo(); } else Application->MessageBox("No hay datos para modificar","Lista vacia",MB_OK); } //---------------------------------------------------------------------------
A tu sistema le hará falta los siguientes accesorios...
void __fastcall TMiFormulario::BotonRegresarClick(TObject *Sender) { Panel->Visible=False; Simple1->Enabled=true; MiFormulario->Caption="Agenda de Wilo"; } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonVolverClick(TObject *Sender) { PanelVisualizar->Visible=false; } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::PorNombre1Click(TObject *Sender) { if(PrimerNodo != NULL) { Ordenar(ParametroOrdenar); } else Application->MessageBox("No hay datos para ordenar","Lista vacia",MB_OK); } void TMiFormulario::Ordenar(int ParametroOrdenar) { if(PrimerNodo!=NULL) { MiNodo *a,*b,*c; if (Application->MessageBox("Se Ordenarán los Elementos de la Lista","ORDENAR",MB_ICONEXCLAMATION+MB_OKCANCEL)==1) { a=PrimerNodo; while(a->SiguienteNodo!=NULL) { b=a->SiguienteNodo; while(b!=NULL) { if (strcmp(a->CampoNodoNombre,b->CampoNodoNombre)>0) { c=new(MiNodo); strcpy(c->CampoNodoNombre,a->CampoNodoNombre); strcpy(c->CampoNodoEmail,a->CampoNodoEmail); strcpy(a->CampoNodoNombre,b->CampoNodoNombre); strcpy(a->CampoNodoEmail,b->CampoNodoEmail); strcpy(b->CampoNodoNombre,c->CampoNodoNombre); strcpy(b->CampoNodoEmail,c->CampoNodoEmail); } b=b->SiguienteNodo; } a=a->SiguienteNodo; } } } else { Application->MessageBox("No Hay Datos","ORDENAR",MB_DEFBUTTON1+MB_ICONEXCLAMATION); } }
Para que la cosa sea más divertida te propongo que los términos de dicha serie se transformen en los elementos de una matríz cuadrada..!!
///////////////////////////////////////////////// // C++ Builder Wilo Carpio // MATRICES Y BIBONACCI ///////////////////////////////////////////////// #include#pragma hdrstop #include "DinoProy.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" ///////////////////////////////////////////////// // Declaracion de Variables Globales ///////////////////////////////////////////////// int mimatriz[5][5]; int mivector[5]; int fila,columna,grado,ant1=1,ant2=2; ///////////////////////////////////////////////// // Prototipo del formulario ///////////////////////////////////////////////// Tmiformulario *miformulario; ///////////////////////////////////////////////// // Activando el formulario ///////////////////////////////////////////////// __fastcall Tmiformulario::Tmiformulario(TComponent* Owner) : TForm(Owner) { } ///////////////////////////////////////////////// // Cerrando el programa ///////////////////////////////////////////////// void __fastcall Tmiformulario::botonsalirClick(TObject *Sender) { if (Application->MessageBox("¿Queres cerrar el Sistema?", "Fin del Programa", MB_OKCANCEL+MB_DEFBUTTON1|MB_ICONQUESTION)== IDOK) { Close(); } } ///////////////////////////////////////////////// // Cancelando generación de matríz ///////////////////////////////////////////////// void __fastcall Tmiformulario::botoncancelarClick(TObject *Sender) { boxdato->Clear(); }
El único dato que requieres es el grado de la matríz donde debes almacenar tu serie de Fibonacci
///////////////////////////////////////////////// // Ingreso del grado de la matríz ///////////////////////////////////////////////// void __fastcall Tmiformulario::botoninicioClick(TObject *Sender) { if (botoninicio->Caption=="Inicio") { boxdato->Visible=true; botonaceptar->Visible=true; botoncancelar->Visible=true; botoninicio->Caption="Cerrar"; boxdato->Text=3; boxdato->SetFocus(); miformulario->Caption="Ingrese el grado de la matriz"; } else { boxdato->Visible=false; botonaceptar->Visible=false; botoncancelar->Visible=false; botoninicio->Caption="Inicio"; miformulario->Caption="Fibonacci"; } }
El siguiente método te muestra una manera sencilla de generar la típica serie de fibonacci la cuál es cargada directamente a los elementos de una matríz cuadrada.
En la última parte apreciarás como transfiero la información generada para la matríz de manera que puedas visualizarla en un Memo Box.
///////////////////////////////////////////////// // Serie de Fibonacci ///////////////////////////////////////////////// void __fastcall Tmiformulario::botonaceptarClick(TObject *Sender) { boxdato->Visible=false; botonaceptar->Visible=false; botoncancelar->Visible=false; botoninicio->Caption="Inicio"; vermatriz->Visible=true; vermatriz->Clear(); botoninicio->Caption="Cerrar"; grado=StrToInt(boxdato->Text); miformulario->Caption="Grado de la matriz generada: "+IntToStr(grado); ///////////////////////////////////////////////// // Generando Serie de Fibonacci ///////////////////////////////////////////////// for(fila=1;fila<=grado;fila++) { for(columna=1;columna<=grado;columna++) { if((fila==1 && columna==1)||(fila==1 && columna==2)) { mimatriz[1][1]=1; mimatriz[2][1]=2; } else { mimatriz[columna][fila]= ant1+ ant2; ant1= ant2; ant2= mimatriz[columna][fila]; } } } ///////////////////////////////////////////////// // Generando Serie de Fibonacci ///////////////////////////////////////////////// for(fila=1;fila<=grado;fila++) { for(columna=1;columna<=grado;columna++) { vermatriz->Lines->Add(IntToStr(mimatriz[columna][fila])); } } } //---------------------------------------------------------------------------
El placer está tan cerca del dolor, que muchas veces lloramos de alegría..!!
Todos los algoritmos que te propongo funcionan correctamente, por lo tanto, solo te resta mejorarlos de acuerdo a tus propias necesidades.
Luego de editar la siguiente sintaxis, al compilar lograrás un sistema que te permitirá ver en acción a los objetos del grafico precedente.
Como podrás apreciar el siguiente ejemplo solo te permite efectuar altas de datos y luego la visualización de los mismos. Solo requieres armar los objetos de acuerdo a la imagen de los objetos de la parte superior de este link y asignarle los nombres que te indico en el siguiente programa.
A modo de introducción también te propongo algunos mecanismos de seguridad y amigabilidad en el procesamiento de un vector cuyo elemento posee dos campos tipo cadena.
Ah..!! Este primer ejemplo, con el fín de simplificar no posee archivo, por lo tanto los registros de datos son volátiles al cerrar el programa.
VECTOR Programa Fuente
///////////////////////////////////////////////////// // C++Builder 5 Wilo Carpio // // MANEJO BASICO DE UN VECTOR DE DOS CAMPOS // SIN ARCHIVO // //////////////////////////////////////////////////// //--------------------------------------------------------------------------- #include#pragma hdrstop #include "Fuente.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" /////////////////////////////////////// // // Declaracion de la Estructura ////////////////////////////////////// typedef struct registro { char Nombre[30], Email[30]; int Borrado; } MiRegistro; ////////////////////////////// // // Declaracion del Vector ////////////////////////////// MiRegistro MiVector[50]; //////////////////////////////////////////// // // Declaracion de las variables del Vector //////////////////////////////////////////// int i=0; int n=0; int Total,l; TMiFormulario *MiFormulario; //--------------------------------------------------------------------------- __fastcall TMiFormulario::TMiFormulario(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonSalirClick(TObject *Sender) { if (Application->MessageBox("Quieres cerrar el programa.?","Ojito.. QUE NO TENES ARCHIVO..!!",MB_DEFBUTTON1 + MB_OKCANCEL + MB_ICONQUESTION)==1) { Close(); } } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonAltasClick(TObject *Sender) { if(BotonAltas->Caption=="&Altas") { BotonAltas->Caption = "&Cerrar"; BoxNombre->Visible=true; BoxNombre->SetFocus(); BoxEmail->Visible=true; MiFormulario->Caption="DIGITA LOS NUEVOS DATOS"; Autor->Visible=false; } else { BotonAltas->Caption = "&Altas"; BoxNombre->Visible=false; BoxEmail->Visible=false; MiFormulario->Caption="VECTORES: Agenda sin archivo Wilo Carpio"; Autor->Visible=true; } } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BoxNombreChange(TObject *Sender) { if(!(BoxNombre->Text=="")) { GrabarAlta->Visible=true; } else { GrabarAlta->Visible=false; } } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::GrabarAltaClick(TObject *Sender) { i++; Total = i; strcpy(MiVector[i].Nombre,BoxNombre->Text.c_str()); strcpy(MiVector[i].Email,BoxEmail->Text.c_str()); MiFormulario->Caption="CARGADO: V("+IntToStr(i)+") = "+AnsiString(MiVector[i].Nombre); BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); BotonVer->Visible=true; } /////////////////////////////////////////////////////////////// // VISUALIZACION DE DATOS POR BOX MEMO Y POR GRILLA ////////////////////////////////////////////////////////////// void __fastcall TMiFormulario::BotonVerClick(TObject *Sender) { if(BotonVer->Caption=="&VerFichas") { ////////////////////////////////////////////// // Carga del vector en el BOX MEMO ////////////////////////////////////////////// MiFormulario->Caption="FICHAS CARGADAS: V( "+IntToStr(Total)+" ) "; BotonVer->Caption = "&Cerrar"; BoxMemo->Clear(); BoxMemo->Lines->Add("\t CONTENIDO"); BoxMemo->Lines->Add("\t =========="); BoxMemo->Visible=true; for(n=1;n<=Total;n++) BoxMemo->Lines->Add("V("+IntToStr(n)+") = "+AnsiString(MiVector[n].Nombre)); ////////////////////////////////////////////// // Carga de datos a la GRILLA ////////////////////////////////////////////// i=1; l=1; MiGrilla->Cells[0][0]="Nombre"; MiGrilla->Cells[1][0]="Email"; while (i<=Total) { MiGrilla->Cells[0][l]=MiVector[i].Nombre; MiGrilla->Cells[1][l]=MiVector[i].Email; i=i+1; l=l+1; } MiGrilla->Visible=true; } else { BotonVer->Caption = "&VerFichas"; BoxMemo->Visible=false; MiGrilla->Visible=false; MiFormulario->Caption="VECTORES: Agenda sin archivo Wilo Carpio"; } } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::MiGrillaClick(TObject *Sender) { MiFormulario->Caption="CONTENIDO DEL VECTOR"; i=1; l=1; MiGrilla->Cells[0][0]="Nombre"; MiGrilla->Cells[1][0]="Email"; while (i<=Total) { MiGrilla->Cells[0][l]=MiVector[i].Nombre; MiGrilla->Cells[1][l]=MiVector[i].Email; i=i+1; l=l+1; } MiGrilla->Visible=true; }
///////////////////////////////////////////////////// // C++Builder 5 Wilo Carpio // // MANEJO BASICO DE UN VECTOR DE DOS CAMPOS // SIN ARCHIVO // //////////////////////////////////////////////////// //--------------------------------------------------------------------------- #include#pragma hdrstop #include "Fuente.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" /////////////////////////////////////// // // Declaracion de la Estructura ////////////////////////////////////// typedef struct registro { char Nombre[30], Email[30]; int Borrado; } MiRegistro; ////////////////////////////// // // Declaracion del Vector ////////////////////////////// MiRegistro MiVector[50]; //////////////////////////////////////////// // // Declaracion de las variables del Vector //////////////////////////////////////////// int i=0; int n=0; int Total,l; TMiFormulario *MiFormulario; //--------------------------------------------------------------------------- __fastcall TMiFormulario::TMiFormulario(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonSalirClick(TObject *Sender) { if (Application->MessageBox("Quieres cerrar el programa.?","Ojito.. QUE NO TENES ARCHIVO..!!",MB_DEFBUTTON1 + MB_OKCANCEL + MB_ICONQUESTION)==1) { Close(); } } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonAltasClick(TObject *Sender) { if(BotonAltas->Caption=="&Altas") { BotonAltas->Caption = "&Cerrar"; BoxNombre->Visible=true; BoxNombre->SetFocus(); BoxEmail->Visible=true; MiFormulario->Caption="DIGITA LOS NUEVOS DATOS"; Autor->Visible=false; } else { BotonAltas->Caption = "&Altas"; BoxNombre->Visible=false; BoxEmail->Visible=false; MiFormulario->Caption="VECTORES: Agenda sin archivo Wilo Carpio"; Autor->Visible=true; } } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BoxNombreChange(TObject *Sender) { if(!(BoxNombre->Text=="")) { GrabarAlta->Visible=true; } else { GrabarAlta->Visible=false; } } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::GrabarAltaClick(TObject *Sender) { i++; Total = i; strcpy(MiVector[i].Nombre,BoxNombre->Text.c_str()); strcpy(MiVector[i].Email,BoxEmail->Text.c_str()); MiFormulario->Caption="CARGADO: V("+IntToStr(i)+") = "+AnsiString(MiVector[i].Nombre); BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); BotonVer->Visible=true; } /////////////////////////////////////////////////////////////// // VISUALIZACION DE DATOS POR BOX MEMO Y POR GRILLA ////////////////////////////////////////////////////////////// void __fastcall TMiFormulario::BotonVerClick(TObject *Sender) { if(BotonVer->Caption=="&VerFichas") { ////////////////////////////////////////////// // Carga del vector en el BOX MEMO ////////////////////////////////////////////// MiFormulario->Caption="FICHAS CARGADAS: V( "+IntToStr(Total)+" ) "; BotonVer->Caption = "&Cerrar"; BoxMemo->Clear(); BoxMemo->Lines->Add("\t CONTENIDO"); BoxMemo->Lines->Add("\t =========="); BoxMemo->Visible=true; for(n=1;n<=Total;n++) BoxMemo->Lines->Add("V("+IntToStr(n)+") = "+AnsiString(MiVector[n].Nombre)); ////////////////////////////////////////////// // Carga de datos a la GRILLA ////////////////////////////////////////////// i=1; l=1; MiGrilla->Cells[0][0]="Nombre"; MiGrilla->Cells[1][0]="Email"; while (i<=Total) { MiGrilla->Cells[0][l]=MiVector[i].Nombre; MiGrilla->Cells[1][l]=MiVector[i].Email; i=i+1; l=l+1; } MiGrilla->Visible=true; } else { BotonVer->Caption = "&VerFichas"; BoxMemo->Visible=false; MiGrilla->Visible=false; MiFormulario->Caption="VECTORES: Agenda sin archivo Wilo Carpio"; } } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::MiGrillaClick(TObject *Sender) { MiFormulario->Caption="CONTENIDO DEL VECTOR"; i=1; l=1; MiGrilla->Cells[0][0]="Nombre"; MiGrilla->Cells[1][0]="Email"; while (i<=Total) { MiGrilla->Cells[0][l]=MiVector[i].Nombre; MiGrilla->Cells[1][l]=MiVector[i].Email; i=i+1; l=l+1; } MiGrilla->Visible=true; }
Del anális de esto ejemplo ya estas en condición de deducir que:
Los vectores y las matrices en C, son manejados como estructuras de datos tipo ARREGLOS, que son grupos consecutivos de localidades de memoria a los cuales les asignamos un mismo nombre y un mismo tipo de dato.
Las magnitudes vectoriales y matriciales, forman parte de los datos estructurados que se caracterizan por ser variables del tipo subindicadas, pues en su estructura integran un valor indice que indica la ubicación de cada uno de sus elementos dentro del conjunto.
Estos datos requieren:
int MiMatriz[30][30];
int TuMatriz[50][30];
int MiMatriz[30][30], TuMatriz[50][30] Esta equivale a las dos anteriores.
MiMatriz[1][1] = 0;
int TuVector[4]= {69, 22, 14, 55}; ( Este ejemplo abarca declaración e inicialización )
MiMatriz[i][j] = TuMatriz[i][j] + EsaMatriz[x][y]
MiMatriz[i][j] = TuMatriz[i][j] - UnValor
MiMatriz[i][j] = TuMatriz[i][j] * 5
Tanto en C, como en C++, en Visual C++ y C++Builder, siempre el elemento inicial tiene como subíndice cero, por ello, el primer elemento si se trata de:
Fácilmente puedes deducir que el elemento enésimo será
Es necesario que los subíndices sean:
///////////////////////////////////////
// BUILDER C++ Wilo Carpio
// Editor de Texto V.1 15/9/2000
///////////////////////////////////////
#include vcl\vcl.h
#pragma hdrstop
#include "Principal.h"
#pragma resource "*.dfm"
///////////////////////////////////////
// Declarando Formulario Principal
///////////////////////////////////////
TMiFormulario *MiFormulario;
///////////////////////////////////////
// Habilitando Formulario Principal
///////////////////////////////////////
__fastcall TMiFormulario::TMiFormulario(TComponent* Owner) : TForm(Owner)
{
}
///////////////////////////////////////
// FUNCION LEER ARCHIVO
///////////////////////////////////////
void __fastcall TMiFormulario::BotonAbrirClick(TObject *Sender)
{
////////////////////////////////////////////////
// Leer el archivo indicado en BoxNombreArchivo
////////////////////////////////////////////////
try
{
MemoBox->Lines->LoadFromFile(BoxNombreArchivo->Text);
MemoBox->Visible=true;
BotonGrabar->Visible=true;
BotonCopy->Visible=true;
BotonCut->Visible=true;
BotonPaste->Visible=true;
}
catch(...)
{
ShowMessage("No es posible cargar el archivo");
}
MemoBox->SetFocus();
}
///////////////////////////////////////
// GRABAR TEXTO DEL MemoBox
///////////////////////////////////////
void __fastcall TMiFormulario::BotonGrabarClick(TObject *Sender)
{
int Opcion;
Opcion= Application->MessageBox("Asignaste un Nombre al Archivo", "GRABACION DE UNA NUEVA FICHA", MB_OKCANCEL+MB_DEFBUTTON1|MB_ICONQUESTION);
if (Opcion== IDOK)
{
////////////////////////////////////////////////
// Grabar el archivo indicado en BoxNombreArchivo
////////////////////////////////////////////////
try
{
MemoBox->Lines->SaveToFile(BoxNombreArchivo->Text);
}
catch(...)
{
ShowMessage("No es posible realizar la grabación");
}
MemoBox->SetFocus();
}
if (Opcion == IDCANCEL)
{
MiFormulario->Caption = "ELEGISTE BOTON CANCELAR";
}
}
///////////////////////////////////////
// COPIAR TEXTO MARCADO DEL MEMO
///////////////////////////////////////
void __fastcall TMiFormulario::BotonCopyClick(TObject *Sender)
{
////////////////////////////////////////////////
// Copiar texto marcado al portapapeles
////////////////////////////////////////////////
MemoBox->CopyToClipboard();
MemoBox->SetFocus();
}
///////////////////////////////////////
// CORTAR TEXTO MARCADO EN EL MEMO
///////////////////////////////////////
void __fastcall TMiFormulario::BotonCutClick(TObject *Sender)
{
////////////////////////////////////////////////
// Cortar texto marcado y pasar al portapapeles
////////////////////////////////////////////////
MemoBox->CutToClipboard();
MemoBox->SetFocus();
}
///////////////////////////////////////
// PEGAR TEXTO DEL BUFER
///////////////////////////////////////
void __fastcall TMiFormulario::BotonPasteClick(TObject *Sender)
{
////////////////////////////////////////////////
// Pegar texto del portapapeles al BoxMemo
////////////////////////////////////////////////
MemoBox->PasteFromClipboard();
MemoBox->SetFocus();
}
///////////////////////////////////////
// ABRIR NUEVO DOCUMENTO
///////////////////////////////////////
void __fastcall TMiFormulario::BotonNuevoClick(TObject *Sender)
{
////////////////////////////////////////////////
// Limpiar el BoxMemo
////////////////////////////////////////////////
MiFormulario->Caption="Escribe el nuevo documento";
BotonGrabar->Visible=true;
BotonCopy->Visible=true;
BotonCut->Visible=true;
BotonPaste->Visible=true;
MemoBox->Visible=true;
MemoBox->Clear();
MemoBox->SetFocus();
}
///////////////////////////////////////
// CERRAR FORMULARIO PRINCIPAL
///////////////////////////////////////
void __fastcall TMiFormulario::BotonSalirClick(TObject *Sender)
{
int Opcion;
Opcion= Application->MessageBox("Deseas Cerrar Este Programa", "FINALIZACION DEL SISTEMA", MB_OKCANCEL+MB_DEFBUTTON1|MB_ICONQUESTION);
if (Opcion== IDOK)
{
Close();
}
}
Editor de Archivos TXT: Ejemplo 2
///////////////////////////////////////
// BUILDER C++ Wilo Carpio
// Editor de Texto V.1 15/9/2000
///////////////////////////////////////
#include ///////////////////////////////////////
TMiFormulario *MiFormulario;
///////////////////////////////////////
__fastcall TMiFormulario::TMiFormulario(TComponent* Owner) : TForm(Owner)
///////////////////////////////////////
void __fastcall TMiFormulario::BotonAbrirClick(TObject *Sender)
////////////////////////////////////////////////
try
catch(...)
///////////////////////////////////////
void __fastcall TMiFormulario::BotonGrabarClick(TObject *Sender)
////////////////////////////////////////////////
///////////////////////////////////////
void __fastcall TMiFormulario::BotonCopyClick(TObject *Sender)
////////////////////////////////////////////////
MemoBox->CopyToClipboard();
///////////////////////////////////////
void __fastcall TMiFormulario::BotonCutClick(TObject *Sender)
////////////////////////////////////////////////
MemoBox->CutToClipboard();
///////////////////////////////////////
void __fastcall TMiFormulario::BotonPasteClick(TObject *Sender)
////////////////////////////////////////////////
MemoBox->PasteFromClipboard();
///////////////////////////////////////
void __fastcall TMiFormulario::BotonNuevoClick(TObject *Sender)
{
////////////////////////////////////////////////
MiFormulario->Caption="Escribe el nuevo documento";
///////////////////////////////////////
void __fastcall TMiFormulario::BotonSalirClick(TObject *Sender)
int Opcion;
if (Opcion== IDOK)
}
#pragma hdrstop
#include "Principal.h"
#pragma resource "*.dfm"
// Declarando Formulario Principal
///////////////////////////////////////
// Habilitando Formulario Principal
///////////////////////////////////////
{
}
// FUNCION LEER ARCHIVO
///////////////////////////////////////
{
// Leer el archivo indicado en BoxNombreArchivo
////////////////////////////////////////////////
{
MemoBox->Lines->LoadFromFile(BoxNombreArchivo->Text);
MemoBox->Visible=true;
BotonGrabar->Visible=true;
BotonCopy->Visible=true;
BotonCut->Visible=true;
BotonPaste->Visible=true;
}
{
ShowMessage("No es posible cargar el archivo");
}
MemoBox->SetFocus();
}
// GRABAR TEXTO DEL MemoBox
///////////////////////////////////////
{
int Opcion;
Opcion= Application->MessageBox("Asignaste un Nombre al Archivo", "GRABACION DE UNA NUEVA FICHA", MB_OKCANCEL+MB_DEFBUTTON1|MB_ICONQUESTION);
if (Opcion== IDOK)
{
// Grabar el archivo indicado en BoxNombreArchivo
////////////////////////////////////////////////
try
{
MemoBox->Lines->SaveToFile(BoxNombreArchivo->Text);
}
catch(...)
{
ShowMessage("No es posible realizar la grabación");
}
MemoBox->SetFocus();
}
if (Opcion == IDCANCEL)
{
MiFormulario->Caption = "ELEGISTE BOTON CANCELAR";
}
}
// COPIAR TEXTO MARCADO DEL MEMO
///////////////////////////////////////
{
// Copiar texto marcado al portapapeles
////////////////////////////////////////////////
MemoBox->SetFocus();
}
// CORTAR TEXTO MARCADO EN EL MEMO
///////////////////////////////////////
{
// Cortar texto marcado al portapapeles
////////////////////////////////////////////////
MemoBox->SetFocus();
}
// PEGAR TEXTO DEL BUFER
///////////////////////////////////////
{
// Pegar texto del portapapeles al BoxMemo
////////////////////////////////////////////////
MemoBox->SetFocus();
}
// ABRIR NUEVO DOCUMENTO
///////////////////////////////////////
// Limpiar el BoxMemo
////////////////////////////////////////////////
BotonGrabar->Visible=true;
BotonCopy->Visible=true;
BotonCut->Visible=true;
BotonPaste->Visible=true;
MemoBox->Visible=true;
MemoBox->Clear();
MemoBox->SetFocus();
}
// CERRAR FORMULARIO PRINCIPAL
///////////////////////////////////////
{
Opcion= Application->MessageBox("Deseas Cerrar Este Programa", "FINALIZACION DEL SISTEMA", MB_OKCANCEL+MB_DEFBUTTON1|MB_ICONQUESTION);
{
Close();
}
Especialmente si eres principiante te conviene copiar textualmente sus algoritmos, compilar y verificar que lograste esta primera pantalla de datos. Luego de ello, para familiarizarte con su manejo te recomiendo modificar los parámetros.
Con fines de simplificar la codificación y destacar los conceptos de los punteros, solo utilizó un solo objeto de visualización.
/////////////////////////////////////////////////////
// C++ BUILDER Wilo Carpio 2000
// Aplicacion de Punteros
// OPERACIONES MATEMATICAS
////////////////////////////////////////////////////
#include vcl\vcl.h>
////////////////////////////////////////////////////////////////
// CONSTANTES GLOBALES
///////////////////////////////////////////////////////////////
const char Autor[] = "C++ Builder Wilo Carpio 08/09/2000 \n\n";
const char Titulo[] = "VARIABLES DINAMICAS: MANEJO DE PUNTEROS";
const char Raya[] = "==========================================\n";
const char Concepto[] = "El puntero es una variable que almacena la direccion de una celda memoria, donde se almacena un dato\n";
const char Concept1[] = "Cualquiera sea el tipo del dato alojado en tal celda, los punteros son variables del mismo tipo\n";
const char Concept2[] = "\n Para declararlos la sintaxis es: TipoDatoDeSuCelda *NombreDelPuntero Ej: int *P \n";
const char Concept3[] = "\n Ej: declaremos 3 punteros: int *P,*Q,*R Luego les asignamos memoria: P=new int ; Q=new int ; R=new int \n";
const char Calculos[] = "\n\n\t Se obtienen estos Cálculos Numéricos \n";
const char SaltoRenglon = '\n';
FUNCION PRINCIPAL:
/////////////////////////////////////////////////////////
// VARIABLES GLOBALES
///////////////////////////////////////////////////////
int A;
float C;
///////////////////////////////////////////
// FUNCION PRINCIPAL
//////////////////////////////////////////
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
/////////////////////////////////
// Declaración de punteros
/////////////////////////////////
int *P, *Q, *R;
/////////////////////////////////
// Asignación de memoria
/////////////////////////////////
P = new int;
Q = new int;
R = new int;
/////////////////////////////////
// Visualizar Resultados
/////////////////////////////////
ShowMessage
(
AnsiString(Autor)+Titulo+AnsiString(SaltoRenglon)+Raya
+Concepto +Concept1 +Concept2 +Concept3
+ "\n Así obtendremos: \n"
+ "\n\t\t *P = " + AnsiString(*P)
+ "\n\t\t *Q = " + AnsiString(*Q)
+ "\n\t\t *R = " + AnsiString(*R)
);
Las asignaciones de cálculo se ajustan a la misma modalidad que se aplica en C++, por lo tanto puedes efectuar lo siguiente
//////////////////////////////////////
// Asignación de Valores a punteros
//////////////////////////////////////
*P = 30;
*Q = 7;
A = *P+*Q;
*R = *P-*Q;
C = (*P)/(*Q);
/////////////////////////////////
// Visualizar Resultados
/////////////////////////////////
ShowMessage
(
Autor+AnsiString(Titulo)+AnsiString(SaltoRenglon)+Raya+"\n\t Asignando los valores "
+ "\n *P = " + AnsiString(*P)
+ "\n *Q = " + AnsiString(*Q)
+ AnsiString(Calculos)
+ "\n SUMA: Asignación a una variable común: A = *P + *Q = " + AnsiString(A)
+ "\n RESTA: Asignación a una variable dinámica: *R = *P -- *Q = " + AnsiString(*R)
+ "\n PRODUCTO: *P x *Q = " + AnsiString(*P**Q)
+ "\n COCIENTE: C = (*P) / (*Q) = " + AnsiString(C)
);
/////////////////////////////////
// Operaciones de cálculo
/////////////////////////////////
/////////////////////////////////
// Liberación de Memoria
/////////////////////////////////
delete P;
delete Q;
delete R;
return 0;
}
Las estructuras dinámicas de datos son colecciones de elementos llamados NODOS, intervinculados por medio de PUNTEROS que permiten estructuras con capacidad de variar su tamaño y ocupar solo la memoria necesaria, creadas y se destruidas durante la ejecución.
Tales nodos de la estructura, generalmente del tipo registro, se enlazan o encadenan de modo que se establece un vículo o puntero asociando a cada nodo, que apunta al nodo siguiente de la estructura.
Existen diferentes tipos de estructuras dinámicas de datos, siendo las más usadas:
Para almacenar un nuevo valor en memoria se asigna a una variable, y la computadora envía una dirección a la memoria seguida por el valor a almacenar en esa posición.
DECLARACION de PUNTEROS
Para declarar un tipo puntero se indica el tipo de valor que se almacenará en la posicion designada por el puntero. Así cada puntero apunta a una variable particular, que es otra posición de memoria.
Dado que el puntero es una variable que registra la dirección de otra variable almacenada en una celda de memoria, es preciso diferenciar entre las dos entidades implicadas en el apuntamiento:
C++, Usa el asterisco (*) que sigue a los nodos, para indicar que "apunta a"; es decir el tipo de dato es una variable puntero que puede contener una dirección a un tipo de dato llamado nodo.
EJEMPLO: Para simplificar el tema, se ha tomado una agenda elemental de dos campos, nombre y email al que se le asignan los mecanismos de altas, bajas, modificaciones y consultas, en el que se incluye los algoritmos de búsqueda.
//////////////////////////////////////////////////////// // C++BUILDER 5 LISTA SIMPLE CON ARCHIV0 // ListaPrograma.cpp Wilucha 17/09/98 // Graba sobre en archivo Simple.txt //--------------------------------------------------------------------------- #include < vcl.h > #include < fstream.h > #include < stdlib.h > #pragma hdrstop #include "ListaPrograma.h" #pragma package(smart_init) #pragma resource "*.dfm" //--------------------------------------------------------------------------- TMiFormulario *MiFormulario; struct MiNodo { char CampoNodoNombre[30]; char CampoNodoEmail[40]; int FlagNodoBaja; struct MiNodo *SiguienteNodo; }
La ventaja de una lista enlazada sobre un arreglo es que la lista enlazada puede crecer y decrecer en tamaño y que fácil insertar o suprimir un nodo en el centro de una lista enlazada.
La lista enlazada es una estructura muy versátil, cuyos algoritmos para inserción y eliminación de datos constan de dos pasos:
ARCHIVO SECUENCIAL en C++BUILDER
La sintaxis para el área de buffer es: FILE *VariablePuntero;
Donde FILE es un tipo de dato estructurado que establece el área de buffer y VariablePuntero es la variable puntero que indica el principio de esta área. Tal puntero generalmente define un puntero a archivo secuencial, o simplemente como archivo secuencial.
struct UnaFicha { char CampoFichaNombre[30]; char CampoFichaEmail[40]; }; FILE *Archivo; UnaFicha MiFicha; //---------------------------------------------------------------------------
La gestión de un archivo, puede resumirse en las siguientes etapas:
Ej: fstream F ("Agenda", ios : :int | ios : :out );
Abrir un archivo existente y si no existe no lo crea
Ej: fstream F ("Agenda", ios : :nocreate );
Ej: ifstream F ("Agenda");
Ej: ofstream F ("Agenda");
Seekg( ): Se usa para determinar posicionamiento forzado:
Previo a ser creado o procesado el archivo de datos debe ser abierto, de modo de asociar el nombre de archivo con el área de buffer y especificar si se va a usar el archivo como sólo para lectura, o sólo para escritura, o para lectura / escritura.
La sintaxis para abrir el archivo es: VariablePuntero = fopen (NombreArchivo, ModoDeUso);
Donde NombreArchivo es la cadena que identifica el nombre del archivo y ModoDeUso es la manera en la que el archivo será utilizado y debe ser una de las cadenas de la siguiente tabla.
La función fopen retorna un puntero al principio del área de buffer asociada con el archivo si este se puedeabrir y caso contrario, retorna un valor NULL si no se puede abrir el archivo, por ejemplo si un archivo existente no ha sido encontrado.
Para terminar el archivo debe cerrarse al final de un programa, aplicando la función de biblioteca fclose.
La sintaxis para cerrar es: fclose(VariablePuntero);
//--------------------------------------------------------------------------- //BOTON PARA SALIR DEL FORMULARIO PRINCIPAL void __fastcall TMiFormulario::Salir1Click(TObject *Sender) { MiNodo *Auxiliar; Auxiliar=PrimerNodo; if(Application->MessageBox("Desea Salir","Atencion",MB_OKCANCEL)==IDOK) { Close(); Archivo=fopen("Simple.txt","wb"); while(Auxiliar != NULL) { strcpy(MiFicha.CampoFichaNombre,Auxiliar->CampoNodoNombre); strcpy(MiFicha.CampoFichaEmail,Auxiliar->CampoNodoEmail); fwrite(&MiFicha, sizeof(MiFicha),1,Archivo); Auxiliar=Auxiliar->SiguienteNodo; } fclose(Archivo); } }
Una vez realizadas todas las operaciones deseadas sobre el Archivo hay que cerrarlo. Al cerrarlo se vacían los buffers y se guarda el Archivo en disco. Un Archivo se cierra mediante la función fclose(Archivo). Si todo va bien fclose devuelve un cero, si hay problemas devuelve otro valor.
Estos problemas se pueden producir si el disco está lleno, por ejemplo.
if (fclose(Archivo)!=0) printf( "Problemas al cerrar el Archivo\n" ); }
Este proceso ha sido aplicado en el siguiente algoritmo..
//////////////////////////////////////////////////////// // C++BUILDER 5 LISTA SIMPLE CON ARCHIV0 // ListaPrograma.cpp Wilucha 17/09/98 // Graba sobre en archivo Simple.txt //--------------------------------------------------------------------------- *PrimerNodo,*NodoActual,*NuevoNodo,*UltimoNodo; MiNodo *FichaAuxiliar,FichaTrucha; int MensajePorBox,ParametroOrdenar,FlagBaja,Fila; int BuscarCodigo(AnsiString); void AltaDeNuevoNodo(char ParamNombre[30],char ParamEmail[40]) { NuevoNodo = new MiNodo[sizeof(MiNodo)]; strcpy(NuevoNodo->CampoNodoNombre,ParamNombre); strcpy(NuevoNodo->CampoNodoEmail,ParamEmail); NuevoNodo->FlagNodoBaja=0; NuevoNodo->SiguienteNodo=NULL; UltimoNodo=NuevoNodo; if(PrimerNodo==NULL) PrimerNodo=NuevoNodo; else { NodoActual=PrimerNodo; while(NodoActual->SiguienteNodo != NULL) NodoActual=NodoActual->SiguienteNodo; NodoActual->SiguienteNodo=NuevoNodo; } }
..Ojito observa que este proceso inserta nuevos nodos en la lista, pero no en el archivo..!!
//--------------------------------------------------------------------------- __fastcall TMiFormulario::TMiFormulario(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::FormActivate(TObject *Sender) { FlagBaja=0; } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::FormCreate(TObject *Sender) { Archivo = fopen("Simple.txt","rb"); while(!feof(Archivo)) { fread(&MiFicha,sizeof(MiFicha),1,Archivo); if(!feof(Archivo)) AltaDeNuevoNodo(MiFicha.CampoFichaNombre,MiFicha.CampoFichaEmail); } fclose(Archivo); } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::Altas1Click(TObject *Sender) { MiFormulario->Caption="INGRESO DE DATOS"; Panel->Visible=true; BotonGrabar->Visible=true; BotonLimpiar->Visible=true; BotonEliminar->Visible=false; BotonModificar->Visible=false; BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); Simple1->Enabled=false; } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonLimpiarClick(TObject *Sender) { BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); }
Por supuesto que los nodos dados de alta están vacios..!!!, por lo tanto veamos cómo les grabamos los datos en cada uno de sus campos...
void __fastcall TMiFormulario::BotonGrabarClick(TObject *Sender) { char Nombre[30], Email[40]; if((BoxNombre->Text=="")||(BoxEmail->Text=="")) Application->MessageBox("Introduzca datos","Atencion",MB_OK); else { strcpy(Nombre,BoxNombre->Text.c_str()); strcpy(Email,BoxEmail->Text.c_str()); if(BuscarNombre(Nombre)==0) { AltaDeNuevoNodo(Nombre,Email); LlenarCombo(); BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); } else { MensajePorBox=Application->MessageBox("Desea ingresarlo nuevamente","Dato existente",MB_OKCANCEL); if(MensajePorBox==IDOK) { strcpy(NodoActual->CampoNodoNombre,BoxNombre->Text.c_str()); strcpy(NodoActual->CampoNodoEmail,BoxEmail->Text.c_str()); BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); } else { BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); } } } } //---------------------------------------------------------------------------
Ahora ya tenemos nuestro trencito con los vagones cargados.. Oohh.!! perdón, tenemos la lista enlazada con sus nodos con datos en sus campos.
En los siguientes links, veremos las operaciones más comunes que podemos efectuar con estos nodos.
En este link encontrarás la codificación de los algoritmos para visualizar los datos que cargaste en cada uno de los nodos de tu estructura dinámica.
//--------------------------------------------------------------------------- void __fastcall TMiFormulario::Consultas1Click(TObject *Sender) { MiFormulario->Caption="Consulta de datos"; if(PrimerNodo != NULL) { PanelCombo->Visible=true; Combo->Clear(); BotonGrabar->Visible=false; BotonLimpiar->Visible=false; BotonEliminar->Visible=false; BotonModificar->Visible=false; LlenarCombo(); } else Application->MessageBox("No hay datos para consultar","Lista Vacia",MB_OK); } //---------------------------------------------------------------------------
Te ofrezco un combo..!!
//--------------------------------------------------------------------------- void TMiFormulario::LlenarCombo() { Combo->Clear(); Combo->Items->Clear(); NodoActual=PrimerNodo; while(NodoActual != NULL) { Combo->Items->Add(NodoActual->CampoNodoNombre); NodoActual=NodoActual->SiguienteNodo; } } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonAceptarClick(TObject *Sender) { int LoHalle; char DatoBuscado[40]; AnsiString DatoDelCombo; LoHalle=0; NuevoNodo=PrimerNodo; DatoDelCombo=Combo->Items->Strings[Combo->ItemIndex]; strcpy(DatoBuscado,DatoDelCombo.c_str()); while(NuevoNodo!=NULL) { if(stricmp(NuevoNodo->CampoNodoNombre,DatoBuscado)==0) { LoHalle=1; if(NuevoNodo->FlagNodoBaja!=1) { Panel->Visible=true; PanelCombo->Visible=false; BoxNombre->Text=NuevoNodo->CampoNodoNombre; BoxEmail->Text=NuevoNodo->CampoNodoEmail; NodoActual=NuevoNodo; NuevoNodo=NULL; } } else NuevoNodo=NuevoNodo->SiguienteNodo; } if(LoHalle==0) { ShowMessage("La ficha que busca no ha sido ingresada"); PanelCombo->Visible=false; } } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::Visualizar1Click(TObject *Sender) { Fila=1; if(PrimerNodo==NULL) { Application->MessageBox("No hay datos en la lista","Atencion...",MB_OK); } PanelVisualizar->Visible = true; if (PrimerNodo!=NULL) { Grilla->Cells[0][0]="Nombre"; Grilla->Cells[1][0]="Email"; NuevoNodo = PrimerNodo; while (NuevoNodo->SiguienteNodo!= NULL) { Grilla->Cells[0][Fila]=NuevoNodo->CampoNodoNombre; Grilla->Cells[1][Fila]=NuevoNodo->CampoNodoEmail; Fila=Fila+1; while ( Grilla->Cells[0][Fila+1]!="") { Grilla->Cells[0][Fila+1]=""; Grilla->Cells[1][Fila+1]=""; } NuevoNodo=NuevoNodo->SiguienteNodo; } Grilla->Cells[0][Fila]=NuevoNodo->CampoNodoNombre; Grilla->Cells[1][Fila]=NuevoNodo->CampoNodoEmail; } else { PanelVisualizar->Visible = false; } }
Si nos equivocamos.. no hay drama..!!, buscamos dónde está el error, lo borramos y a otra cosa.!!!
//--------------------------------------------------------------------------- int BuscarNombre(AnsiString UnNombre) { int HayDato=0; NodoActual=PrimerNodo; if (NodoActual!=NULL) while (NodoActual != NULL) { if ((UnNombre)==NodoActual->CampoNodoNombre) { HayDato=1; break; } NodoActual=NodoActual->SiguienteNodo; } return(HayDato); } void __fastcall TMiFormulario::Bajas1Click(TObject *Sender) { MiFormulario->Caption="Eliminacion de datos"; if(PrimerNodo != NULL) { PanelCombo->Visible=true; BotonGrabar->Visible=false; BotonLimpiar->Visible=false; BotonModificar->Visible=false; BotonEliminar->Visible=true; Simple1->Enabled=false; LlenarCombo(); FlagBaja=1; } else Application->MessageBox("No hay datos para eliminar","Lista vacia",MB_OK); } //---------------------------------------------------------------------------
//--------------------------------------------------------------------------- //BOTON PARA ELIMNAR LOS DATOS void __fastcall TMiFormulario::BotonEliminarClick(TObject *Sender) { if(PrimerNodo != NULL) { MensajePorBox=Application->MessageBox("Desea Eliminar estos datos","Eliminacion de datos",MB_OKCANCEL); if(MensajePorBox==IDOK) { FichaAuxiliar=NodoActual; if(NodoActual==PrimerNodo) PrimerNodo=NodoActual->SiguienteNodo; else { NodoActual=PrimerNodo; while(NodoActual->SiguienteNodo != NULL) { if(NodoActual->SiguienteNodo==FichaAuxiliar) { FichaTrucha,NodoActual; break; } NodoActual=NodoActual->SiguienteNodo; } FichaTrucha,FichaAuxiliar->SiguienteNodo; } delete(FichaAuxiliar); LlenarCombo(); Application->MessageBox("Los datos fueron eliminados","Eliminacion de datos",MB_OK); } } else Application->MessageBox("No hay datos a eliminar","La lista HayDato vacia",MB_OK); BoxNombre->Clear(); BoxEmail->Clear(); } //---------------------------------------------------------------------------
Si deseas corregir el contenido de un nodo en particular, lo ubicas a este y luego activas el siguiente algoritmo
//--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonModificarClick(TObject *Sender) { strcpy(NodoActual->CampoNodoNombre,BoxNombre->Text.c_str()); strcpy(NodoActual->CampoNodoEmail,BoxEmail->Text.c_str()); Application->MessageBox("Los datos ya han sido modificados","Modificacion de datos",MB_OK); BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::Modificaciones1Click(TObject *Sender) { MiFormulario->Caption="Modificacion de datos"; if(PrimerNodo != NULL) { PanelCombo->Visible=true; Combo->Clear(); BotonGrabar->Visible=false; BotonLimpiar->Visible=true; BotonModificar->Visible=true; BotonEliminar->Visible=false; Simple1->Enabled=false; LlenarCombo(); } else Application->MessageBox("No hay datos para modificar","Lista vacia",MB_OK); } //---------------------------------------------------------------------------
A tu sistema le hará falta los siguientes accesorios...
void __fastcall TMiFormulario::BotonRegresarClick(TObject *Sender) { Panel->Visible=False; Simple1->Enabled=true; MiFormulario->Caption="Agenda de Wilo"; } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonVolverClick(TObject *Sender) { PanelVisualizar->Visible=false; } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::Imprimir1Click(TObject *Sender) { int RespuestaDeBox; { RespuestaDeBox=Application->MessageBox("Tu impresora HayDato prendida?","Atencion",MB_OKCANCEL); if (RespuestaDeBox==IDOK) PrintDialog1->Execute(); } } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::PorNombre1Click(TObject *Sender) { if(PrimerNodo != NULL) { Ordenar(ParametroOrdenar); } else Application->MessageBox("No hay datos para ordenar","Lista vacia",MB_OK); } void TMiFormulario::Ordenar(int ParametroOrdenar) { if(PrimerNodo!=NULL) { MiNodo *a,*b,*c; if (Application->MessageBox("Se Ordenarán los Elementos de la Lista","ORDENAR",MB_ICONEXCLAMATION+MB_OKCANCEL)==1) { a=PrimerNodo; while(a->SiguienteNodo!=NULL) { b=a->SiguienteNodo; while(b!=NULL) { if (strcmp(a->CampoNodoNombre,b->CampoNodoNombre)>0) { c=new(MiNodo); strcpy(c->CampoNodoNombre,a->CampoNodoNombre); strcpy(c->CampoNodoEmail,a->CampoNodoEmail); strcpy(a->CampoNodoNombre,b->CampoNodoNombre); strcpy(a->CampoNodoEmail,b->CampoNodoEmail); strcpy(b->CampoNodoNombre,c->CampoNodoNombre); strcpy(b->CampoNodoEmail,c->CampoNodoEmail); } b=b->SiguienteNodo; } a=a->SiguienteNodo; } } } else { Application->MessageBox("No Hay Datos","ORDENAR",MB_DEFBUTTON1+MB_ICONEXCLAMATION); } }
///////////////////////////////////////////////////////////////// // C++BUILDER 5 LISTA SIMPLE CON ARCHIV0 // ListaPrograma.cpp Wilucha 22/09/02 //--------------------------------------------------------------- // Al iniciar el programa se transfieren los datos grabados en un // archivo secuencial a los nodos de una lista. //--------------------------------------------------------------- // Las operaciones ABM y consultas solo se hacen sobre los nodos //--------------------------------------------------------------- // Al terminar el programa se transfieren los datos registrados en // los nodos de una lista a un archivo secuencial. //--------------------------------------------------------------- #include < vcl.h > #include < fstream.h > #include < stdlib.h > #pragma hdrstop #include "ListaPrograma.h" #pragma package(smart_init) #pragma resource "*.dfm" //----------------------------------------------------------------- TMiFormulario *MiFormulario; ////////////////////////////////////////////////////////// // DECLARACION DE LA ESTRUCTURA DEL NODO ////////////////////////////////////////////////////////// struct MiNodo { char CampoNodoNombre[30]; char CampoNodoEmail[40]; int FlagNodoBaja; struct MiNodo *PunteroDeNodo; } ////////////////////////////////////////////////////////// // DECLARACION DE VARIABLES GLOBALES ////////////////////////////////////////////////////////// *PrimerNodo,*NodoActual,*NuevoNodo,*UltimoNodo; MiNodo *FichaAuxiliar,FichaTrucha; int MensajePorBox,ParametroOrdenar,FlagBaja,FilaNro; int BuscarCodigo(AnsiString); ////////////////////////////////////////////////////////// // DECLARACION DE LA ESTRUCTURA DE LA FICHA ////////////////////////////////////////////////////////// struct UnaFicha { char CampoFichaNombre[30]; char CampoFichaEmail[40]; }; ////////////////////////////////////////////////////////// // DECLARACION DEL ARCHIVO A USAR ////////////////////////////////////////////////////////// FILE *Archivo; UnaFicha MiFicha; ////////////////////////////////////////////////////////// // DECLARACION DEL UNICO FORMULARIO CONTENEDOR ////////////////////////////////////////////////////////// __fastcall TMiFormulario::TMiFormulario(TComponent* Owner) : TForm(Owner) { } ////////////////////////////////////////////////////////// // OPERACION AL ACTIVARSE EL FORMULARIO ////////////////////////////////////////////////////////// void __fastcall TMiFormulario::FormActivate(TObject *Sender) { FlagBaja=0; }
////////////////////////////////////////////////////////// // FUNCION PARA CREAR NUEVO NODO: Tiene 2 parámetros ////////////////////////////////////////////////////////// void AltaDeNuevoNodo(char ParamNombre[30],char ParamEmail[40]) { NuevoNodo = new MiNodo[sizeof(MiNodo)]; strcpy(NuevoNodo->CampoNodoNombre,ParamNombre); strcpy(NuevoNodo->CampoNodoEmail,ParamEmail); NuevoNodo->FlagNodoBaja=0; NuevoNodo->PunteroDeNodo=NULL; UltimoNodo=NuevoNodo; if(PrimerNodo==NULL) PrimerNodo=NuevoNodo; else { NodoActual=PrimerNodo; while(NodoActual->PunteroDeNodo != NULL) NodoActual=NodoActual->PunteroDeNodo; NodoActual->PunteroDeNodo=NuevoNodo; } } ////////////////////////////////////////////////////////// // FUNCIÓN PARA BUSCAR UN DATO EN LA LISTA ////////////////////////////////////////////////////////// int BuscarNombre(AnsiString UnNombre) { int HayDato=0; NodoActual=PrimerNodo; if (NodoActual!=NULL) while (NodoActual != NULL) { if ((UnNombre)==NodoActual->CampoNodoNombre) { HayDato=1; break; } NodoActual=NodoActual->PunteroDeNodo; } return(HayDato); } ////////////////////////////////////////////////////////// // CARGAR DATOS EN CAMPOS DEL NODO ////////////////////////////////////////////////////////// void __fastcall TMiFormulario::GrabarDatosDeBoxesClick(TObject *Sender) { char Nombre[30], Email[40]; if((BoxNombre->Text=="")||(BoxEmail->Text=="")) Application->MessageBox("Digita los datos","Atencion",MB_OK); else { strcpy(Nombre,BoxNombre->Text.c_str()); strcpy(Email,BoxEmail->Text.c_str()); if(BuscarNombre(Nombre)==0) { AltaDeNuevoNodo(Nombre,Email); LlenarCombo(); BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); } else { MensajePorBox=Application->MessageBox("Quieres volver a ingresarlo","OJITO: Dato existente..!!",MB_OKCANCEL); if(MensajePorBox==IDOK) { strcpy(NodoActual->CampoNodoNombre,BoxNombre->Text.c_str()); strcpy(NodoActual->CampoNodoEmail,BoxEmail->Text.c_str()); BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); } else { BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); } } } }
///////////////////////////////////////////////////////////////////// // ARCHIVOS SECUENCIALES ///////////////////////////////////////////////////////////////////// // Archivo = fopen("NombreDeArchivo","ModoDeUso") // Abro archivo secuencial "Simple.txt" en modo lectura "rb" //------------------------------------------------------------------ // fread(&MiFicha,sizeof(MiFicha),1,Archivo): Leo 1 ficha de Archivo //------------------------------------------------------------------ // fclose(Archivo) Cierra el archivo //////////////////////////////////////////////////////////////////// // CARGA de la LISTA con el ARCHIVO EXISTENTE: "Simple.txt" // Cada ficha se transfiere a cada nodo de la lista //////////////////////////////////////////////////////////////////// void __fastcall TMiFormulario::FormCreate(TObject *Sender) { Archivo = fopen("Simple.txt","rb"); while(!feof(Archivo)) { fread(&MiFicha,sizeof(MiFicha),1,Archivo); if(!feof(Archivo)) AltaDeNuevoNodo(MiFicha.CampoFichaNombre,MiFicha.CampoFichaEmail); } fclose(Archivo); } /////////////////////////////////////////////////////////////////////// // CARGA de los NODOS de la LISTA al ARCHIVO EXISTENTE: "Simple.txt" // Cada Nodo se transfiere a cada Ficha del archino // fwrite(&MiFicha, sizeof(MiFicha),1,Archivo): Grabo una ficha //////////////////////////////////////////////////////////////////// void __fastcall TMiFormulario::Salir1Click(TObject *Sender) { MiNodo *NodoAuxiliar; NodoAuxiliar=PrimerNodo; if(Application->MessageBox("Deseas grabar las modificaciones en el archivo..", "ESTAS POR CERRAR EL PROGRAMA", MB_OKCANCEL+ MB_DEFBUTTON1|MB_ICONQUESTION)==IDOK) { Close(); Archivo=fopen("Simple.txt","wb"); while(NodoAuxiliar != NULL) { strcpy(MiFicha.CampoFichaNombre,NodoAuxiliar->CampoNodoNombre); strcpy(MiFicha.CampoFichaEmail,NodoAuxiliar->CampoNodoEmail); fwrite(&MiFicha, sizeof(MiFicha),1,Archivo); NodoAuxiliar=NodoAuxiliar->PunteroDeNodo; } fclose(Archivo); } } ////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////// void __fastcall TMiFormulario::Altas1Click(TObject *Sender) { MiFormulario->Caption="INGRESO DE DATOS"; PanelAltas->Visible=true; GrabarDatosDeBoxes->Visible=true; BotonLimpiar->Visible=true; BotonEliminar->Visible=false; BotonModificar->Visible=false; BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); Simple1->Enabled=false; } ////////////////////////////////////////////////////////// // BOTON LIMPIAR DEL PANEL DE ALTAS ////////////////////////////////////////////////////////// void __fastcall TMiFormulario::BotonLimpiarClick(TObject *Sender) { BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); } ////////////////////////////////////////////////////////// // CARGAR ComboNombre CON CAMPO DE NODO ////////////////////////////////////////////////////////// void TMiFormulario::LlenarCombo() { ComboNombre->Clear(); ComboNombre->Items->Clear(); NodoActual=PrimerNodo; while(NodoActual != NULL) { ComboNombre->Items->Add(NodoActual->CampoNodoNombre); NodoActual=NodoActual->PunteroDeNodo; } }
////////////////////////////////////////////////////////// // ORDENAR NODOS POR BURBUJA ////////////////////////////////////////////////////////// void TMiFormulario::Ordenar(int ParametroOrdenar) { if(PrimerNodo!=NULL) { MiNodo *a,*b,*c; if (Application->MessageBox("Se Ordenarán los Elementos de la Lista","ORDENAR",MB_ICONEXCLAMATION+MB_OKCANCEL)==1) { a=PrimerNodo; while(a->PunteroDeNodo!=NULL) { b=a->PunteroDeNodo; while(b!=NULL) { if (strcmp(a->CampoNodoNombre,b->CampoNodoNombre)>0) { c=new(MiNodo); strcpy(c->CampoNodoNombre,a->CampoNodoNombre); strcpy(c->CampoNodoEmail,a->CampoNodoEmail); strcpy(a->CampoNodoNombre,b->CampoNodoNombre); strcpy(a->CampoNodoEmail,b->CampoNodoEmail); strcpy(b->CampoNodoNombre,c->CampoNodoNombre); strcpy(b->CampoNodoEmail,c->CampoNodoEmail); } b=b->PunteroDeNodo; } a=a->PunteroDeNodo; } } } else { Application->MessageBox("No Hay Datos","ORDENAR",MB_DEFBUTTON1+MB_ICONEXCLAMATION); } } ////////////////////////////////////////////////////////// // ORDENAR POR NOMBRES ////////////////////////////////////////////////////////// void __fastcall TMiFormulario::PorNombre1Click(TObject *Sender) { if(PrimerNodo != NULL) { Ordenar(ParametroOrdenar); } else Application->MessageBox("No hay datos para ordenar","Lista vacia",MB_OK); } ////////////////////////////////////////////////////////// // MODIFICACIONES ////////////////////////////////////////////////////////// void __fastcall TMiFormulario::Modificaciones1Click(TObject *Sender) { MiFormulario->Caption="Modificacion de datos"; if(PrimerNodo != NULL) { PanelCombo->Visible=true; ComboNombre->Clear(); GrabarDatosDeBoxes->Visible=false; BotonLimpiar->Visible=true; BotonModificar->Visible=true; BotonEliminar->Visible=false; Simple1->Enabled=false; LlenarCombo(); } else Application->MessageBox("No hay datos para modificar","Lista vacia",MB_OK); } ////////////////////////////////////////////////////////// // BAJAS ////////////////////////////////////////////////////////// void __fastcall TMiFormulario::Bajas1Click(TObject *Sender) { MiFormulario->Caption="Eliminacion de datos"; if(PrimerNodo != NULL) { PanelCombo->Visible=true; GrabarDatosDeBoxes->Visible=false; BotonLimpiar->Visible=false; BotonModificar->Visible=false; BotonEliminar->Visible=true; Simple1->Enabled=false; LlenarCombo(); FlagBaja=1; } else Application->MessageBox("No hay datos para eliminar","Lista vacia",MB_OK); } ////////////////////////////////////////////////////////// // REGRESAR ////////////////////////////////////////////////////////// void __fastcall TMiFormulario::BotonRegresarClick(TObject *Sender) { PanelAltas->Visible=False; Simple1->Enabled=true; MiFormulario->Caption="Agenda de Wilo"; } ////////////////////////////////////////////////////////// // BAJA DE NODO ////////////////////////////////////////////////////////// void __fastcall TMiFormulario::BotonEliminarClick(TObject *Sender) { if(PrimerNodo != NULL) { MensajePorBox=Application->MessageBox("Desea Eliminar estos datos","Eliminacion de datos",MB_OKCANCEL); if(MensajePorBox==IDOK) { FichaAuxiliar=NodoActual; if(NodoActual==PrimerNodo) PrimerNodo=NodoActual->PunteroDeNodo; else { NodoActual=PrimerNodo; while(NodoActual->PunteroDeNodo != NULL) { if(NodoActual->PunteroDeNodo==FichaAuxiliar) { FichaTrucha,NodoActual; break; } NodoActual=NodoActual->PunteroDeNodo; } FichaTrucha,FichaAuxiliar->PunteroDeNodo; } delete(FichaAuxiliar); LlenarCombo(); Application->MessageBox("Los datos fueron eliminados","Eliminacion de datos",MB_OK); } } else Application->MessageBox("No hay datos a eliminar","La lista HayDato vacia",MB_OK); BoxNombre->Clear(); BoxEmail->Clear(); } ////////////////////////////////////////////////////////// // MODIFICACIONES ////////////////////////////////////////////////////////// void __fastcall TMiFormulario::BotonModificarClick(TObject *Sender) { strcpy(NodoActual->CampoNodoNombre,BoxNombre->Text.c_str()); strcpy(NodoActual->CampoNodoEmail,BoxEmail->Text.c_str()); Application->MessageBox("Los datos ya han sido modificados","Modificacion de datos",MB_OK); BoxNombre->Clear(); BoxEmail->Clear(); BoxNombre->SetFocus(); }
////////////////////////////////////////////////////////// // CONSULTAS ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// // BUSQUEDA POR COMBO ////////////////////////////////////////////////////////// void __fastcall TMiFormulario::AceptarDatoComboClick(TObject *Sender) { int LoHalle; char DatoBuscado[40]; AnsiString DatoDelCombo; LoHalle=0; NuevoNodo=PrimerNodo; DatoDelCombo=ComboNombre->Items->Strings[ComboNombre->ItemIndex]; strcpy(DatoBuscado,DatoDelCombo.c_str()); while(NuevoNodo!=NULL) { if(stricmp(NuevoNodo->CampoNodoNombre,DatoBuscado)==0) { LoHalle=1; if(NuevoNodo->FlagNodoBaja!=1) { PanelAltas->Visible=true; PanelCombo->Visible=false; BoxNombre->Text=NuevoNodo->CampoNodoNombre; BoxEmail->Text=NuevoNodo->CampoNodoEmail; NodoActual=NuevoNodo; NuevoNodo=NULL; } } else NuevoNodo=NuevoNodo->PunteroDeNodo; } if(LoHalle==0) { ShowMessage("La ficha que busca no ha sido ingresada"); PanelCombo->Visible=false; } } ////////////////////////////////////////////////////////// // VOLVER ////////////////////////////////////////////////////////// void __fastcall TMiFormulario::BotonVolverClick(TObject *Sender) { PanelGrilla->Visible=false; } ////////////////////////////////////////////////////////// // VISUALIZACION DEL COMBO ////////////////////////////////////////////////////////// void __fastcall TMiFormulario::BuscarOpcionClick(TObject *Sender) { MiFormulario->Caption="Consulta de datos"; if(PrimerNodo != NULL) { PanelCombo->Visible=true; ComboNombre->Clear(); GrabarDatosDeBoxes->Visible=false; BotonLimpiar->Visible=false; BotonEliminar->Visible=false; BotonModificar->Visible=false; LlenarCombo(); } else Application->MessageBox("No hay datos para consultar","Lista Vacia",MB_OK); } ////////////////////////////////////////////////////////// // VER DATOS POR GRILLA ////////////////////////////////////////////////////////// void __fastcall TMiFormulario::GrillaOpcionClick(TObject *Sender) { FilaNro=1; if(PrimerNodo==NULL) { Application->MessageBox("No hay datos en la lista","Atencion...",MB_OK); } PanelGrilla->Visible = true; if (PrimerNodo!=NULL) { MiGrilla->Cells[0][0]="Nombre"; MiGrilla->Cells[1][0]="Email"; NuevoNodo = PrimerNodo; while (NuevoNodo->PunteroDeNodo!= NULL) { MiGrilla->Cells[0][FilaNro]=NuevoNodo->CampoNodoNombre; MiGrilla->Cells[1][FilaNro]=NuevoNodo->CampoNodoEmail; FilaNro=FilaNro+1; while ( MiGrilla->Cells[0][FilaNro+1]!="") { MiGrilla->Cells[0][FilaNro+1]=""; MiGrilla->Cells[1][FilaNro+1]=""; } NuevoNodo=NuevoNodo->PunteroDeNodo; } MiGrilla->Cells[0][FilaNro]=NuevoNodo->CampoNodoNombre; MiGrilla->Cells[1][FilaNro]=NuevoNodo->CampoNodoEmail; } else { PanelGrilla->Visible = false; } }
//--------------------------------------------------------------------------- void __fastcall TMiFormulario::SalirOpcionClick(TObject *Sender) { MiNodo *NodoAuxiliar; NodoAuxiliar=PrimerNodo; if(Application->MessageBox("Deseas grabar las modificaciones en el archivo..", "ESTAS POR CERRAR EL PROGRAMA", MB_OKCANCEL+ MB_DEFBUTTON1|MB_ICONQUESTION)==IDOK) { Close(); Archivo=fopen("Simple.txt","wb"); while(NodoAuxiliar != NULL) { strcpy(MiFicha.CampoFichaNombre,NodoAuxiliar->CampoNodoNombre); strcpy(MiFicha.CampoFichaEmail,NodoAuxiliar->CampoNodoEmail); fwrite(&MiFicha, sizeof(MiFicha),1,Archivo); NodoAuxiliar=NodoAuxiliar->PunteroDeNodo; } fclose(Archivo); } } ////////////////////////////////////////////////////////// // IMPRIMIR ////////////////////////////////////////////////////////// void __fastcall TMiFormulario::ImprimeOpcionClick(TObject *Sender) { if (Application->MessageBox("OJITO: Tu impresora está prendida..??","Atencion",MB_OKCANCEL)==IDOK) PrintDialog1->Execute(); } //---------------------------------------------------------------------------
Te propongo algoritmos para altas, bajas, consulta, búsqueda e impresión del contenido de la base
de datos. Si eres novell en estos menesteres, te recomiendo editar textualmente mi programa fuente, luego
compilar.
Dado que una base de datos es el contenedor de información registrada en tablas, conexiones ODBC y
procedimientos almacenados; podemos simplificar y afirmar que es el conjunto de tablas e índices
pertenecientes a un mismo sistema de información.
Para utilizar una tabla determinada de la base de datos, esta debe ser abierta de manera que tanto la tabla y la base de datos queden activados.
El sistema de gestión de bases de datos incorporado en la versión de C++ Bulder 5, se utiliza como diccionario de datos para apoyar el desarrollo de aplicaciones o su uso interactivo desde la ventana de database desktop.
Por ello, si modificamos un registro, las reglas de validación están automáticamente activas. Asi, si existe una condición que impide grabar un campo determinado con igual contenido, cuando se intenta actualizar el registro actual, se produce una advertencia de validación.
C++ Builder, permite además, guardar nombres largos de campo o su descripción, evitando el problema del uso de nombres crípticos por la limitación de la longitud de los nombres de campo, como ocurría antes.
Otra característica interesante de C++ Builder, son sus vistas o consultas SQL almacenadas en la base de datos, cuya particularidad es pueden hacerse uso como una tabla, de modo que puedes, abrirlas, cerrarlas o actualizar las tablas que han intervenido en tal consulta.
De acuerdo a la ubicación física de la tabla consultada podemos tener una:
La base de datos posee los procedimientos almacenados, que permiten incluir código que pueda ser usado desde que se activa la base de datos, pudiendo utilizar tal código, por ejemplo, para incluir una rutina de numeración automática de códigos para los registros que se vayan añadiendo a la tabla.
TABLA LIBRE: Es aquella que no pertenece a una base de datos, por tanto no posee características aplicadas a las tablas pertenecientes a una base de datos.
LA BASE DE DATOS PUEDE CONTENER
Se guarda información acerca de las columnas seleccionadas, los criterios de recuperación de registros, el orden de las filas o los campos actualizables.
Se guarda información acerca de las columnas seleccionadas, los criterios de recuperación de registros, el orden de las filas o los campos actualizables.
Esta información se utiliza posteriormente para generar vistas remota.
Los procedimientos contenidos en la base de datos están disponibles en tanto en cuanto la base de datos este abierta.
Contiene, además, el código relativo a las reglas de validación.
Por tanto, cada vez que se produce algún evento de inserción, modificación o eliminación, se ejecuta este código.
1.- CREAR BASE DE DATOS con VISUAL FOX
Escoja del menú archivo la opción nuevo (CTRL-N) o escoja el botón de comando nuevo de la barra de herramientas estándar.
Visualice a continuación el cuadro de dialogo para la elección del nuevo tipo de fichero a crear.
Escoja base de datos.
2.- CREAR BASE DE DATOS desde C++Builder
También puede pulsar el botón derecho en cualquier zona libre de la ventana del generador y escoger del menú subsiguiente la opción Nueva Tabla.
3.- CREAR BASE DE DATOS desde C++ Builder
USO de BASE DE DATOS
El primero crea la base de datos y abre el diseñador de base de datos.
El segundo necesita una base de datos abierta y activa. Si no es así, muestra el cuadro de dialogo Abrir para elegir la base de datos a modificar.
Para que se pueda acceder a la información de un contenedor de base de datos, es necesario, en primer lugar, abrir la base de datos mediante el comando OPEN DATABASE NombreArchivo.
Se puede abrir varias bases de datos a la vez.
Cuando se abre una base de datos, esta queda disponible, pero no activa. Esto quiere decir que algunos comandos y funciones no actuaran correctamente.
La razón es que trabajan sobre la base de datos activa; por tanto, no basta con abrir solo la base de datos, hay que activarla.
Para este ultimo cometido se ha de utilizar SET DATABASE TO [NombreBaseDatos].
Cerrar la base de datos activa es tan sencillo como utilizar el comando CLOSE DATABASE.
Cuando se abre y activa una base de datos, la función DBC() devuelve el nombre de la base de datos activa.
Si existe la seguridad de que una base de datos esta abierta, aunque no este activa, se puede confirmar mediante la función DBUSED (NombreBaseDatos).
De todos modos, aun se puede ir un poco mas allá y almacenar en una matriz todas las bases de datos abiertas. Este resultado se obtiene mediante la función ADATABASES().
Para eliminar físicamente del disco una base de datos se utiliza el comando DELETE DATABASE NombreBaseDatos. Este comando elimina los ficheros DBC, DCT y DCX relacionado con la base de datos. También elimina toda referencia a la base de datos en las tabas que contenía; por tanto, estas pasan a ser tablas libres.
CREAR TABLA de DATOS desde C++ Builder
USAR TABLA de DATOS desde C++ Builder
///////////////////////////////////////////////// // C++ BUILDER 5 BASE de DATOS // Con una tabla dbf // Wilo Carpio 30/11/20001 ///////////////////////////////////////////////// /////////////////////////////////////////////////// // DECLARACION DE VARIABLES GLOBALES /////////////////////////////////////////////////// AnsiString DatoBuscado;
CREANDO NUEVA FICHA
Para generar un nuevo tregistro puedes usar los procedimientos SQL o simplemente recurrir a la función Append() cuya sintaxis puedes apreciar en las siguientes lineas.
/////////////////////////////////////////////////// // ACTIVANDO BOTON ALTAS /////////////////////////////////////////////////// void __fastcall TMiFormulario::BotonAltasClick(TObject *Sender) { MiFormulario->Caption = "ALTA DE REGISTROS"; PanelAltas->Caption="Digita los datos, luego graba"; ActivoPanelAltas(); MuestroBoxDatos(); LimpioLosBoxes(); HabilitoBoxDatos(); BoxNombre->SetFocus(); }; /////////////////////////////////////////////////// // GRABACION DE UN REGISTRO EN LA TABLA /////////////////////////////////////////////////// void __fastcall TMiFormulario::GrabarDatosClick(TObject *Sender) { GrabarDatos->Visible=false; AceptarDatos->Visible=false; if (MiFormulario->Caption == "ALTA DE REGISTROS") { TLocateOptions Resultado; Resultado = Resultado < < loPartialKey; if (MiTabla - > Locate ( "nombre",BoxNombre->Text,Resultado)) { ShowMessage("Ese Mono Ya Está Grabado"); LimpioLosBoxes(); BoxNombre->SetFocus(); } else { MiTabla->Append(); LeoDatosDeBoxes(); MiTabla->Post(); LimpioLosBoxes(); BoxNombre->SetFocus(); } } else if (MiFormulario->Caption =="MODIFICAR REGISTRO") { MiTabla->Edit(); LeoDatosDeBoxes(); MiTabla->Post(); } else if (MiFormulario->Caption =="BAJA DE REGISTRO") { MiTabla->Delete(); MiTabla->Refresh(); }; }; /////////////////////////////////////////////////// // CERRANDO PANEL DE ALTAS /////////////////////////////////////////////////// void __fastcall TMiFormulario::CerrarAltasClick(TObject *Sender) { ActivoPanelABM(); }
GRILLAS DE DATOS
La manera más simple de visualizar el contenido de tu tabla es recurrir a la grilla de datos
/////////////////////////////////////////////////// // ACTIVANDO PANEL CON LA GRILLA DE DATOS /////////////////////////////////////////////////// void __fastcall TMiFormulario::BotonGrillaClick(TObject *Sender) { ActivoPanelGrilla(); }; void ActivoPanelGrilla(void) { MiFormulario->Caption="'GRILLA DE DATOS"; MiFormulario->PanelGrilla->Visible=true; MiFormulario->PanelABM->Visible=false ; }; /////////////////////////////////////////////////// // CERRANDO LA GRILLA /////////////////////////////////////////////////// void __fastcall TMiFormulario::CerrarGrillaMouseMove(TObject *Sender, TShiftState Shift, int X, int Y) { ActivoPanelABM(); }
ELIMINACION DE UNA FICHA
Para borrar un registro puedes recurrir a la función Delete()
/////////////////////////////////////////////////// // ACTIVANDO BOTON DE BAJAS /////////////////////////////////////////////////// void __fastcall TMiFormulario::BotonBajaClick(TObject *Sender) { MiFormulario->Caption="BAJA DE REGISTRO"; ActivoPanelAltas(); HabilitoBoxDatos(); CargoComboNombre(); } /////////////////////////////////////////////////// // ELIMINACION DE UN REGISTRO /////////////////////////////////////////////////// void __fastcall TMiFormulario::BorrarDatosClick(TObject *Sender) { MuestroBoxDatos(); BorrarDatos->Visible=false; if (Application->MessageBox("¿Deseas borrar estos datos..??","ELIMINACION DE UN REGISTRO",MB_YESNO + MB_DEFBUTTON2 + MB_ICONQUESTION ) == IDYES) { MiTabla->Delete(); MiTabla->Refresh(); ComboNombre->Text=""; LimpioLosBoxes(); }; };
MODIFICAR REGISTROS
/////////////////////////////////////////////////// // ACTIVANDO BOTON DE MODIFICACIONES /////////////////////////////////////////////////// void __fastcall TMiFormulario::BotonCambiosClick(TObject *Sender) { MiFormulario->Caption="MODIFICAR REGISTRO"; ActivoPanelAltas(); HabilitoBoxDatos(); CargoComboNombre(); } /////////////////////////////////////////////////// // CAMBIO DE CONTENIDO DE UN BOX /////////////////////////////////////////////////// void __fastcall TMiFormulario::BoxNombreChange(TObject *Sender) { if ((MiFormulario->Caption == "ALTA DE REGISTROS")||(MiFormulario->Caption =="MODIFICAR REGISTRO")) if (BoxNombre->Text == "") { GrabarDatos->Visible=false; } else { GrabarDatos->Visible=true; } };
BUSCANDO FICHAS
/////////////////////////////////////////////////// // OPCIONES DE OPTION GRUP PARA BUSCAR /////////////////////////////////////////////////// void __fastcall TMiFormulario::OpcionBuscarClick(TObject *Sender) { OpcionBuscar->Visible=false; if (OpcionBuscar->Items->Strings[OpcionBuscar->ItemIndex] == "Por Combo" ) { CargoComboNombre(); } else { PanelAltas->Caption="Digita nombre buscado"; ComboNombre->Visible=true; ComboNombre->SetFocus(); DatoBuscado=ComboNombre->Text; }; }; /////////////////////////////////////////////////// // ACTIVANDO BOTON DE BUSQUEDA /////////////////////////////////////////////////// void __fastcall TMiFormulario::BotonBuscarClick(TObject *Sender) { MiFormulario->Caption="BUSCAR REGISTRO"; PanelAltas->Caption="Clikea Opción de Buscar"; ActivoPanelAltas(); OpcionBuscar->Visible= true; } /////////////////////////////////////////////////// // CAMBIO DEL CONTENIDO DEL DISPLAY DEL COMBO /////////////////////////////////////////////////// void __fastcall TMiFormulario::ComboNombreChange(TObject *Sender) { if (MiFormulario->Caption =="BUSCAR REGISTRO") { VerDato->Visible=true; } else { AceptarDatos->Visible=true; }; } /////////////////////////////////////////////////// // FUNCION DE BUSQUEDA POR COMBO /////////////////////////////////////////////////// void BuscoMono(void) { LimpioLosBoxes(); MuestroBoxDatos(); MiFormulario->AceptarDatos->Visible=false; MiFormulario->VerDato->Visible=false; TLocateOptions Resultado; Resultado = Resultado<MiTabla->Locate("nombre",MiFormulario->ComboNombre->Text,Resultado)) { MiFormulario->BoxNombre->Text = MiFormulario->MiTabla->FieldByName("Nombre")->AsString; MiFormulario->BoxEmail->Text = MiFormulario->MiTabla->FieldByName("Email")->AsString; } else { ShowMessage("Ese mono NO EXISTE!!!"); }; MiFormulario->ComboNombre->Text=""; }; /////////////////////////////////////////////////// // CARGA DEL COMBO CON UN CAMPO /////////////////////////////////////////////////// void CargoComboNombre(void) { bool B; B=false; MiFormulario->PanelAltas->Caption="Selecciona Dato del combo"; MiFormulario->ComboNombre->Visible=true; MiFormulario->ComboNombre->Clear(); MiFormulario->ComboNombre->SetFocus(); MiFormulario->MiTabla->First(); while (B==False) { if (MiFormulario->MiTabla->Eof) { B=true; } else { MiFormulario->ComboNombre->Items->Add(MiFormulario->MiTabla->FieldValues["nombre"]); MiFormulario->MiTabla->Next(); } } }; /////////////////////////////////////////////////// // ACEPTAR DATO DEL DISPLAY DEL COMBO /////////////////////////////////////////////////// void __fastcall TMiFormulario::AceptarDatosClick(TObject *Sender) { AceptarDatos->Visible=false; BuscoMono(); if (MiFormulario->Caption =="BAJA DE REGISTRO") { BorrarDatos->Visible=true; }; } /////////////////////////////////////////////////// // MOSTRAR DATO DEL DISPLAY DEL COMBO /////////////////////////////////////////////////// void __fastcall TMiFormulario::VerDatoClick(TObject *Sender) { BuscoMono(); DesabilitoBoxDatos(); }
NAVEGANDO por la TABLA
/////////////////////////////////////////////////// // NAVEGADORES DE LA GRILLA /////////////////////////////////////////////////// void __fastcall TMiFormulario::PrimeroClick(TObject *Sender) { MiTabla->First(); } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::AnteriorClick(TObject *Sender) { MiTabla->Prior(); } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::SiguienteClick(TObject *Sender) { MiTabla->Next(); } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::UltimoClick(TObject *Sender) { MiTabla->Last(); }
FUNCIONES COMUNES
/////////////////////////////////////////////////// // FUNCIONES COMUNES DE CONTROL DEL PROGRAMA /////////////////////////////////////////////////// void ActivoPanelABM(void) { MiFormulario->Caption="PROGRAMA MODELO C++Builder: Wilo Carpio "+Date(); MiFormulario->PanelABM->Visible=true ; MiFormulario->PanelGrilla->Visible=false ; MiFormulario->PanelTeoria->Visible=false ; MiFormulario->PanelAltas->Visible=false; HabilitoBoxDatos(); MiFormulario->ComboNombre->Text=""; }; void ActivoPanelAltas(void) { MiFormulario->PanelABM->Visible=false ; MiFormulario->PanelGrilla->Visible=false ; MiFormulario->PanelTeoria->Visible=false ; MiFormulario->PanelAltas->Visible=true; MiFormulario->OpcionBuscar->Visible= false; MiFormulario->OpcionBuscar->ItemIndex=-1; MiFormulario->ComboNombre->Visible= false; MiFormulario->VerDato->Visible= false; MiFormulario->ComboNombre->Text=""; DesabilitoBoxDatos(); LimpioLosBoxes(); OcultarIconosABM(); OcultoBoxDatos(); }; void DesabilitoBoxDatos(void) { MiFormulario->BoxNombre->Enabled=false; MiFormulario->BoxEmail->Enabled=false; }; void HabilitoBoxDatos(void) { MiFormulario->BoxNombre->Enabled= true; MiFormulario->BoxEmail->Enabled= true; }; void OcultoBoxDatos(void) { MiFormulario->BoxNombre->Visible=false; MiFormulario->BoxEmail->Visible=false; }; void MuestroBoxDatos(void) { MiFormulario->BoxNombre->Visible=true; MiFormulario->BoxEmail->Visible= true; }; void OcultarIconosABM(void) { MiFormulario->GrabarDatos->Visible=false; MiFormulario->BorrarDatos->Visible=false; MiFormulario->AceptarDatos->Visible=false; MiFormulario->ComboNombre->Visible=false; }; void LeoDatosDeBoxes(void) { MiFormulario->MiTabla->FieldByName("Nombre")->AsString = MiFormulario->BoxNombre->Text; MiFormulario->MiTabla->FieldByName("Email")->AsString = MiFormulario->BoxEmail->Text; }; void LimpioLosBoxes(void) { MiFormulario->BoxNombre->Text=""; MiFormulario->BoxEmail->Text=""; }; /////////////////////////////////////////////////// // FUNCION DE SALIDA DEL PROGRAMA /////////////////////////////////////////////////// void __fastcall TMiFormulario::ChauMouseUp(TObject *Sender, TShiftState Shift, int X, int Y) { if (Application->MessageBox("Deseas cerrar el programa?","ESTAS POR CERRAR ESTE SISTEMA",MB_YESNO + MB_DEFBUTTON2 + MB_ICONQUESTION ) == IDYES) { MiFormulario->Close(); }; };
MODOS de IMPRIMIR
/////////////////////////////////////////////////// // ACTIVANDO BOTON DEL PANEL CON TEORIA /////////////////////////////////////////////////// void __fastcall TMiFormulario::BotonTeoriaClick(TObject *Sender) { PanelTeoria->Visible=true; PanelABM->Visible=false; Autor->Visible=true; } /////////////////////////////////////////////////// // CERRANDO PANEL DE TEORIA /////////////////////////////////////////////////// void __fastcall TMiFormulario::CerrarAutorClick(TObject *Sender) { PanelABM->Visible=true; PanelTeoria->Visible=false; } /////////////////////////////////////////////////// // ACTIVANDO IMPRESION DE TEORIA /////////////////////////////////////////////////// void __fastcall TMiFormulario::ImprimoTeoriaClick(TObject *Sender) { MiFormulario->Caption="ESTAS POR IMPRIMIR LA TEORIA"; if (Application->MessageBox("¿Deseas imprimir estos datos.??","IMPRESION DE DATOS DE LA TEORIA",MB_YESNO + MB_DEFBUTTON2 + MB_ICONQUESTION ) == IDYES) { if (Application->MessageBox("¿Está activada tu impresora.??","IMPRESION DE DATOS DE LA TEORIA", MB_YESNO + MB_DEFBUTTON2 + MB_ICONQUESTION ) == IDYES) { PrintDialog->Execute(); BoxConTeoria->Print("MyApp.exe - readme.txt"); }; }; MiFormulario->Caption="ESTAS POR IMPRIMIR DATOS DE LA GRILLA"; if (Application->MessageBox("¿Deseas imprimir estos datos.??","IMPRESION DE DATOS DE LA GRILLA",MB_YESNO + MB_DEFBUTTON2 + MB_ICONQUESTION ) == IDYES) { if (Application->MessageBox("¿Está activada tu impresora.??","IMPRESION DE DATOS DE LA GRILLA",MB_YESNO + MB_DEFBUTTON2 + MB_ICONQUESTION ) == IDYES) { PrintDialog->Execute(); TPrinter *Prntr = Printer(); Graphics::TBitmap *bmp = new Graphics::TBitmap(); bmp->LoadFromFile("c:\Archivos de programa\Borland\CBuilder5\Projets\BDB2001Wilo\BebeWilo.bmp"); Prntr->BeginDoc(); Prntr->Canvas->Draw((Prntr->PageWidth - bmp->Width),(Prntr->PageHeight - bmp->Height),bmp); Prntr->EndDoc(); delete bmp; }; }; } /////////////////////////////////////////////////// // IMPRESION DE LA TABLA CON Quick REPORT /////////////////////////////////////////////////// void __fastcall TMiFormulario::ImprimoGrillaClick(TObject *Sender) { MiFormulario->Caption="ESTAS POR IMPRIMIR EL CONTENIDO DE LA TABLA"; if (Application->MessageBox("¿Deseas imprimir estos datos.??","IMPRESION DE DATOS DE LA TABLA", MB_YESNO + MB_DEFBUTTON2 + MB_ICONQUESTION ) == IDYES) { if (Application->MessageBox("¿Está activada tu impresora.??","IMPRESION DE DATOS DE LA TABLA", MB_YESNO + MB_DEFBUTTON2 + MB_ICONQUESTION ) == IDYES) { MiReporte->QuickRep1->Preview(); }; }; }
En este link, el enfoque tanto de las colas y de las pilas es puramente algorítmico y como estructuras lineales de datos tratadas como con enlaces estáticos o mediante enlaces dinámicos.
Colega algorítmico, te ofrezco un sistema integral con las operaciones básicas y clásicas que pueden
efectuarse con estas estructuras dinámicas... Ah pero ..
CONCEPTOS BASICOS:
La pila es una versión restringida de una lista enlazada, ya que los nuevos nodos solo pueden agregarse a una pila y eliminarse de una pila desde la parte superior de ésta. El miembro de enlace del último nodo de la pila está establecido a nulo (cero) para indicar el fondo de la pila.
En el mundo de los programas informáticos las pilas tienen aplicaciones como por ejemplo, cuando se realiza una llamada de función, la función llamada debe saber la manera de regresar a su invocador, y por esto la dirección de devolución se pone en una pila. También los compiladores utilizan a las pilas en el proceso de evaluación de expresiones y en la generación de código de lenguaje de maquina.
Cuando sucede una serie de llamadas de función, los valores de devolución sucesivos se ponen en la pila en un orden último en entrar, primero en salir, para que cada función pueda regresar a su invocador. Las pilas soportan las llamadas de función recursivas en la misma forma que lo hacen con las llamadas no recursivas convencionales.
Las pilas contienen el espacio que se crea para las variables automáticas en cada llamada a una función. Cuando la función regresa a su invocador, el espacio para las variables automáticas de la función se saca de la pila, y de ésta manera el programa ya no conoce dichas variables.
Como una pila es una lista, podemos plantear dos técnicas de proceso.
METER Y SACAR...!!
Primero implantamos la pila con cabecera. Después se examina una pila vacía en la misma manera que una lista vacía.
La creación de una pila vacía requiere crear una cabecera con un apuntador siguiente a NULL. El meter se implanta como inserción al frente de la lista enlazada, donde el frente de la lista se conoce como cima de la pila. La cima se efectúa examinando el elemento de la primera posición de la lista. Por ultimo, implantaremos sacar eliminando el frente de la lista.
Todas las operaciones tardan un tiempo constante, por que en ninguna de las rutinas tiene referencia al tamaño de la pila ( excepto en la comprobación de si esta vacía ); tampoco se encuentra un ciclo que dependa del tamaño.
ARREGLOS
Es la alternativa que evita los apuntadores y probablemente es la solución mas utilizada y solo se necesita declarar el tamaño de un arreglo con anticipación. Para ello en aplicaciones típicas, aun si se tienen muy pocas operaciones con pilas, el numero de elementos en la pila no crece demasiado y siempre es fácil declarar el arreglo suficientemente grande sin desperdiciar demasiado espacio.
En el proceso con arreglos con arreglos, cada pila tiene la cima de la pila, la cual es 0 para una pila vacía. Para meter algún elemento x en la pila, se debe incrementar la cima de la pila y después se hace PILA ( cima de la pila ) = x; donde PILA es el arreglo que representa la pila real.
Para sacar, se devuelve el valor de PILA ( cima de la pila ) y después se decrementa la cima de la pila. Por supuesto, ya que puede haber varias pilas, el arreglo PILA y la cima de la pila son parte de un registro que representa una pila.
Las operaciones se realizan no solo en tiempos constantes, sino en un tiempo muy corto y en algunas maquinas, meter y sacar se pueden escribir en una sola instrucción de maquina y operar en un arreglo de direccionamiento con auto incremento y auto decremento.
Dado que la mayoría de las maquinas modernas tienen operaciones sobre pilas como parte del conjunto de instrucciones refuerza la idea de que la pila es probablemente la estructura de datos más importante en informática, después del arreglo.
Suele ocurrir que un problema del procesamiento de pilas como arreglos es la comprobación de errores; un sacar de una pila vacía o un meter en una pila llena excederá los limites del arreglo y causara una ruptura.
Si se incluyen tales comprobaciones en la implantación de arreglos podrían tomar tanto tiempo como la manipulación de la pila. Por esta razón, puede convenir omitir la comprobación de errores en las rutinas de pilas, excepto cuando el manejo de errores sea crucial, tal ocurre en los sistemas operativos.
Se puede resolver este problema declarando un tamaño de la pila suficiente para no excederlo y asegurándose de que las rutinas que usan sacar y meter nunca intenten sacar de una pila vacía.
Las filas de espera también llamadas colas, se producen cada vez que hacemos cola en la caja del comercio, cuando cargamos combustible en el automóvil, cuando abordamos un autobús, cuando pagamos en la caseta de cobro de la autopista; los estudiantes hacen cola para inscribirse en las materias que quieren y en los sistemas informáticos usamos internamente muchas colas de espera.
En estas estructuras de datos abstractos, los usuarios hacen altas o ponen cosas en ellas, una a la vez mediante una operación de encolamiento, y las retiran o dan de baja, un elemento a la vez por medio de una operación de desencolamiento.
Aunque en teoría la cola puede ser infinitamente grande, en la práctica, ella es finita y sus elementos se devuelven de la cola en orden de FIFO (Firts In Firts Out: primero en entrar, primero en salir): el primer elemento que entra en la cola es el primero en ser retirado de ella.
Del mismo modo que las pilas, también las colas son listas. Con una cola, no obstante, la inserción se hace por un extremo, mientras que la eliminación se realiza por el otro extremo.
Las operaciones básicas sobre una cola son encolar, que inserta un elemento al final de la lista, y dar de
baja o desencolar, para eliminar el elemento del inicio de la lista o frente.
COLAS COMO ARREGLOS:
////////////////////////////////////////////////////// // ESTRUCTURA DINAMICA DE DATOS Wilo Carpio // MANEJO DE PILA Y COLA // C++ Builder ////////////////////////////////////////////////////// #include//Para reconocer los tipos de datos ingresados #pragma hdrstop #include #include "PilaYCola.h" //Archivo de cabecera pila y cola.h #pragma package(smart_init) #pragma resource "*.dfm" TMiFormulario *MiFormulario; struct Registro { char NombrePila[30]; // Para la pila char EmailPila[40]; // Para la pila char NombreCola[30]; // Para la cola char EmailCola[30]; // Para la cola int EstaEnPila,EstaEnCola; // Flag de borrado struct Registro *SiguientePila,*SiguienteCola; }*NodoPila,*NodoCola,*NodoAuxPila,*NodoAuxCola,*AuxCola,*CabeceraPila, *CabeceraCola ,*Ultimo,*Primero; struct Persona { char NombrePila[30]; char EmailPila[40]; char NombreCola[30]; char EmailCola[40]; }; Persona MonoPila,MonoCola; int bandera, i, j; char NombrePila[30],EmailPila[30]; char NombreCola[30],EmailCola[30]; AnsiString NombreEnPila, NombreEnCola; //////////////////////////////////////////////////////////////// //*procedimiento de busqueda para validar los datos en la pila// //////////////////////////////////////////////////////////////// int BuscarEnLaPila(AnsiString NombreEnPila) { int EstaEnLaPila=0; NodoPila=CabeceraPila; if (NodoPila!=NULL) while (NodoPila != NULL) { if ((NombreEnPila)==NodoPila->NombrePila) { EstaEnLaPila=1; break; } NodoPila=NodoPila->SiguientePila; } return(EstaEnLaPila); } /////////////////////////////////////////////////////////////// // Busqueda para validar los datos en la cola /////////////////////////////////////////////////////////////// int BuscarEnLaCola(AnsiString NombreEnCola) { int EstaEnLaCola=0; NodoCola=CabeceraCola; if (NodoCola!=NULL) while (NodoCola != NULL) { if ((NombreEnCola)==NodoCola->NombreCola) { EstaEnLaCola=1; break; } NodoCola=NodoCola->SiguienteCola; } return(EstaEnLaCola); } ///////////////////////////////////////////////////////////////////// // Liberar memoria e insertar los datos en la pila ///////////////////////////////////////////////////////////////////// void InsertarEnPila(char NombrePila[30], char EmailPila[40]) // { NodoPila=new Registro [sizeof (Registro)]; // new asigna memoria al puntero strcpy(NodoPila->NombrePila,NombrePila); // strcpy copia dos cadenas strcpy(NodoPila->EmailPila,EmailPila); NodoPila->EstaEnPila=0; //valor que sirve para la eliminacion NodoPila->SiguientePila=NULL; if (CabeceraPila == NULL) CabeceraPila = NodoPila; else { NodoPila->SiguientePila = CabeceraPila; CabeceraPila = NodoPila; } if (bandera==0) ShowMessage("Informacion registrada..!!"); } /////////////////////////////////////////////////////////////////////// // Liberar memoria e insertar los datos en la cola ///////////////////////////////////////////////////////////////////// void InsertarEnCola(char NombreCola[30], char EmailCola[30]) //*void palabra reservada que no va a apuntar a ningun tipo { NodoCola=new Registro [sizeof (Registro)]; strcpy(NodoCola->NombreCola,NombreCola); strcpy(NodoCola->EmailCola,EmailCola); NodoCola->EstaEnCola=0; //Sirve para la eliminacion NodoCola->SiguienteCola=NULL; if (CabeceraCola == NULL) { CabeceraCola = NodoCola; CabeceraCola->SiguienteCola=NULL; Primero= CabeceraCola; } else { Primero->SiguienteCola = NodoCola; NodoCola->SiguienteCola = NULL; Primero = NodoCola; } if (bandera==0) ShowMessage("Informacion Registrada"); } //--------------------------------------------------------------------------- __fastcall TMiFormulario::TMiFormulario(TComponent* Owner) : TForm(Owner) { } void __fastcall TMiFormulario::BRPAClick(TObject *Sender) { MiFormulario->PanelAutor->Visible=false; } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::FormCreate(TObject *Sender) { MiFormulario->PanelAutor->Visible=false; } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::Autor1Click(TObject *Sender) { MiFormulario->PanelAutor->Visible=true; }
void __fastcall TMiFormulario::Altas1Click(TObject *Sender) { MiFormulario->Caption=("Digita los datos de la agenda"); bandera=0; PanelPila->Visible=true; BoxNombreP->Clear(); BoxEmailP->Clear(); BoxNombreP->SetFocus(); BoxNombreP->SetFocus(); } //--------------------------------------------------------------------------- //Grabar los datos en la agenda ingresados en la pila void __fastcall TMiFormulario::BotonGrabarPClick(TObject *Sender) { int Mensaje; char NombrePila[30], EmailPila[40]; if((BoxNombreP->Text!="")||(BoxEmailP->Text!="")) { strcpy(NombrePila,BoxNombreP->Text.c_str()); strcpy(EmailPila,BoxEmailP->Text.c_str()); if(BuscarEnLaPila(NombrePila)==0) { InsertarEnPila(NombrePila,EmailPila); BoxNombreP->Clear(); BoxEmailP->Clear(); BoxNombreP->SetFocus(); } else { Mensaje=Application->MessageBox("Desea ingresarlo nuevamente","Dato existente",MB_OKCANCEL); if(Mensaje==IDOK) { strcpy(NodoPila->NombrePila,BoxNombreP->Text.c_str()); strcpy(NodoPila->EmailPila,BoxEmailP->Text.c_str()); BoxNombreP->Clear(); BoxEmailP->Clear(); BoxNombreP->SetFocus(); } else { BoxNombreP->Clear(); BoxEmailP->Clear(); BoxNombreP->SetFocus(); } } } } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonLimpiarPClick(TObject *Sender) //procedimiento para limpiar los box en caso de arrepentirme de haber ingresado algun dato// { BoxNombreP->Clear(); BoxEmailP->Clear(); BoxNombreP->SetFocus(); } void __fastcall TMiFormulario::BotonGrabarCClick(TObject *Sender) { int Mensaje; char NombreCola[30], EmailCola[40]; if((BoxNombreC->Text!="")||(BoxEmailC->Text!="")) { strcpy(NombreCola,BoxNombreC->Text.c_str()); strcpy(EmailCola,BoxEmailC->Text.c_str()); if(BuscarEnLaCola(NombreCola)==0) { InsertarEnCola(NombreCola,EmailCola); BoxNombreC->Clear(); BoxEmailC->Clear(); BoxNombreC->SetFocus(); } else { Mensaje=Application->MessageBox("Desea ingresarlo nuevamente","Dato existente",MB_OKCANCEL); if(Mensaje==IDOK) { strcpy(NodoCola->NombreCola,BoxNombreC->Text.c_str()); strcpy(NodoCola->EmailCola,BoxEmailC->Text.c_str()); BoxNombreC->Clear(); BoxEmailC->Clear(); BoxNombreC->SetFocus(); } else { BoxNombreC->Clear(); BoxEmailC->Clear(); BoxNombreC->SetFocus(); } } } } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::Altas2Click(TObject *Sender) { MiFormulario->Caption=("Ingresa los datos en la agenda"); bandera=0; PanelCola->Visible=true; BoxNombreC->Clear(); BoxEmailC->Clear(); BoxNombreC->SetFocus(); } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonLimpiarCClick(TObject *Sender) { BoxNombreC->Clear(); BoxEmailC->Clear(); BoxNombreC->SetFocus(); } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonVolverCClick(TObject *Sender) { MiFormulario->Caption=("Agenda con Pilas y Colas"); PanelCola->Visible = false; }
void __fastcall TMiFormulario::BotonVolverPClick(TObject *Sender) //procedimiento para retornar al formulario principal// { MiFormulario->Caption=("Agenda con Pilas y Colas"); PanelPila->Visible = false; } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::Visualizacion1Click(TObject *Sender) //procedimiento para visualizar los datos en la grilla introducidos en el procedimiento de la pila// { MiFormulario->Caption=("Los datos en la agenda son:"); i=1; if(CabeceraPila==NULL) { Application->MessageBox("No hay datos en la lista","Atencion...",MB_OK); } PanelVisualizarP->Visible = true; if (CabeceraPila!=NULL) { GrillaPila->Cells [0][0]="Nombre"; GrillaPila->Cells[1][0]="EmailPila"; NodoAuxPila = CabeceraPila; while (NodoAuxPila->SiguientePila!= NULL) { GrillaPila->Cells[0][i]=NodoAuxPila->NombrePila; GrillaPila->Cells[1][i]=NodoAuxPila->EmailPila; i=i+1; while ( GrillaPila->Cells[0][i+1]!="") { GrillaPila->Cells[0][i+1]=""; GrillaPila->Cells[1][i+1]=""; } NodoAuxPila=NodoAuxPila->SiguientePila; } GrillaPila->Cells[0][i]=NodoAuxPila->NombrePila; GrillaPila->Cells[1][i]=NodoAuxPila->EmailPila; } else { PanelVisualizarP->Visible = false; } } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonRegresarPClick(TObject *Sender) //procedimiento para retornar al formulario principal*// { MiFormulario->Caption=("Agenda con Pilas y Colas"); PanelVisualizarP->Visible = false; } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::Consultas1Click(TObject *Sender) //*procedimiento para consultar un dato en el combo// { MiFormulario->Caption=("Elija el nombre a consultar"); PanelBuscarPila->Visible = true; bandera=4; //*si es una consulta Registro *Actual; Actual = CabeceraPila; ComboPila->Clear(); while (Actual!=NULL) { ComboPila->Items->Add(Actual->NombrePila); Actual=Actual->SiguientePila; } } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonAceptarPilaClick(TObject *Sender) { MiFormulario->Caption=("El nombre elegido es:"); int encontrado; char bus[40]; AnsiString var; encontrado=0; NodoAuxPila=CabeceraPila; var=ComboPila->Items->Strings[ComboPila->ItemIndex]; strcpy(bus,var.c_str()); while (NodoAuxPila !=NULL ) { //funcion de busqueda if (stricmp(NodoAuxPila->NombrePila,bus)==0) { encontrado=1; if (bandera==1) //si es una modificacion { if (NodoAuxPila->EstaEnPila!=1) { BotonGrabarP->Visible=true; BotonLimpiarP->Visible=true; PanelPila->Visible=true; PanelBuscarPila->Visible=false; BoxNombreP->Text=NodoAuxPila->NombrePila; BoxEmailP->Text=NodoAuxPila->EmailPila; NodoAuxCola=NodoAuxPila; NodoAuxPila=NULL; } } else { if(bandera==4) { if (NodoAuxPila->EstaEnPila!=1) { BotonGrabarP->Visible=false; BotonLimpiarP->Visible=false; PanelPila->Visible=true; PanelBuscarPila->Visible=false; BoxNombreP->Text=NodoAuxPila->NombrePila; BoxEmailP->Text=NodoAuxPila->EmailPila; NodoAuxCola=NodoAuxPila; NodoAuxPila=NULL; } } } } else NodoAuxPila=NodoAuxPila->SiguientePila; } //fin del while if (encontrado==0) { ShowMessage("La ficha que busca no ha sido ingresada"); PanelBuscarPila->Visible=false; } }
ORDENANDO:
// ORDENAR void __fastcall TMiFormulario::Modificaciones1Click(TObject *Sender) { MiFormulario->Caption=("Seleccione el nombre a modificar"); bandera=1; PanelBuscarPila->Visible=true; Registro *Actual; Actual = CabeceraPila; ComboPila->Clear(); while (Actual!=NULL) { ComboPila->Items->Add(Actual->NombrePila); Actual=Actual->SiguientePila; } } void __fastcall TMiFormulario::Modificaciones2Click(TObject *Sender) { MiFormulario->Caption=("Seleccione el nombre a modificar"); bandera=1; PanelBuscarCola->Visible=true; Registro *actual; actual = CabeceraCola; ComboCola->Clear(); while (actual!=NULL) { ComboCola->Items->Add(actual->NombreCola); actual=actual->SiguienteCola; } }
BAJAS:
// BAJA void __fastcall TMiFormulario::Bajas1Click(TObject *Sender) { PanelBajaP->Visible=true; } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonEliminarPilaClick(TObject *Sender) { NodoAuxPila=CabeceraPila; if (CabeceraPila==NULL) { Application->MessageBox("No hay datos en la cola","ATENCION",+MB_OK); } else { int opcion; opcion = Application->MessageBox("EstaEnLaPila seguro de eliminar el dato","ATENCION",+MB_OKCANCEL+MB_ICONQUESTION); if (opcion==IDOK) { CabeceraPila = NodoAuxPila->SiguientePila; delete(NodoAuxPila); Application->MessageBox("El dato fue eliminado con exito!!!","ATENCION",+MB_OK); } } } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonRetornarPClick(TObject *Sender) { MiFormulario->Caption=("Agenda con Pilas y Colas"); PanelBajaP->Visible = false; } void __fastcall TMiFormulario::Bajas2Click(TObject *Sender) { PanelBajasC->Visible = true; } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonEliminarColaClick(TObject *Sender) { if (CabeceraCola==NULL) { Application->MessageBox("No hay datos en la cola","ATENCION",+MB_OK); } else { int opcion; opcion = Application->MessageBox("EstaEnLaPila seguro de eliminar el dato","ATENCION",+MB_OKCANCEL+MB_ICONQUESTION); if (opcion==IDOK) { NodoCola = CabeceraCola; CabeceraCola = NodoCola->SiguienteCola; delete(NodoCola); { Application->MessageBox("El dato fue eliminado con exito!!!","ATENCION",+MB_OK); } } } } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonRetornarCClick(TObject *Sender) { MiFormulario->Caption=("Agenda con Pilas y Colas"); PanelBajasC->Visible = false; }
CONSULTAS:
//CONSULTA void __fastcall TMiFormulario::Visualizacion2Click(TObject *Sender) {MiFormulario->Caption=("Los datos en la agenda son:"); i=1; if(CabeceraCola==NULL) { Application->MessageBox("No hay datos en la lista","Atencion...",MB_OK); } PanelVisualizarC->Visible = true; if (CabeceraCola!=NULL) { GrillaC->Cells [0][0]="NOMBRE"; GrillaC->Cells[1][0]="EmailPila"; NodoCola = CabeceraCola; while (NodoCola->SiguienteCola!= NULL) { GrillaC->Cells[0][i]=NodoCola->NombreCola; GrillaC->Cells[1][i]=NodoCola->EmailCola; i=i+1; while ( GrillaC->Cells[0][i+1]!="") { GrillaC->Cells[0][i+1]=""; GrillaC->Cells[1][i+1]=""; } NodoCola=NodoCola->SiguienteCola; } GrillaC->Cells[0][i]=NodoCola->NombreCola; GrillaC->Cells[1][i]=NodoCola->EmailCola; } else { PanelVisualizarC->Visible = false; } } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonRegresarCClick(TObject *Sender) { MiFormulario->Caption=("Agenda con Pilas y Colas"); PanelVisualizarC->Visible = false; } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::Consultas2Click(TObject *Sender) { MiFormulario->Caption=("Elija el nombre a consultar"); PanelBuscarCola->Visible = true; bandera=4; Registro *actual; actual = CabeceraCola; ComboCola->Clear(); while (actual!=NULL) { ComboCola->Items->Add(actual->NombreCola); actual=actual->SiguienteCola; } } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::BotonAceptarColaClick(TObject *Sender) { MiFormulario->Caption=("El nombre elegido es:"); int encontrado; char bus[40]; AnsiString var; encontrado=0; NodoCola=CabeceraCola; var=ComboCola->Items->Strings[ComboCola->ItemIndex]; strcpy(bus,var.c_str()); while (NodoCola !=NULL ) { //funcion de busqueda if (stricmp(NodoCola->NombreCola,bus)==0) { encontrado=1; if (bandera==1) //si es una modificacion { if (NodoCola->EstaEnCola!=1) { BotonGrabarC->Visible=true; BotonLimpiarC->Visible=true; PanelCola->Visible=true; PanelBuscarCola->Visible=false; BoxNombreC->Text=NodoCola->NombreCola; BoxEmailC->Text=NodoCola->EmailCola; AuxCola=NodoCola; NodoCola=NULL; } } else { if(bandera==4) { if (NodoCola->EstaEnCola!=1) { BotonGrabarC->Visible=false; BotonLimpiarC->Visible=false; PanelCola->Visible=true; PanelBuscarCola->Visible=false; BoxNombreC->Text=NodoCola->NombreCola; BoxEmailC->Text=NodoCola->EmailCola; AuxCola=NodoCola; NodoCola=NULL; } } } } else NodoCola=NodoCola->SiguienteCola; } //fin del while if (encontrado==0) { ShowMessage("La ficha que busca no ha sido ingresada"); PanelBuscarCola->Visible=false; } }
MODIFICACIONES:
// MODIFICACION de ARCHIVO void __fastcall TMiFormulario::FormActivate(TObject *Sender) { FILE *Archivo,*Archivo1; //declaracion de un puntero a un archivo Archivo = fopen("Pila.dat", "rb"); Archivo1 = fopen("Cola.dat", "rb"); //abre el archivo bandera=3; //para decir que es la carga desde el archivo while (!feof(Archivo)) { fread(&MonoPila, sizeof(MonoPila),1,Archivo); if(!feof(Archivo)) InsertarEnPila(MonoPila.NombrePila,MonoPila.EmailPila); } while (!feof(Archivo1)) { fread(&MonoCola, sizeof(MonoCola),1,Archivo1); if(!feof(Archivo1)) InsertarEnCola(MonoCola.NombreCola,MonoCola.EmailCola); } fclose(Archivo); fclose(Archivo1); } //--------------------------------------------------------------------------- void __fastcall TMiFormulario::Salir1Click(TObject *Sender) { if (Application->MessageBox("Cierras la agenda?","ATENCION...!!",MB_OKCANCEL+MB_ICONQUESTION)== IDOK); { FILE *ArchPila,*ArchCola; Registro *NodoPilaActual,*NodoColaActual; ArchPila = fopen("Pila.dat","wb"); ArchCola = fopen("Cola.dat","wb"); NodoPilaActual=NodoPila; NodoColaActual=NodoCola; while (NodoPilaActual != NULL) { if (NodoPilaActual->EstaEnPila != 1) { strcpy(MonoPila.NombrePila,NodoPilaActual->NombrePila); strcpy(MonoPila.EmailPila,NodoPilaActual->EmailPila); fwrite(&MonoPila , sizeof(MonoPila),1,ArchPila); } NodoPilaActual=NodoPilaActual->SiguientePila; } while (NodoColaActual != NULL) { if (NodoColaActual->EstaEnCola != 1) { strcpy(MonoCola.NombreCola,NodoColaActual->NombreCola); strcpy(MonoCola.EmailCola,NodoColaActual->EmailCola); fwrite(&MonoCola , sizeof(MonoCola),1,ArchCola); } NodoColaActual=NodoColaActual->SiguienteCola; } fclose(ArchPila); fclose(ArchCola); Close(); } } void __fastcall TMiFormulario::BotonCerrarClick(TObject *Sender) { if (Application->MessageBox("Cierras la agenda?","ATENCION...!!",MB_OKCANCEL+MB_ICONQUESTION)== IDOK); { FILE *ArchPila,*ArchCola; Registro *NodoPilaActual,*NodoColaActual; ArchPila = fopen("Pila.dat","wb"); ArchCola = fopen("Cola.dat","wb"); NodoPilaActual=NodoPila; NodoColaActual=NodoCola; while (NodoPilaActual != NULL) { if (NodoPilaActual->EstaEnPila != 1) { strcpy(MonoPila.NombrePila,NodoPilaActual->NombrePila); strcpy(MonoPila.EmailPila,NodoPilaActual->EmailPila); fwrite(&MonoPila , sizeof(MonoPila),1,ArchPila); } NodoPilaActual=NodoPilaActual->SiguientePila; } while (NodoColaActual != NULL) { if (NodoColaActual->EstaEnCola != 1) { strcpy(MonoCola.NombreCola,NodoColaActual->NombreCola); strcpy(MonoCola.EmailCola,NodoColaActual->EmailCola); fwrite(&MonoCola , sizeof(MonoCola),1,ArchCola); } NodoColaActual=NodoColaActual->SiguienteCola; } fclose(ArchPila); fclose(ArchCola); Close(); } }
IMPRIMIR:
// IMPRIMIR void __fastcall TMiFormulario::PrintDialogClick(TObject *Sender) { int respuesta; { respuesta=Application->MessageBox("Tu impresora Está prendida?","Atencion",MB_OKCANCEL); if (respuesta==IDOK) PrintDialog1->Execute(); } }
Colega virtual, si eres del mundo algoritmico en estos links encontrarás toda la información necesaria para manejar con solvencia los conceptos de:
Todos los algoritmos que te propongo funcionan correctamente, pues ya los probé en mi PC y en el Laboratorio de la facultad, por lo tanto, solo te resta mejorarlos de acuerdo a tus propias necesidades.
Luego de editar la siguiente sintaxis, al compilar lograrás un sistema modelo, cuya pantallas tienen el aspecto de las imágenenes de esta page.
Buena suerte y que les saque utilidad a mi propuesta..!!
/////////////////////////////////////////////////// // C++ BUILDER Wilo Carpio // Fuente.cpp // Variables Dinámicas y Archivos /////////////////////////////////////////////////// #include#include #include #include #pragma hdrstop #include "Fuente.h" #pragma package(smart_init) #pragma resource "*.dfm" //////////////////////////////////////////// // DECLARACION DEL FORMULARIO PRINCIPAL //////////////////////////////////////////// TMiFormulario *MiFormulario;
Como ya estas deduciendo, en esta propuesta continuo con el trillado ejemplo de la agenda.
La idea es solo enseñarte la sintaxis y la semántica de la estructura algorítmica que utiliza C++ Builder, la cual, con pequeñas variantes puedes migrarla a Visual C++ de Microsoft.
Para simplificarte la comprensión te he llenado la codificación con ayudas no compilables, los cuales, si eres un colega experimentado, te ruego me perdones..!!
///////////////////////////////////////////////// // DECLARACIONES DE VARIABLES ///////////////////////////////////////////////// struct registro { char nombre[30],edad[10],domicilio[30]; bool elimina; }; struct registro MiRegistro; __fastcall TMiFormulario::TMiFormulario(TComponent* Owner): TForm(Owner) { archivo.open("MisDatos.DAT",ios::in|ios::out|ios::binary|ios::ate); if (!archivo) { ShowMessage("No hay archivo che..!!"); throw; } DatosPorMonitor(); } void __fastcall TMiFormulario::BotonAltasClick(TObject *Sender) { if(BotonAltas->Caption=="&Altas") { MiFormulario->Caption="Digita los datos, luego graba"; BotonAltas->Caption="&Cerrar"; MiGrilla->Visible=false; MisFolios->Visible=false; datos->Visible=true; Eliminar->Visible=false; nom->SetFocus(); nom->Text = ""; dom->Text = ""; ed->Text = ""; guardar->Visible=true; } else { MiFormulario->Caption="Agenda de Wilo"; datos->Visible=false; BotonAltas->Caption="&Altas"; } } void __fastcall TMiFormulario::guardarClick(TObject *Sender) { strcpy(MiRegistro.nombre,nom->Text.c_str()); strcpy(MiRegistro.domicilio,dom->Text.c_str()); strcpy(MiRegistro.edad,ed->Text.c_str()); MiRegistro.elimina=false; archivo.write((char *)&MiRegistro, sizeof(MiRegistro)); if (!archivo) ShowMessage("No existe el archivo..!!"); DatosPorMonitor(); nom->SetFocus(); } void __fastcall TMiFormulario::nomChange(TObject *Sender) { if (nom->Text=="") { guardar->Enabled=false; } else { guardar->Enabled=true; } }
La apariencia de los datos presentados en una grilla de entorno Windows, a mi criterio es inmejorable, por ello, en este link te ofrezco mi propuesta.
Te aconsejo que pongas atención en la rotulación de la grilla..!!
void __fastcall TMiFormulario::consultaClick(TObject *Sender) { MiFormulario->Caption="Registros del Archivo"; PortaBoton->Visible=false; MiGrilla->Visible=true; int j=1; archivo.seekg(0, ios::beg); archivo.read((char *)&MiRegistro, sizeof(MiRegistro)); MiGrilla->Cells[0][0] = "Nro"; MiGrilla->Cells[1][0] = "Nombre"; MiGrilla->Cells[2][0] = "Edad"; MiGrilla->Cells[3][0] = "Domicilio"; int i=1,k; for (i=1;i<=TotalRegistrosGrabados();i++) for (k=0;k<=3;k++) { MiGrilla->Cells[k][i]=""; } i=1; while (j<=TotalRegistrosGrabados()) { if (MiRegistro.elimina==false) { MiGrilla->Cells[0][i]= i; MiGrilla->Cells[1][i]=MiRegistro.nombre; MiGrilla->Cells[2][i]=MiRegistro.edad; MiGrilla->Cells[3][i]=MiRegistro.domicilio; i++; } j++; archivo.read((char *)&MiRegistro, sizeof(MiRegistro)); } } void TMiFormulario::DatosPorMonitor() { if (NumeroRegistro()<=TotalRegistrosGrabados()) { archivo.read((char *)&MiRegistro, sizeof(MiRegistro)); NumeroRegistro(NumeroRegistro()-1); nom->Text = MiRegistro.nombre; dom->Text = MiRegistro.domicilio; ed->Text = MiRegistro.edad; } else { nom->Text = ""; dom->Text = ""; ed->Text = ""; } } void __fastcall TMiFormulario::BotonAceptarClick(TObject *Sender) { int FichaActual=1; char bus[40]; AnsiString var; MiFormulario->MiCombo->Visible=false; MiFormulario->BotonAceptar->Visible=false; AnsiString DatoBuscado; bool SiEsta = false; archivo.seekg(0,ios::beg); archivo.read((char *)&MiRegistro, sizeof(MiRegistro)); var=MiCombo->Items->Strings[MiCombo->ItemIndex]; strcpy(bus,var.c_str()); while(FichaActual<=TotalRegistrosGrabados()) { if((strcmp(MiRegistro.nombre,bus)==0)&&(MiRegistro.elimina==false)) { SiEsta = true; nom->Text = MiRegistro.nombre; dom->Text = MiRegistro.domicilio; ed->Text = MiRegistro.edad; datos->Visible=true; guardar->Visible=false; Eliminar->Visible=false; BotonBuscar->Caption="&Cerrar"; datos->Caption="FICHA BUSCADA: Nº "+IntToStr(FichaActual); break; } FichaActual=FichaActual+1; archivo.read((char *)&MiRegistro, sizeof(MiRegistro)); } if(SiEsta==false) { Application->MessageBox("NO EXISTE","EL REGISTRO BUSCADO",MB_OK); MiFormulario->Caption="Agenda de Wilo"; } }
En este link te ofrezco los algoritmos de carga de la grilla de datos a visualizar, con el contenido de los registros que almacenaste en tu archivo.
Como ya habrás detectado, en este ejemplo los datos se operan usando la estructura dinámica de una lista enlazada simple..!!
void __fastcall TMiFormulario::SpeedButton1Click(TObject *Sender) { if(BotonVerGrilla->Caption=="&VerGrilla") { BotonVerGrilla->Caption="&Cerrar"; MiFormulario->Caption="Fichas del Archivo"; MiGrilla->Visible=true; int j=1; archivo.seekg(0, ios::beg); archivo.read((char *)&MiRegistro, sizeof(MiRegistro)); MiGrilla->Cells [0][0]= "Ficha"; MiGrilla->Cells [1][0]= "Nombre"; MiGrilla->Cells [2][0]= "Edad"; MiGrilla->Cells [3][0]= "Domicilio"; int i=1,k; for (i=1;i<=TotalRegistrosGrabados();i++) for (k=0;k<=3;k++) { MiGrilla->Cells[k][i]=""; } i=1; while (j<=TotalRegistrosGrabados()) { if (MiRegistro.elimina==false) { MiGrilla->Cells[0][i]= i; MiGrilla->Cells[1][i]=MiRegistro.nombre; MiGrilla->Cells[2][i]=MiRegistro.edad; MiGrilla->Cells[3][i]=MiRegistro.domicilio; i++; } j++; archivo.read((char *)&MiRegistro, sizeof(MiRegistro)); } } else { MiFormulario->Caption="Agenda de Wilo"; BotonVerGrilla->Caption="&VerGrilla"; MiGrilla->Visible=false; } }
En este procedimiento, para identificar el archivo a eliminar, utilizo para la busqueda un combo box, de acuerdo a la siguiente secuencia.
void __fastcall TMiFormulario::BotonBajasClick(TObject *Sender) { int FichaActual=1; MiGrilla->Visible=false; MisFolios->Visible=false; MiFormulario->MiCombo->Visible=true; MiFormulario->BotonAceptar2->Visible=true; datos->Caption="Ficha Buscada"; if(BotonBajas->Caption=="&Eliminar") { MiFormulario->BotonBajas->Caption="&Cerrar"; MiCombo->Clear(); archivo.seekg(0,ios::beg); archivo.read((char *)&MiRegistro, sizeof(MiRegistro)); while(FichaActual<=TotalRegistrosGrabados()) { MiCombo->Items->Add(MiRegistro.nombre); FichaActual=FichaActual+1; archivo.read((char *)&MiRegistro, sizeof(MiRegistro)); } } else { MiFormulario->MiCombo->Visible=false; MiFormulario->BotonAceptar2->Visible=false; datos->Visible=false; MiFormulario->Caption="Agenda de Wilo"; BotonBajas->Caption="&Eliminar"; } } void __fastcall TMiFormulario::EliminarClick(TObject *Sender) { int opcion; long a; char bus[40]; AnsiString var; int FichaActual=1; MiFormulario->Caption="BAJA de una FICHA"; BotonBajas->Caption="&Cerrar"; archivo.seekg(0,ios::beg); archivo.read((char *)&MiRegistro, sizeof(MiRegistro)); var=MiCombo->Items->Strings[MiCombo->ItemIndex]; strcpy(bus,var.c_str()); opcion=Application->MessageBox("Esta seguro","ELIMINAR",MB_OKCANCEL+MB_ICONQUESTION); if(opcion==IDOK) { while(FichaActual<=TotalRegistrosGrabados()) { if((strcmp(MiRegistro.nombre,bus)==0)) { if (MiRegistro.elimina==false) { MiRegistro.elimina=true; a=archivo.tellg(); archivo.seekg(a-sizeof(MiRegistro)); archivo.write((char *)&MiRegistro, sizeof(MiRegistro)); } } FichaActual=FichaActual+1; archivo.read((char *)&MiRegistro, sizeof(MiRegistro)); } datos->Visible=false; } else { datos->Visible=false; } MiFormulario->Caption="Agenda de Wilo"; BotonBajas->Caption="&Eliminar"; } void __fastcall TMiFormulario::BotonAceptar2Click(TObject *Sender) { int FichaActual=1; char bus[40]; AnsiString var; MiFormulario->MiCombo->Visible=false; MiFormulario->BotonAceptar2->Visible=false; AnsiString DatoBuscado; bool SiEsta = false; archivo.seekg(0,ios::beg); archivo.read((char *)&MiRegistro, sizeof(MiRegistro)); var=MiCombo->Items->Strings[MiCombo->ItemIndex]; strcpy(bus,var.c_str()); while(FichaActual<=TotalRegistrosGrabados()) { if((strcmp(MiRegistro.nombre,bus)==0)&&(MiRegistro.elimina==false)) { SiEsta = true; nom->Text = MiRegistro.nombre; dom->Text = MiRegistro.domicilio; ed->Text = MiRegistro.edad; datos->Visible=true; guardar->Visible=false; Eliminar->Visible=true; BotonBajas->Caption="&Cerrar"; datos->Caption="FICHA BUSCADA: Nº "+IntToStr(FichaActual); break; } FichaActual=FichaActual+1; archivo.read((char *)&MiRegistro, sizeof(MiRegistro)); } if(SiEsta==false) { Application->MessageBox("NO EXISTE","EL REGISTRO BUSCADO",MB_OK); MiFormulario->Caption="Agenda de Wilo"; } }
Sin estas funciones, todo lo anterior no funciona, por lo tanto debes codificarlos cuidadosamente, en primera instancia no te conviene cambiar ninguna estructura.
Buena suerte..!!
void __fastcall TMiFormulario::BotonSalirClick(TObject *Sender) { int Opcion; Opcion= Application->MessageBox("Deseas cerrar este Programa", "FINALIZACION DEL SISTEMA", MB_OKCANCEL+MB_DEFBUTTON1|MB_ICONQUESTION); if (Opcion== IDOK) { Close(); } } int TMiFormulario::NumeroRegistro() { return archivo.tellg()/sizeof(MiRegistro)+1; } void TMiFormulario::NumeroRegistro(int NuevoNumero) { archivo.seekg((NuevoNumero-1)*sizeof(MiRegistro)); } int TMiFormulario::TotalRegistrosGrabados() { int PosicionActual = archivo.tellg(); archivo.seekg(0, ios::end); int N = NumeroRegistro()-1; archivo.seekg(PosicionActual); return N; } void __fastcall TMiFormulario::BotonHelpClick(TObject *Sender) { if(BotonHelp->Caption=="&Help") { MiFormulario->Caption="Ayuda del Sistema"; MisFolios->Visible=true; MisFolios->Enabled=true; BotonHelp->Caption="&Cerrar"; } else { MiFormulario->Caption="Agenda de Wilo"; MisFolios->Visible=false; BotonHelp->Caption="&Help"; } } void __fastcall TMiFormulario::HojaSistemaShow(TObject *Sender) { VideoPlayer1->Play(); }
// BUSCAR void __fastcall TMiFormulario::BotonBuscarClick(TObject *Sender) { int FichaActual=1; MiGrilla->Visible=false; MisFolios->Visible=false; MiFormulario->MiCombo->Visible=true; MiFormulario->BotonAceptar->Visible=true; MiFormulario->Caption="BUSQUEDA de una FICHA"; if(BotonBuscar->Caption=="&Buscar") { MiFormulario->BotonBuscar->Caption="&Cerrar"; MiCombo->Clear(); archivo.seekg(0,ios::beg); archivo.read((char *)&MiRegistro, sizeof(MiRegistro)); while(FichaActual<=TotalRegistrosGrabados()) { MiCombo->Items->Add(MiRegistro.nombre); FichaActual=FichaActual+1; archivo.read((char *)&MiRegistro, sizeof(MiRegistro)); } } else { MiFormulario->MiCombo->Visible=false; MiFormulario->BotonAceptar->Visible=false; MiFormulario->Caption="Agenda de Wilo"; BotonBuscar->Caption="&Buscar"; datos->Visible=false; } }
// ADJUNTO /////////////////////////////////////////////////// // C++ BUILDER Wilo Carpio // Fuente.h // Variables Dinámicas y Archivos /////////////////////////////////////////////////// #ifndef FuenteH #define FuenteH #include#include #include #include #include #include #include #include #include #include #include class TMiFormulario : public TForm { __published: // IDE-managed Components TGroupBox *datos; TLabel *Label1; TLabel *Label2; TLabel *Label3; TEdit *nom; TEdit *dom; TEdit *ed; TBitBtn *guardar; TPanel *PortaBoton; TBitBtn *BotonAltas; TBitBtn *BotonBuscar; TBitBtn *BotonBajas; TBitBtn *BotonHelp; TStringGrid *MiGrilla; TSpeedButton *BotonSalir; TPageControl *MisFolios; TTabSheet *HojaSistema; TTabSheet *HojaAutor; TTabSheet *HojaAyuda; TLabel *LabelSistema; TSpeedButton *BotonVerGrilla; TImage *MiFoto; TLabel *RotuloAutor; TMemo *MiMemo; TComboBox *MiCombo; TBitBtn *BotonAceptar; TBitBtn *Eliminar; TBitBtn *BotonAceptar2; TMediaPlayer *VideoPlayer1; TAnimate *Animate1; void __fastcall BotonAltasClick(TObject *Sender); void __fastcall consultaClick(TObject *Sender); void __fastcall BotonBuscarClick(TObject *Sender); void __fastcall BotonBajasClick(TObject *Sender); void __fastcall BotonSalirClick(TObject *Sender); void __fastcall guardarClick(TObject *Sender); void __fastcall nomChange(TObject *Sender); void __fastcall BotonHelpClick(TObject *Sender); void __fastcall SpeedButton1Click(TObject *Sender); void __fastcall BotonAceptarClick(TObject *Sender); void __fastcall EliminarClick(TObject *Sender); void __fastcall BotonAceptar2Click(TObject *Sender); void __fastcall HojaSistemaShow(TObject *Sender); private: // User declarations fstream archivo; void TMiFormulario::DatosPorMonitor(); int TMiFormulario::TotalRegistrosGrabados(); int TMiFormulario::NumeroRegistro(); void TMiFormulario::NumeroRegistro(int NuevoNumero); public: // User declarations __fastcall TMiFormulario(TComponent* Owner); }; extern PACKAGE TMiFormulario *MiFormulario; #endif
// ADJUNTO /////////////////////////////////////////////////// // C++ BUILDER Wilo Carpio // Modelo.cpp // Variables Dinámicas y Archivos /////////////////////////////////////////////////// #include#pragma hdrstop USERES("Modelo.res"); USEFORM("Fuente.cpp", MiFormulario); WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { try { Application->Initialize(); Application->CreateForm(__classid(TMiFormulario), &MiFormulario); Application->Run(); } catch (Exception &exception) { Application->ShowException(&exception); } return 0; }
BIBLIOGRAFIA BASICA
LIBRO AUTOR EDITORIAL AÑO Programación C++ - Luis Joyanes - Mc Graw Hill 1999 C++ Cómo programar - Deitel y Deitel - Prentice Hall 1999 Visual C++ 6 - Kate gregory - Prentice Hall 2000 Visual C++ 6 - Cris H. Pappas - Mc Graw Hill 2000 Visual C++6 Manual - Beck Zaratian - Mc Graw Hill 1999 Visual C++6 - Holzner - Mc Graw Hill 1999 Manual C / C++ - Wiliam H. Murray - Mc Graw Hill 1997 Visual C++6 - María Cascon Sánchez - Prentice Hall 1999 Visual C++ - Ori y Nathan Gurenwich - SAMS Publishing 1998 C++ Builder 5 - Fransisco Charte - Anaya 2000
|
|||||
Lenguajes | Gramáticas | Autómatas | Series | ||
Laplace | Ecuación | Operador | Compilador |
Y para el cruel que me arranca
el corazón con que vivo,
cardo ni ortiga cultivo;
..cultivo una rosa blanca..!
José Martí
|
||||||||
Te espero en: wilucha@gmail.com
Esta page está en: www.wilocarpio.com.ar
11/09/2002