Ir arriba

Lenguaje: BUILDER

Permite el diseño de paradigmas orientados a objetos, mediante:

- DESARROLLO RAPIDO:
Usa componentes prefabricados, de manera de pegarlos sobre un contenedor y luego solo escribir los métodos correspondientes.

- CODIFICACIÓN MANUAL:
Codificas con un editor de texto y luego procesas con um complilador de Builder.

El
Vector
Matriz
Puntero
Lista
Cola
El
Arbol
Archivo
Editor
Agenda
Base
Datos
Sobrecarga
Básico
Torrre
Hanoi
Polimorfismo
Modelo

ESTRUCTURA del PROGRAMA C++BUILDER
Para no entrar en una aburrida teorización, vayámos al grano..!!! y para ello sigue los siguientes pasos


En el siguiente link desarrolaré los algporitmos de tu primer programa, el cual estará diseñado para calcular la superficie de un círculo. Qué barbaridad no..!!!

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; 
           }

Para ir al grano, en el editor de programación..!! copia textualmente cada uno de los siguientes renglones que te propongo para tu primera vez dentro de esta fantástica tecnología de generación de modernos sistemas paradigmáticos.
Te recomiendo poner atención en las declaraciones de bibliotecas y tipos de datos efectuadas, puedes apreciar que es similar a C++.

  //////////////////////////////////////////////////////////////
  //  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;
 

Del mismo modo que las estructuras de C y C++, aquí también cuentas con una función principal, cuyo nombre es WinMain(), tal puedes apreciar en el siguiente código, donde veras algunas novedades como que, es que están ausente cin y cout, los cuales se reemplazaron con los objetos InputBox() y ShowMessage() respectivamente. También se usan las funciones AnsiString() y atoi() para transformar los string.

///////////////////////////////////////////////
//             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:
En este ejemplo puedes apreciar las estructuras de control y la aplicación una función que no usa el característico prototipo


  //////////////////////////////////////////
  // 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;
}
Vector
Matriz
Puntero
Lista
Cola
Arbol
Archivo
Editor
Agenda
Base Datos
Modelo

MATRICES en C++BUILDER
| Fibonacci

Para no entrar en una aburrida teorización, vayámos al grano..!!! y para ello sigue los siguientes pasos

  • Luego de pinchar en el ícono de tu C++Builder, verás aparecer el entorno de programación y en el clickea en la opción PROJECT, que abrirá un menu.

  • Pincha en la opción VIEW SOURCE y verás aparecer el editor de programas de C++Builder, con algunas lineas básicas por defecto. Por ahora, limpia totalmente este editor.

  • Copia textualmente cada una de las siguientes partes que te propongo en el desarrollo de esta page. Por el momento no cambies nada..!!!

  • Cuando hayas terminado de escribir todas las instrucciones de tu programa, graba..!!. Builder te pedira dos nombres: El primero es el del proyecto y el segundo es el archivo fuente .cpp.

  • Finalmente presiona la tecla F9 y Builder compilará y ejecutará tu programa. Te mostrará por pantalla un formulario con el resultado de tu programa

  • Si metiste el dedo en el lugar equivocado, te pedirá que coorrijas tu error, caso contrario, generará un archivo ejecutable .exe, con el nombre de tu proyecto. Buena suerte..!!!

//////////////////////////////////////////
// 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


La estructura basica en un programa en C++ Builder tiene la siguiente estructura sintáctica

/////////////////////////////////////
//  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


La función en C++ Builder tiene la siguiente estructura sintáctica

///////////////////////////////////////////////
//             FUNCION PRINCIPAL
///////////////////////////////////////////////
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
  //////////////////////////////
  //    Variables Locales
  //////////////////////////////

  //////////////////////////////
  //    Bucle Operativo
  //////////////////////////////
  do
  {

FUNCIONES en C++BUILDER: ALTAS


Observa el manejo de las filas y las columnas

    //////////////////////////////
    //    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


Asignaciones, bucles y todas esas cosas..


    /////////////////////////////////////////////
    //  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;
}
Vector
Matriz
Puntero
Lista
Cola
Arbol
Archivo
Editor
Agenda
Base Datos
Modelo

ARCHIVOS en C++BUILDER

