Ir al contenido


Foto

binarios y structuras


  • Por favor identifícate para responder
8 respuestas en este tema

#1 ifrit

ifrit

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 105 mensajes
  • LocationLa Habana, Cuba

Escrito 22 julio 2010 - 04:54

Hola scafandra!
He estado compicado con muchas cosas y no habia tenido la oportunidad de entrar a los foros y demas...
El tema que me trae es en el mismo que me has ayudado mucho sobr eficheros binarios y como leer, escribir, editar y eliminar de estos aca te dejo el codigo que una vez, amablemente me distes.

cpp
  1. //---------------------------------------------------------------------------
  2.  
  3. #include <vcl.h>
  4. #pragma hdrstop
  5.  
  6. #include "Unit1.h"
  7. //---------------------------------------------------------------------------
  8. #pragma package(smart_init)
  9. #pragma resource "*.dfm"
  10.  
  11. #include <fstream.h>
  12. #include <fcntl.h>
  13. #include<io.h>
  14.  
  15. using namespace std;
  16.  
  17. struct tipoRegistro {
  18.   char nombre[32];
  19.   int edad;
  20.   float altura;
  21. };
  22.  
  23. class TRegistros
  24. {
  25.   private:
  26.   TList* List;
  27.  
  28.   public:
  29.   TRegistros();
  30.   ~TRegistros();
  31.  
  32.   tipoRegistro& operator [] (int);
  33.   int GetCount();
  34.   void Insert(tipoRegistro& R);
  35.   void Add(tipoRegistro& R);
  36.   void Delete(int);
  37.   void ReadFile(char* FileName);
  38.   void WriteFile(char* FileName);
  39.   void Clear();
  40. };
  41.  
  42. TRegistros::TRegistros()
  43. {
  44.   List = new TList();
  45. }
  46.  
  47. TRegistros::~TRegistros()
  48. {
  49.   Clear();
  50.   delete List;
  51. }
  52.  
  53. // libera todos los registros
  54. void TRegistros::Clear()
  55. {
  56.   for(int n=0; n<List->Count;n++){
  57.     delete List->Items[n];
  58.     List->Items[n] = 0;
  59.   }
  60.   List->Clear();
  61. }
  62.  
  63. int TRegistros::GetCount()
  64. {
  65.   return List->Count;
  66. }
  67.  
  68. // Devuelve una referencia a un tipoRegistro pedido.
  69. // Si está fuera de rango devuelve el correspondiente al modulo.
  70. tipoRegistro& TRegistros::operator [] (int i)
  71. {
  72.   return *(tipoRegistro*)List->Items[i&List->Count];
  73. }
  74.  
  75. void TRegistros::Add(tipoRegistro& R)
  76. {
  77.   tipoRegistro* NewR = new tipoRegistro;
  78.   *NewR = R;
  79.   List->Add(NewR);
  80. }
  81.  
  82. void TRegistros::Delete(int i)
  83. {
  84.   delete List->Items[i];
  85.   List->Delete(i);
  86. }
  87.  
  88. // Esto lo puedes hacer con fstream también
  89. void TRegistros::ReadFile(char* FileName)
  90. {
  91.   int File = open(FileName, O_BINARY);
  92.   if(File ==-1) return;
  93.  
  94.   int Size = filelength(File);
  95.   int Count = Size/sizeof(tipoRegistro);
  96.   tipoRegistro* Items = new tipoRegistro[Count];
  97.   read(File, (void*)Items, Size);
  98.   close(File);
  99.   Clear();
  100.   for(int n=0; n<Count; n++)
  101.     Add(Items[n]);
  102.   delete [] Items;
  103. }
  104. /*
  105. // Esto lo puedes hacer con el sistema de bajo nivel también.
  106. // Funciona bien
  107. void TRegistros::WriteFile(char* FileName)
  108. {
  109.   ofstream fsalida(FileName, ios::trunc | ios::binary);
  110.   for(int n=0; n<List->Count; n++)
  111.     fsalida.write((char*)(List->Items[n]),sizeof(tipoRegistro));
  112.   fsalida.close();
  113. }
  114. */
  115. // Esto con el sistema de bajo nivel
  116. void TRegistros::WriteFile(char* FileName)
  117. {
  118.   int File = open(FileName, O_CREAT | O_TRUNC | O_BINARY | O_RDWR);
  119.   if(File ==-1) return;
  120.   for(int n=0; n<List->Count; n++)
  121.     write(File, List->Items[n], sizeof(tipoRegistro));
  122.   close(File);
  123. }
  124.  
  125.  
  126.  
  127. TForm1 *Form1;
  128. //---------------------------------------------------------------------------
  129. __fastcall TForm1::TForm1(TComponent* Owner)
  130.         : TForm(Owner)
  131. {
  132.   // Creo un objeto de la clase TRegistros:
  133.   TRegistros Registros;
  134.   // Creo un registro:
  135.   tipoRegistro Reg;
  136.   strcpy(Reg.nombre, "Jose Luis");
  137.   Reg.edad = 32;
  138.   Reg.altura = 1.78;
  139.   // Añado el registro:
  140.   Registros.Add(Reg);
  141.   strcpy(Reg.nombre, "Pepe Juan");
  142.   Reg.edad = 35;
  143.   Reg.altura = 2.05;
  144.   // Añado el registro:
  145.   Registros.Add(Reg);
  146.   strcpy(Reg.nombre, "Maria");
  147.   Reg.edad = 25;
  148.   Reg.altura = 1.70;
  149.   // Añado el registro:
  150.   Registros.Add(Reg);
  151.  
  152.   // Escribo archivo
  153.   Registros.WriteFile("Prueba.dat");
  154.  
  155. }
  156. //---------------------------------------------------------------------------
  157. void __fastcall TForm1::Button1Click(TObject *Sender)
  158. {
  159.   // Creo un objeto de la clase TRegistros:
  160.   TRegistros Registros;
  161.   // Leo archivo
  162. Registros.ReadFile("Prueba.dat");
  163. for(int i=0; i<Registros.GetCount(); i++){
  164.   Memo1->Lines->Add(Registros[i].nombre);
  165.   Memo1->Lines->Add("Edad: "+IntToStr(Registros[i].edad));
  166.   Memo1->Lines->Add("Talla: "+CurrToStr(Registros[i].altura));
  167. } 
  168. }
  169. //---------------------------------------------------------------------------


