Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Ayuda con archivos con Tipo (https://www.clubdelphi.com/foros/showthread.php?t=70662)

WPascal 03-11-2010 23:12:26

Ayuda con archivos con Tipo
 
Saludos a todos, estoy aprendiendo el manejo de archivos en Pascal y quize hacer un programita que leyera los datos de un juego de ajedrez y los almacenara en un record para poder guardar la informacion en un archivo con tipo, el problema es que el compilador me da un error que no sé que quiere decir, entonces necesito que me colaboren, qué error estoy cometiendo.
Aqui está el código:

Código Delphi [-]
program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

Type
    TDPartida = Record                               {Creo El tipo Record TDPartida
                                                      con datos blancas,negras,anyo y resultado }
                Blancas,Negras,Resultado:String;
                Anyo:Integer;
    End;
Var
    Partidas: file of TDPartida;   {Este es el Alias, donde tira el error}
    Juego:TDpartida;                {En la variable juego guardo la informacion}
                                     {que pasaré al archivo}
    NEntradas,I:Integer;
    {NEntradas es la cantidad de veces que se vana ingresar registros}
begin
    Assign(Partidas,'Resultados de las partidas.chess');
    Write('cuantos datos de partidas va a ingresar?: '); Readln(NEntradas);
    for I := 1 to NEntradas do  {Aqui pido los datos segun el valor de NEntradas}
        begin
            Writeln('Blancas:'); Read(Juego.Blancas);
            Writeln('Negras:'); Read(Juego.Negras);
            Writeln('Anyo:'); Read(Juego.Anyo);
            Writeln('Resultado:'); Read(Juego.Resultado);
            {Pregunto si el archivo existe}
            if not FileExists('Resultados de las partidas.chess') then
                Rewrite(Partidas);
            Reset(Partidas);  {pongo el archivo en modo escritura}
            Write(Partidas,Juego); {escribo en el archivo la informacion del record}
        end;
    Close(partidas);

end.

El compilador me tira el error:

[DCC Error] Project1.dpr(14): E2155 Type 'TDPartida' needs finalization - not allowed in file type

De antemano gracias por sus respuestas y su tiempo.

ecfisa 04-11-2010 01:12:16

Hola WPascal.

El problema te lo genera la línea: Blancas,Negras,Resultado:String;

El tipo string no puede aparecer en un archivo tipado, ya que su longitud es indeterminada.
Tenés que definir el tamaño, como por ejemplo:
Código Delphi [-]
    Blancas, Negras,Resultado: string[40]; // o la longitud que necesites

Saludos. :)

WPascal 04-11-2010 01:48:10

Hola, Ecfisa, nuevamente gracias por tu tiempo y colaborarme con este problema, hice el cambio que me solicitaste y de inmendiato funcionó, lo raro es que en el libro con el que me estoy guiando no decía nada de ese límite jaja.
Nuevamente gracias.
Hasta pronto.

roman 04-11-2010 02:00:33

¿Con qué libro te está guiando? Porque, si no mal recuedo, en versiones antiguas de Pascal (no sé si de Delphi), el tipo de datos string era equivalente a string[256], o sea, un tipo de datos de longitud fija.

// Saludos

WPascal 04-11-2010 02:09:47

El libro se llama Manual de FreePascal 1.0 para Win32

roman 04-11-2010 02:45:44

Hola,

Examinando por encima el manual que refieres, veo que, en efecto, en la sección donde hablan de archivos con tipo en ocasiones ponen el tipo string y en otras el tipo ShortString, al momento de delcarar el registro. Así que, les falta aclarar.

Por otra parte, en la sección donde habla de los tipos de datos fundamentales, menciona que string puede referirse a un ShortString (cadena de 255 caracteres) o a un AnsiString (número ilimitado de caracteres), dependiendo del modo en que se encuentre el compilador.