El lenguaje que usa C++Builder, provee los potentes procedimientos LoadFromFile() y SaveToFile() que nos permite operar directamente archivos de texto contenidos en objetos tipo Tmemo y archivos gráficos contenitos en objetos TImage.

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:

  1. TEMPORARIOS: Son aquellos de existencia virtual, cuyo soporte es solo del tipo lógico y por ello al cerrar el progragrama que los administra, sus datos desaparecen.

  2. PERMANENTES: Guardados en soportes físicos, para permitir leer información grabada en forma permanente, guardados como archivos de datos, o secuencia de bits.
    Estos a su vez pueden ser de dos tipos:

    • Secuenciales: En ellos los datos se organizan linealmente uno a continuación de otro, de manera que para localizar uno de ellos, es inevitable la lectura de todos los datos anteriormente ubicados, carácterística que los hace lentos, aunque su manejo es simple.

    • Acceso directo: O archivos aleatorios, que permiten conociendo su ubicación, localizar sus datos en forma directa, por ello son más veloces que los anteriores, pero su manejo es más complejo.

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:

  1. DECLARACION DEL TIPO DE VARIABLE: Se usa el archivo cabecera Fstream.H y luego con el, podemos declarar los siguientes tipos de apertura:

    • Fstream: Para abrir el archivo en disco para lectura o escritura.

      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 );

    • Ifstream: Para abrir un archivo existente para lectura.

      Ej: ifstream F ("Agenda");

    • Ofstream: Abre archivo para escritura creándolo.

      Ej: ofstream F ("Agenda");

  2. ABRIR Y CERRAR EL ARCHIVO: Se puede abrir usando alguno de los procedimientos anteriores o bién aplicando open() y luego para el cierre se usa close()

  3. ESCRIBIR Y LEER DATOS: Aplicando write() y read() podemos gestionar cualquier tipo de dato, indicando dos parámetros:

    • Puntero tipo char con la ubicación del dato

    • Entero con la cantidad de bytes a leer o escribir.

  4. POSICION EN EL ARCHIVO: Para conocer la posición actual del fichero se usa un puntero que trabaja del mismo modo que el señalador de un libro. Al activar el archivo tal puntero se ubica en el primer registro existente y luego cada siguiente operación sobre el archivo hace que la posición avance automáticamente hasta la siguiente posición. Tal posición puede ser modificada usando las funciones seekg() y tellg():

    Seekg( ): Se usa para determinar posicionamiento forzado:

    • Absoluto: Usa un solo parametro la posición a donde se quiere desplazar el puntero.

    • Relativo: Usa un segundo parámetro para un desplazamiento relativo desde la posición actual ios::cur, o desde el final ios::end o desde el principio ios::beg .

APERTURA Y CIERRE DEL ARCHIVO SECUENCIAL

Volver al principio

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.

  • "r" Abrir un archivo existente sólo para lectura.

  • "w" Abrir un nuevo archivo sólo para escritura. Si existe un archivo con el nombre-archivo especificado, será destruido y creado uno nuevo en su lugar.

  • "a" Abrir un archivo existente para añadir. Se creará un archivo nuevo si no existe un archivo con el nombre nombre-archivo especificado.

  • "r+" Abrir un archivo existente para lectura escritura.

  • "w+" Abrir un archivo nuevo para escritura y lectura. Si existe un archivo con el nombre-archivo especificado, será destruido y creado uno nuevo en su lugar.

  • "a+" Abrir un archivo existente para leer y añadir. Se creará un archivo nuevo si no existe un archivo con el nombre nombre-archivo especificado.

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

Volver al principio
Las transacciones típicas del archivo es el ABM o Altas, Bajas y Modificaciones, para lo cual se suele usar dos estrategias:

  • Para actualizar los registros dentro de un archivo de datos, se lee cada registro de un archivo, se actualiza el registro y después se escribe el registro actualizado al mismo archivo.

  • Trabajar con dos archivos diferentes: Un archivo fuente y otro Nuevo. Se lee cada registro del fuente, se actualiza y se escribe en el Nuevo y cuando se han actualizado todos los registros, se borra o se almacena el archivo fuente y se renombra el archivo nuevo. Así el Nuevo archivo se convierte en Fuente para el siguiente turno de modificaciones. Este proceso se aplica para efectuar bajas físicas de registros.

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

Volver al principio
Están basadas en las funciones de biblioteca fread y fwrite o funciones de lectura y escritura sin formato, que permiten almacenar bloques de datos, consistentes en un número de bytes continuos, que representaran una estructura de datos compleja, tal como arrays simples o múltiples.

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:

  • Puntero get, que especifica la posición del archivo en el que se producirá la siguiente operación de entrada.

  • Puntero put , que especifica la posición del archivo en el que se producirá la siguiente de salida.

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:

  1. Puntero a FILE al archivo que es objeto de la búsqueda. Dicho archivo deberá haber sido abierto previamente con la función fopen().

  2. offset. Este argumento indica la distancia a que debemos movernos desde el punto de comienzo; deberá declararse como tipo long. Puede ser positivo (movimiento hacia adelante), negativo (movimiento hacia atrás) o cero (permanece en el mismo sitio).

  3. Modo, que identifica el punto de comienzo. El archivo cabecera stdio.h especifica las siguientes constantes explícitas para este modo:
    • SEEK_SET Comienzo del archivo

    • SEEK_CUR Posición actual

    • SEEK_END Fin del archivo

La función fgetpos devuelve la posición actual del puntero a FILE, para ello necesita dos argumentos

  1. Apuntador asociado con el archivo sobre el cual queremos realizar la búsqueda.

  2. Variable de tipo fpos_t en donde se almacena la posición actual del apuntador al archivo.

LECTURA DE UN ARCHIVO TEXTO

Volver al principio

Ejemplo que lee un Archivo de texto y lo muestra en la pantalla:


//////////////////////////////////////
//   Leer un archivo
// C                       WiloCarpio
//////////////////////////////////////

#include 

int 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

  • r Abre un Archivo existente para lectura

  • w Crea un Archivo nuevo (o borra su contenido si existe) y lo abre para escritura.

  • a Abre un Archivo (si no existe lo crea) para escritura. El puntero se sitúa al final del archivo, así se puedan añadir datos si borrar los existentes.

    Se puede agregar: b Para abrir en modo binario, t modo texto y + modo lectura y escritura
    Ejemplo:

  • rb+ Abre el Archivo en modo binario para lectura y escritura

  • w+ Crea (o lo borra si existe) un Archivo para lectura y escritura

  • rt Abre un archivo existente en modo texto para lectura.

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


La función fgets se usa para leer líneas completas desde un Archivo.

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
//////////////////////////////////////

#include 

int 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

Volver al principio
Abrimos un Archivo 'origen.txt' y lo copiamos en otro Archivo 'destino.txt'. Además el Archivo se muestra en pantalla.

//////////////////////////////////////
//   Escribir en un archivo
// C                       WiloCarpio
//////////////////////////////////////
#include 

int 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..!!

Volver al principio

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);

  • buffer - variable que contiene los datos que vamos a escribir en el Archivo.

  • tamano - el tamaño del tipo de dato a escribir. Puede ser un int, un float, una estructura, ... Para conocer su tamaño usamos el operador sizeof.

  • numero - el número de datos a escribir.

  • pArchivo - El puntero al Archivo sobre el que trabajamos.

Ejemplo:


//////////////////////////////////////
//   Archivo
// C                       WiloCarpio
//////////////////////////////////////

#include 

struct {
        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 );

  • ®istro - es la variable (en este caso una estructura) que contiene la información a meter al Archivo.

  • sizeof(registro) - lo utillizamos para saber cuál es el número de bytes que vamos a guardar, el tamaño en bytes que ocupa la estructura.

  • 1 - indica que sólo vamos a guardar un elemento. Cada vez que se recorre el bucle guardamos sólo un elemento.

  • Archivo - el puntero FILE al Archivo donde vamos a escribir.

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

Volver al principio
Siguiendo con el ejemplo anterior ahora vamos a leer los datos que habíamos introducido en "nombres.txt".

#include 

struct {
        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


El siguiente ejemplo te muestra el funcionamiento de fseek. Se trata de un programa que lee la letra que hay en la posición que especifica el usuario.

#include 

int 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, ...);

Vector
Matriz
Puntero
Lista
Cola
Arbol
Archivo
Editor
Agenda
Base Datos
Modelo

ARBOLES en C++BUILDER