Como ves en la construccion del formulario ya tu agregar todos lo valores, cosa que haria yo desde unos edits...Tampoco truncaria el fichero cuando lo guardo, sino que agregaria la informacion nueva al final (int File = open(FileName, O_CREAT | O_APPEND | O_BINARY | O_RDWR);).
Pero te comento que el problema me lo esta dando cuando leeo la informacion porque si guardo  por ejemplo:
nombre: michel
edad: 34
alt: 1,78
y luego cualquier otro nombre con distintos datos
siempre me sale que hay dos registros , pero los dos son michel...
Podrias hacer una prueba y hecharle una ojeada por favor
muchs gracias

  • 0

#2 ifrit

ifrit

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 105 mensajes
  • LocationLa Habana, Cuba

Escrito 22 julio 2010 - 05:40

hola escafandra, estuve analizando mas el caso y dentro de la funcion ReadFile de la clase todo funciona ok porque dentro escribi


cpp
  1. ShowMessage(Items[n].nombre)


y efectivamente me muestr alos nombres que hay en el .dat
Parace que el problema esta en la llamada a esta funcion o en la forma de mostrar los resultados en el memo

  • 0

#3 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 22 julio 2010 - 07:45

Hola ifrit

No desesperes si escafandra no te contesta, es que lo mandamos de vacaciones, ya estaba insoportable :D :D :D

Salud OS
  • 0

#4 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 01 agosto 2010 - 06:11

Hola ifrit

No desesperes si escafandra no te contesta, es que lo mandamos de vacaciones, ya estaba insoportable :D :D :D

Salud OS


Pues os vais a fastidiar  ^o|... porque ya estoy de vuelta  :D :D :D

ifrit, he mirado lo que pasa y es sencillo, se trata de un error de transcripción en la función que sobrecarga el operador [], donde dice & debe ser %. sabes que el operador % encuentra el módulo o resto de una división. La función quedaría así:



cpp
  1. // Devuelve una referencia a un tipoRegistro pedido.
  2. // Si está fuera de rango devuelve el correspondiente al modulo.
  3. tipoRegistro& TRegistros::operator [] (int i)
  4. {
  5.   return *(tipoRegistro*)List->Items[i%List->Count];
  6. }



Saludos.
  • 0

#5 ifrit

ifrit

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 105 mensajes
  • LocationLa Habana, Cuba

Escrito 01 agosto 2010 - 09:56

Scafandra que bueno estes de vuleta nuevamente  :D :D :D un millon de gracias por el codigo, ya me tenias asustado  :|.
Tambien quiero agregarle a esa clase el poder compactar y mandar el fichero no solo para una carpeta, sino tambien para un ftp (lo de compactar sera con una libreria gratis .zip creo que zlib -no te especifico ahora pues no estoy en mi pc-, y lo de subir a un ftp con indy 10.x -los que vienen con codegear 2010-) Ya estare retomando el tema pues se me va de las manos, y espero me puedas seguri ayudando como siempre
muchas gracias y bienvenido nuevamente.
  • 0

#6 ifrit

ifrit

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 105 mensajes
  • LocationLa Habana, Cuba

Escrito 02 agosto 2010 - 07:22

scafandra yo el fichero no lo trunco cada vez, como sino que agregao continuamente informacion en el y cuando necesito editar una informacion lo que sucede es que vuelve a escribirme lo que estaba mas lo nuevo editado y como vez la informacion la tendria duplicada. No se como arreglar este problema
Espero me puedas ayudar.
  • 0

#7 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 02 agosto 2010 - 01:57

En ese caso, lo mejor será que reescribas nuevo el archivo completo, truncando el anterior cuando llames a la función WriteFile, tal y como te lo expuse en el código original:


cpp
  1. open(FileName, O_CREAT | O_TRUNC | O_BINARY | O_RDWR);



Saludos.
  • 0

#8 ifrit

ifrit

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 105 mensajes
  • LocationLa Habana, Cuba

Escrito 02 agosto 2010 - 04:04

Sucede que si dejo trunc lo que tenia se borra y solo se grega lo nuevo.
Por ejemplo hoy agregue
nombre:michel
edad:25
altura:1,75
luego guardo con writeFile y si luego deseo almacenar
nombre:Reinier
edad:27
altura:1,73
Se borra todo lo relacionado con michel y solo se agrega lo de Reinier, espero hacerme entender, lo que he hecho por el momento es leer el fichero con readFile, editar, eliminar el fichero fisico y luego writeFile, pero creo que esta un poco feo esto.
Espero me halla echo entender, gracias por la ayuda.
  • 0

#9 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 02 agosto 2010 - 05:12

Bueno, no se borrará si antes lo lees del archivo correspondiente, pues la clase TRegistros estará "cargada" con los datos previos...

Otra forma sería sin truncar el archivo pero no leerlo si vamos a añadir datos, de esta forma no tendríamos duplicados, pero esto me gusta menos.

Saludos.
  • 0




IP.Board spam blocked by CleanTalk.