De hecho, esto es igual en Delphi. Dependiendo de la opción del compilador {$H} (activada por defecto). Si dejas tu código como lo tenías, pero pones {$H-} antes de la delcaración de TDPartida, verás que el compilador ya no protesta.

// Saludos

WPascal 04-11-2010 03:19:47

OK Roman, gracias de nuevo por la información.
Saludos.

ecfisa 04-11-2010 03:35:13

Hola.

Si, es así roman.

En realidad Tubo Pascal sólo definía el tipo de datos string, que como bién decis tenía un tamaño fijo de 256 bytes. Donde en la posición 0 del arreglo de caracteres se guardaba la longitud de la cadena almacenada. Es por eso que se podía utilzar Ord(s[0]) en lugar de la función Length.

El tipo ShortString es un nombre dado ya por Delphi al antiguo string de Pascal para diferenciarlo del AnsiString que trata las cadenas al modo
del lenguaje C.

De ahí que Delphi no pueda determinar a que tipo nos referimos y por lo tanto su longitud, como sucede en el caso de arriba. A no ser, claro, que se le indique al compilador como debe interpretarlas con una directiva.

Saludos. :)

WPascal 05-11-2010 01:49:39

Hola luego de resolver el problema del enlace me he dado cuenta de otro problema; por ejemplo, quiero ingresar tres registros, se supone que me deberían quedar guardados en el archivo con tipo, pero lo que hace el programa es reemplazar el registro anterior por el nuevo, he mirado el código pero no encuentro la falla, pues se supone que la función Reset abre el archivo para lectura/escritura no para sobreescribirlo, aquí les dejo el código para ver si me pueden ayudar qué estoy omitiendo.

Código Delphi [-]
program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

Type
    TDPartida = Record                               {Creo El tipo Record TDPartida
                                                      con datos blancas,negras,anyo y resultado }
                Blancas,Negras,Resultado:String[40];
                Anyo:Integer;
    End;
Var
    Partidas: file of TDPartida;   {Este es el Alias}
    Juego:TDpartida;                {En la variable juego guardo la informacion}
                                     {que pasaré al archivo}
    NEntradas,I:Integer;
    {NEntradas es la cantidad de veces que se vana ingresar registros}
begin
    Assign(Partidas,'Resultados de las partidas.chess');
    Write('cuantos datos de partidas va a ingresar?: '); Readln(NEntradas);
    for I := 1 to NEntradas do  {Aqui pido los datos segun el valor de NEntradas}
        begin
            Writeln('Blancas:'); Readln(Juego.Blancas);
            Writeln('Negras:'); Readln(Juego.Negras);
            Writeln('Anyo:'); Readln(Juego.Anyo);
            Writeln('Resultado:'); Readln(Juego.Resultado);

            {Pregunto si el archivo existe}
            if not FileExists('Resultados de las partidas.chess') then
                      Rewrite(Partidas);
                Reset(Partidas);  {pongo el archivo en modo escritura}
                Write(Partidas,Juego); {escribo en el archivo la informacion del record}
                Close(partidas);
        end;


end.
Nuevemante gracias de antemano
Saludos.

ecfisa 05-11-2010 02:08:20

Hola WPascal.

Reestructuré un poco tu código.
En tu ejemplo el archivo se debe abrir, realizar las operaciones y luego cerrar.
Lo que estabas haciendo es reescribir siempre el primer registro. Al hacer Reset(Partidas) dentro del ciclo, en cada ingreso el archivo se abre y el puntero se posiciona en el primer registro y allí se guarda.