Los árboles son estructuras dinámicas de datos estan conformados estructuralmente por conjuntos de uno o más nodos, quienes pueden o no estar vacíos y están dotados de enlaces jerárquicos.

  • Nodo Raíz:
    o Raíz del árbol es el nodo especial ubicado en la cima del árbol

  • Subárboles"
    Formados por los demás nodos conectados a la raíz por medio de aristas o ramas.

  • Nodo Terminal,
    Hoja o rama, son los nodos que no poseen subárboles

  • Nodo Interior
    o bifurcación, son los nodos que tienen uno o dos subárboles.
  • LIO FAMILIAR:
    Aquellos nodos que tienen el mismo padre se llaman "Hermanos" y los hijos de estos son "Nietos" del "Padre". Está claro no.???

    • Nivel: Es la ubicación del nodo respecto de la raíz del árbol, cuyo nivel es 1. En los nodos restantes está definido por cada descendiente directo.

    • Grado de un árbol Es el nivel de la rama más alejada de la raíz, o sea, es el número mayor de descendientes directos de un nodo.

    • Longitud o Profundidad. Lo define el número de aristas de una secuencia de nodos.

    • Profundidad de Árbol Es la cantidad de aristas de la hoja más profunda.

    • Camino de N1 a Nk Es la sucesión de nodos N1, N2, N3... a Nk

    • Altura del Nodo Definido por el número de aristas del camino más largo entre el nodo y una hoja.

    • La altura del árbol vacio se define –1

    • Antecesor y Descendiente Cuando existe un camino que va de N1 a N2 , se dice que N1 es un Antecesor de N2 y que este es un Descendiente de N1.

    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:

    • Base: Definen los elementos del conjuntos que servirán para crear el resto del conjunto.

    • Reglas de recurrencia: Permiten crear un elemento a partir de elementos ya creados.

    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


    Usa una función recursiva que permita insertar los nuevos nodos sin perder su raíz, sobre la que se realizan las operaciones sobre todo 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


    Se activa una función recursiva de recorrido, que toma como parámetro un nodo, tal lo muestra el siguiente diagrama de flujo. Se pueden usar con este fin los recorridos en Preorden y Postorden .

    • POSTORDEN Primero hacia la derecha, luego hacia la izquierda y luego la raíz,

    • PREORDEN Primero hacia la izquierda , luego hacia la derecha y finalmente la raíz.
    
    
    ////////////////////////////////////////////////////
    //              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]="";
      }
    }
    
    Vector
    Matriz
    Puntero
    Lista
    Cola
    Arbol
    Archivo
    Editor
    Agenda
    Base Datos
    Modelo

    AGENDA en C++BUILDER

    Recuerda que las estructuras de datos estáticas, como arreglos requieren necesariamente definir tamaños fijados en tiempo de compilación, mientras que las estructuras dinámicas de datos se expanden o contraen a medida que sean requeridas para su proceso.

    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:

    • Las listas enlazadas: Que desarrolaremos en este link
    • Las pilas
    • Las Colas
    • Los Arboles
    • Los grafos.

    LISTA ENLAZADA SIMPLE
    Volver al principio

    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:

    • La variable puntero ( Hace el apuntamiento )
    • La variable apuntada ( A quién se apunta ).

    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;
    }
    
    

    LISTA ENLAZADA VOLATIL

    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:

    • RECORRER
      la lista desde el principio hasta que se alcanza la posición apropiada.

    • EJECUTAR
      cambios en los punteros para modificar la estructura de la lista.

    METAMOS NODOS en la LISTA
    Volver al principio

    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...

    • LOCOMOTORA..!!..(Primer Nodo)
      Preguntamos si ya hay una. Si no la hay colocamos una sobre la via.. (La Lista..!!)

    • PRIMER VAGON..!!(Segundo Nodo)
      Preguntamos si ya hay una locomotora. Si la hay colocamos una sobre la via.. (La Lista..!!).. luego la enganchamos con la locomotora

    • SEGUNDO VAGON..!!(Tercer Nodo)
      Buscamos el último vagón, o sea el primero. Si lo encontramos, colocamos el segundo vagón sobre la via.. (La Lista..!!).. luego la enganchamos con el último vagón.

    • SIGUIENTE VAGON..!!(Siguiente Nodo)
      Buscamos el último vagón, Si lo encontramos, colocamos este vagón sobre la via.. (La Lista..!!).. luego la enganchamos con el último vagón.

    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.

    RECORRAMOS LOS NODOS
    Volver al principio

    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;
     }
    }
    

    BORREMOS NODOS..!!
    Volver al principio

    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();
    }
    //---------------------------------------------------------------------------
    

    CAMBIEMOS DATOS EN LOS NODOS
    Volver al principio

    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);
    }
    
    //---------------------------------------------------------------------------
    

    BONUS TRACK..!!!
    Volver al principio

    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);
     }
    }
    
    PARADIGMA: Los jóvenes creen que el dinero lo es todo...
    ..los viejos lo saben...!!! ( Wilucha )

    MANEJO DE MATRICES: SERIE DE FIBONACCI
    Volver al principio | Altas | Generación |

    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();
    }
    
    ALTAS: Ingreso de datos

    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";
    			  }
    		
    		}
    
    CONSULTAS: Ver datos
    Volver al principio

    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..!!

    Vector
    Matriz
    Puntero
    Lista
    Cola
    Arbol
    Archivo
    Editor
    Agenda
    Base Datos
    Modelo

    VECTORES en C++BUILDER

    Colega algorítmico, si eres del mundo paradigmático en estos links encontrarás toda la información necesaria para iniciar el manejo de los conceptos del Vector.. o Array.. o Arreglo.. Para los cuales son válidos los siguientes conceptos básicos.
    • Un vector es una forma de dato estructurado que se caracteriza por tener un subíndice que indica su localización dentro del conjunto homogeneo de datos que registra.

    • Todos los elementos del vector son del mismo tamaño y del mismo tipo de dato.

    • Cada vector posee un nombre o identificador que es constante y representa la dirección de su primer elemento

    • Gracias a tal subídice, el manejo algorítmico de los vectores, como podrás comprobar en este link, es una cosa muy sencilla, especialmente si tienes alguna solvencia en la aplicación de los iteradores definidos.

    • Tal subíndice puedes operarlo matemáticamente como una expresión cualquiera de variable entera.

    • El subíndice es una variable entera que comienza en cero.

    • La cantidad de elementos del vector prácticamente es ilimitado, pero es necesario que definas de antemano su límite.

    • Los datos que puedes guardar en el vector siempre será del mismo tipo y al igual que cualquier otra variable es necesario que previamente lo definas.

    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:

    1. DECLARACION: Previo a usarlas, debes declararlas como variables globales o como locales: Ejemplo: Para declarar que operararás con una matríz de 20 filas por 20 columnas, la sintaxis es:

      int MiMatriz[30][30];

      int TuMatriz[50][30];

      int MiMatriz[30][30], TuMatriz[50][30] Esta equivale a las dos anteriores.

    2. INICIALIZACION: Si requieres asignar un valor inicial a uno de los elementos de la matríz, por ejemplo 0 al primer elemento, la sintaxis es:

      MiMatriz[1][1] = 0;

      int TuVector[4]= {69, 22, 14, 55}; ( Este ejemplo abarca declaración e inicialización )

    3. ASIGNACION: Con los datos en formato matricial puedes operar tal como lo haces con una variable común, solo debes poner atención al índice del elemento que asignas. Ejemplos:

      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:

    1. VECTORES: MiVector[0]
    2. MATRICES: MiMatriz[0][0]

    Fácilmente puedes deducir que el elemento enésimo será

    1. VECTORES: MiVector[n-1]
    2. MATRICES: MiMatriz[n-1][n-1]

    Es necesario que los subíndices sean:

    1. VALORES ENTEROS: MiVector[12]
    2. EXPRESIONES ENTERAS: MiMatriz[n-m][n-q+1], donde m, n y q son variables enteras.
    Vector
    Matriz
    Puntero
    Lista
    Cola
    Arbol
    Archivo
    Editor
    Agenda
    Base Datos
    Modelo

    EDITORES en C++BUILDER

    Amigo virtual, en estos links encontraras todos los algoritmos necesarios para administrar un editor de textos que funciona en entorno windows. Distribuye los objetos correspondientes y la sintaxis siguiente que te propongo te permitirá efectuar las características operaciones de generar un archivo, copiarlo, modificarlo, abrirlo, borrarlo, etc.

    ///////////////////////////////////////
    // 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 Volver al principio

    ///////////////////////////////////////
    // BUILDER C++ Wilo Carpio
    // Editor de Texto V.1 15/9/2000
    ///////////////////////////////////////

    #include
    #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 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();
    }

    }

    Vector
    Matriz
    Puntero
    Lista
    Cola
    Arbol
    Archivo
    Editor
    Agenda
    Base Datos
    Modelo

    PUNTEROS en C++BUILDER

    El manejo de las variables dinámicas en Builder C++, podrás prácticar con un ejemplo simple, con una codificación que al compilarla lograrás generar esta en primer término esta pantalla de conceptos y datos y en el siguiente verás el objeto de resultados.

    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;
    }

    Vector
    Matriz
    Puntero
    Lista
    Cola
    Arbol
    Archivo
    Editor
    Agenda
    Base Datos
    Modelo

    LISTAS en C++BUILDER

    Recuerda que las estructuras de datos estáticas, como arreglos requieren necesariamente definir tamaños fijados en tiempo de compilación, mientras que las estructuras dinámicas de datos se expanden o contraen a medida que sean requeridas para su proceso.

    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:

    • Las listas enlazadas: Que desarrolaremos en este link
    • Las pilas
    • Las Colas
    • Los Arboles
    • Los grafos.

    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:

    • La variable puntero ( Hace el apuntamiento )
    • La variable apuntada ( A quién se apunta ).

    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;
    }
    

    CONCEPTO de LISTA ENLAZADA

    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:

    • RECORRER
      la lista desde el principio hasta que se alcanza la posición apropiada.

    • EJECUTAR
      cambios en los punteros para modificar la estructura de la lista.

    ARCHIVO SECUENCIAL en C++BUILDER


    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.

    
    struct UnaFicha
       {
         char CampoFichaNombre[30];
         char CampoFichaEmail[40];
       };
    
      FILE *Archivo;
      UnaFicha MiFicha;
    //---------------------------------------------------------------------------
    

    La gestión de un archivo, puede resumirse en las siguientes etapas:

    1. DECLARACION DEL TIPO DE VARIABLE: Se usa el archivo cabecera Fstream.H y luego con el, podemos declarar los siguientes tipos de apertura:

      • Fstream: Para abrir el archivo en disco para lectura o escritura.

        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 );

      • Ifstream: Para abrir un archivo existente para lectura.

        Ej: ifstream F ("Agenda");

      • Ofstream: Abre archivo para escritura creándolo.

        Ej: ofstream F ("Agenda");

    2. ABRIR Y CERRAR EL ARCHIVO: Se puede abrir usando alguno de los procedimientos anteriores o bién aplicando open() y luego para el cierre se usa close()

    3. ESCRIBIR Y LEER DATOS: Aplicando write() y read() podemos gestionar cualquier tipo de dato, indicando dos parámetros:

      • Puntero tipo char con la ubicación del dato

      • Entero con la cantidad de bytes a leer o escribir.

    4. POSICION EN EL ARCHIVO: Para conocer la posición actual del fichero se usa un puntero que trabaja del mismo modo que el señalador de un libro. Al activar el archivo tal puntero se ubica en el primer registro existente y luego cada siguiente operación sobre el archivo hace que la posición avance automáticamente hasta la siguiente posición. Tal posición puede ser modificada usando las funciones seekg() y tellg():

      Seekg( ): Se usa para determinar posicionamiento forzado:

      • Absoluto: Usa un solo parametro la posición a donde se quiere desplazar el puntero.

      • Relativo: Usa un segundo parámetro para un desplazamiento relativo desde la posición actual ios::cur, o desde el final ios::end o desde el principio ios::beg .

    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.

    • "r" Abrir un archivo existente sólo para lectura.

    • "w" Abrir un nuevo archivo sólo para escritura. Si existe un archivo con el nombre-archivo especificado, será destruido y creado uno nuevo en su lugar.

    • "a" Abrir un archivo existente para añadir. Se creará un archivo nuevo si no existe un archivo con el nombre nombre-archivo especificado.

    • "r+" Abrir un archivo existente para lectura escritura.

    • "w+" Abrir un archivo nuevo para escritura y lectura. Si existe un archivo con el nombre-archivo especificado, será destruido y creado uno nuevo en su lugar.

    • "a+" Abrir un archivo existente para leer y añadir. Se creará un archivo nuevo si no existe un archivo con el nombre nombre-archivo especificado.

    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" );
        }
    

    METAMOS NODOS en la LISTA

    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...

    • LOCOMOTORA..!!..(Primer Nodo)
      Preguntamos si ya hay una. Si no la hay colocamos una sobre la via.. (La Lista..!!)

    • PRIMER VAGON..!!(Segundo Nodo)
      Preguntamos si ya hay una locomotora. Si la hay colocamos una sobre la via.. (La Lista..!!).. luego la enganchamos con la locomotora

    • SEGUNDO VAGON..!!(Tercer Nodo)
      Buscamos el último vagón, o sea el primero. Si lo encontramos, colocamos el segundo vagón sobre la via.. (La Lista..!!).. luego la enganchamos con el último vagón.

    • SIGUIENTE VAGON..!!(Siguiente Nodo)
      Buscamos el último vagón,  Si lo encontramos, colocamos este vagón sobre la via.. (La Lista..!!).. luego la enganchamos con el último vagó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.

    RECORRAMOS LOS 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;
     }
    }
    

    BORREMOS NODOS..!!

    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();
    }
    //---------------------------------------------------------------------------
    

    CAMBIEMOS DATOS EN LOS NODOS

    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);
     }
    }
    

    BONUS TRACK..!!!
    
    /////////////////////////////////////////////////////////////////
    // 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();
     }
    //---------------------------------------------------------------------------
    
    Vector
    Matriz
    Puntero
    Lista
    Cola
    Arbol
    Archivo
    Editor
    Agenda
    Base Datos
    Modelo

    BASES de DATOS en C++BUILDER

    Amigo virtual en este page podrás apreciar la aplicación de los algoritmos típicos que se requieren para procesar una base de datos compuesta por una sola tabla, que fue creada usando Visual Fox Pro. Por supuesto que la estructura de este sistema, es valido para cualquier otra tabla generada por otro entorno, tal como Access, Paradox, DBase u otro estandar.

    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:

    • VISTA LOCAL: Utiliza tablas de la propia base de datos

    • VISTA REMOTA: Vistas que utilizan a través de ODBC cualquier origen de datos que soporte esta norma.

    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

    1. TABLAS: Guarda el nombre, la descripción y las reglas de validación a nivel de fila.

    2. VISTAS: Consultas actualizables realizadas a tablas de la propia base de datos.

      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.

    3. CAMPOS: Guarda el nombre, la descripción y las reglas de validación a nivel de columna.

    4. INDICE: Guarda el tipo de índice: principal, candidato, regular o normal.

    5. VISTAS REMOTAS: Consultas actualizables realizadas a tablas remotas situadas en algún servidor de datos.

      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.

    6. CONEXIONES: Con información acerca de una conexión hecha vía ODBC a algún servidor de datos.

      Esta información se utiliza posteriormente para generar vistas remota.

    7. PROCEDIMIENTOS: Procedimientos almacenados, consistente en la información generada por el generador de integridad referencial o procedimientos de usuario.

      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


    Para crear una base de datos en VISUAL FOX se puede seguir algunos de estos procedimientos:
    1. Desde el generador de proyectos, escoja nuevo posicionado en la fila bases de datos de la pagina datos.

    2. Desde el menú principal,

      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.

    3. Desde la ventana de comandos, emitiendo la sentencia create project.

    2.- CREAR BASE DE DATOS desde C++Builder


    Para efectuar este proceso, proceda de la siguiente forma:
    1. Desde el generador de proyectos, escoja Nuevo posicionado en la fila Tablas de la base de datos a la cual quiere que pertenezca la nueva tabla. No es necesario que este editando la base de datos con el generador de bases de datos.

    2. Desde el menú principal, 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. Solo es posible realizar estas acciones cuando se esta editando la base de datos en el generador de bases de datos.

    3. Si esta editando la base de datos directamente, escoja el botón de comando Nueva Tabla de la barra de herramientas Generador de bases de datos.

      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

    1. Desde el generador de proyectos, escoja Data Access, y elija Data Source.

    2. También debe elegir Table para trabajar con la tabla designada.

    3. Una vez que ya tengo la tabla, en las propiedades de Data Source (Data Set), poner el nombre de la tabla que estoy utilizando.

    USO de BASE DE DATOS


    Crear y mantener la información del contenedor de bases de datos se realiza mediante los comandos CREATE DATABASE NombreArchivo y MODIFY DATABASE [NombreBaseDatos], respectivamente.

    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

    1. Desde la opción tools, elegir DataBase Desktop, en donde abrirá una ventana.

    2. En file, elegir new y luego table, donde te dará la opción de elegir el tipo de tabla que desees utilizar .

    3. Una vez elegida apretar ok, en donde aparecerá la tabla para ser creada.

    4. Poner los campos a usar y su tipo y tamaño.

    5. Luego guardar la tabla con Save As.

    USAR TABLA de DATOS desde C++ Builder

    1. Con el table elegido de Data Source, utilizar las propiedades para relacionarlo con la tabla creada.

    2. En las propiedades, en TableName, escribir el camino de donde se encuentra la tabla que necesitare.

    3. Por ultimo, en Active cambiar false por true, si el camino esta bien, no habrá ningún problema. Ya puedo trabajar con mi tabla.
    
    /////////////////////////////////////////////////
    //  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


    Para editar y modificar el contenido de una ficha de la tabla puedes usar la función Edit()
    
    ///////////////////////////////////////////////////
    // 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


    La manera más eficiente de buscar una ficha, ya sea para consultas o para modificaciones o para bajas es usar un Combo Box, cuyos algoritmos podras ver en los siguientes renglones.
    
    ///////////////////////////////////////////////////
    //   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


    Corresponden a los algoritmos de los típicos cuatro botones de navegación
    
    ///////////////////////////////////////////////////
    //  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


    En todos tus programas te haran falta alguno de estos algoritmos.
    
    ///////////////////////////////////////////////////
    //  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


    En los siguientes párrafos te propongo las alternativas más usuales para imprimir distintos tipos de archivos.
    
    ///////////////////////////////////////////////////
    //   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();
              };
        };
    }
    
    Vector
    Matriz
    Puntero
    Lista
    Cola
    Arbol
    Archivo
    Editor
    Agenda
    Base Datos
    Modelo

    PILAS y COLAS en C++BUILDER

    Colega virtual, aunque te parezca extraño existe toda una "Teoría de las Colas" la cual las clasifica en:
    • Colas Finitas
    • Colas Infinitas
    • Colas Simples
    • Colas Múltiples

    A las colas se las conoce también como "Filas de Espera", por lo tanto ya estás imaginando el rumbo de toda esta teoría cuyo análisis matemático por suerte, corresponde a la disciplina de la "Investigación Operativa", que por cierto es muy apasionante..!!

    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 manera clásica para idealizar una pila es pensar en la estructura que adopta la pila de platos, donde para aumentar otro plato en ella, es necesario colocarla en la parte superior y para retirar un plato, debemos levantar el que está en la cima o en la parte superior; por ello, las pilas son estructuras de datos tipo LIFO ( último en entrar, primero en salir): el último elemento que se coloca (mete o inserta) en la pila es el primero que se quita (saca o remueve) de ella.

    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.

    • Pila con apuntadores
    • Pila con arreglo

    METER Y SACAR...!!


    Realiza altas (Meter) insertando al frente de la lista y la baja (Sacar) eliminando el elemento que está al frente de la lista. Una operación cima solo examina el elemento del frente de la lista, devolviendo su valor. A veces la operación sacar y cima se combinan en una. Podríamos usar llamadas a las rutinas sobre listas enlazadas.

    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: Para las colas pueden aplicarse los procesos de los arreglos, usando la estructura de datos COLA[ ], y la posición Frente y Final, que representan los extremos de la cola, y Tamaño que es el numero de elementos de la cola.

    • Para encolar un elemento x, incrementamos Tamaño y Final, y luego hacemos COLA[Final] = x.
    • Para desencolar un elemento se pone en el valor a devolver COLA[Frente], se decrementa Tamaño y se incrementa Frente.

    Si no tienes experiencia en el manejo de estructuras dinámicas te recomiendo iniciar con otro link más simple, o en su defecto copia textualmente los siguientes que te propongo.
    
    //////////////////////////////////////////////////////
    // 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();
    }
    }
    

    MODELOS de PROGRAMAS en C++ BUILDER
    Volver al principio

    Colega virtual, si eres del mundo algoritmico en estos links encontrarás toda la información necesaria para manejar con solvencia los conceptos de:

    • Estructuras de datos dinámicas
    • Gestión integral de Archivos en C++
    • Programación Orientada a Objetos
    • Visualización de datos mediante grillas windows
    • Procedimientos de búsqueda por combo box
    • Manejo de imágenes dinámicas de video.

    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.

    • Elección de la ficha mediante combo box
    • Visualización de la ficha elegida para ser dada de baja.
    • Confirmación o cancelación de la eliminación
    • Baja lógica del Registro
    
    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
    

    PARADIGMA
    La ignorancia niega o agrede o critica
    La ciencia duda..!!
    Wilucha

    PARADIGMAS IMPRESOS:
    Lenguajes Gramáticas Autómatas Series
    Laplace Ecuación Operador Compilador

    PARADIGMA
    Cultivo una rosa blanca
    ..en julio, como en enero
    para el amigo sincero
    que me da su mano franca..!!

    Y para el cruel que me arranca
    el corazón con que vivo,
    cardo ni ortiga cultivo;
    ..cultivo una rosa blanca..!
    José Martí

    Mis Paradigmas

    Te espero en: wilucha@gmail.com

    Esta page está en: www.wilocarpio.com.ar

    11/09/2002

    Volver al principio