Verifiqué la existencia del archivo, con try/except, para que veas otra forma de hacerlo.
Código Delphi [-]
program Project1;{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TDPartida = record
    Blancas,Negras,Resultado:String[40];
    Anyo:Integer;
  end;
var
  Partidas: file of TDPartida;
  Juego:TDpartida;
  NEntradas,I:Integer;
begin
  Assign(Partidas,'Resultados de las partidas.chess');
  try
    Reset(Partidas);
  except
    Rewrite(Partidas);
  end;
  Write('cuantos datos de partidas va a ingresar?: ');
  Readln(NEntradas);
  for I := 1 to NEntradas do
  begin
    Write('Blancas:');
    Readln(Juego.Blancas);
    Write('Negras:');
    Readln(Juego.Negras);
    Write('Anyo:');
    Readln(Juego.Anyo);
    Write('Resultado:');
    Readln(Juego.Resultado);
    Write(Partidas,Juego);
  end;
  Close(Partidas);
end.
end.

Saludos. :)

WPascal 05-11-2010 03:18:21

Claro!, yo pensaba que reset era solo para leer/escribir y no para pararse en el principio del archivo (Nuevamente le echo la culpa al libro :mad:). Pero de cualquier manera no tenía por qué meter el Reset en el For, jaja descuidos de principiante.
Gracias Ecfisa por tus siempre efectivas respuestas .:D Ya me empiezan a gustar más estos archivos de tipo ;) , por cierto, qué opinan de estos archivos, es bueno utilizarlo o son mejores los archivos .ini , porque de estos no he encontrado información útil.

ecfisa 05-11-2010 03:53:22

No tenés nada que agradecer, hoy por vos mañana por mi... ;)

Se puede usar Reset dentro de un for, lo que sucede que es de lo más ineficiente ya que abrir y cerrar archivos consume tiempo y recursos.
Te agrego un ejemplo donde se hace y aprovecho a usar otro modo para verificar la existencia del archivo.
Código Delphi [-]
...
begin
  Assign(Partidas,'Resultados de las partidas.chess');
  try
    Reset(Partidas);
  except
    Rewrite(Partidas);
  end;
  Write('cuantos datos de partidas va a ingresar?: ');
  Readln(NEntradas);
  for I := 1 to NEntradas do
  begin
    {$I-}                   // desactivar detección de errores
    Reset(Partidas);        // abrir
    if IOResult <> 0 then   // si no existe
      ReWrite(Partidas);    // crearlo
    {$I+}                   // activar detección de errores
    Write('Blancas:');
    Readln(Juego.Blancas);
    Write('Negras:');
    Readln(Juego.Negras);
    Write('Anyo:');
    Readln(Juego.Anyo);
    Write('Resultado:');
    Readln(Juego.Resultado);
    Seek(Partidas,FileSize(Partidas)); // ir al último registro
    Write(Partidas,Juego);             // guardar
    Close(Partidas);                   // cerrar
  end;
...

Fijate que use el procedimiento Seek para que no sobreescriba los registros.

Saludos. :)

WPascal 06-11-2010 02:35:38

Hola Ecfisa, precisamente tenía esa duda en cuanto a que se borraban los anteriores registros pero no le puse mucha atención por el momento porque en el programita que en que estoy trabajando necesito precisamente que se sobreescriba la información cada vez que se escriba en el archivo, pero ya tengo la duda aclarada para cuando necesite que no se borren los anteriores registros (que es lo más común) con la función Seek.
En cuanto a ayudarte yo a tí :eek: jaja lo veo difícil.
Pero en un futuro me gustaría por lo menos ayudar a los más novatos, cuando yo ya no lo sea tanto :p.
Gracias y saludos.

ecfisa 06-11-2010 03:54:17

Cita:

Empezado por WPascal (Mensaje 381517)
En cuanto a ayudarte yo a tí :eek: jaja lo veo difícil.
Pero en un futuro me gustaría por lo menos ayudar a los más novatos, cuando yo ya no lo sea tanto :p.
Gracias y saludos.

De nada WPascal.

Pero disiento con vos, yo no veo tán difícil que me puedas ayudar en cualquier momento... ;)

Saludos. :)


La franja horaria es GMT +2. Ahora son las 21:59:01.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi