Recent

Author Topic: Record type file doesn't print integer data properly  (Read 9749 times)

Zilveztre

  • New member
  • *
  • Posts: 7
Record type file doesn't print integer data properly
« on: November 22, 2014, 07:49:41 pm »
As the title says, the program asks you to put some numbers (on a record) than later on is written on a file. But when it gets to the point of printing that record(tSiemCos) it prints a bunch of symbols without any meaning... what am I doing wrong?  %)

Type declaration:
Code: [Select]
Type
   tCult= record
             codEsp: integer;
             nomb: string[15];
             resist: string[15];
             metod: string[10];
             mes: integer;
             dia: integer;
          end;
   tSiemCos= record
                codEsp: integer;
                anio: integer;
                mes: integer;
                dia: integer;
                cant: integer;
             end;
   tArchCult= File of tCult;
   tArchSiemCos= File of tSiemCos;


Procedure that prints the data on screen:
Code: [Select]
Procedure mostrarReg(var arch: tArchCult; reg:tSiemCos);

Var
   nomb: string;

begin
   nomb:= buscaNombre(arch,reg.codEsp);
   Writeln(reg.mes, '  ',reg.dia,'  ',nomb,'  ',reg.cant);
End;

Thanks a lot!!

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Record type file doesn't print integer data properly
« Reply #1 on: November 22, 2014, 08:34:11 pm »
What is the code for your buscaNombre() function?

eny

  • Hero Member
  • *****
  • Posts: 1634
Re: Record type file doesn't print integer data properly
« Reply #2 on: November 22, 2014, 10:59:27 pm »
Please show the entire program that asks for input, writes it to a file and reads it back.
My crystal ball is at the repair shop (high mileage; needs a big overhaul).
All posts based on: Win10 (Win64); Lazarus 2.0.10 'stable' (x64) unless specified otherwise...

Zilveztre

  • New member
  • *
  • Posts: 7
Re: Record type file doesn't print integer data properly
« Reply #3 on: November 23, 2014, 07:21:37 am »
Please show the entire program that asks for input, writes it to a file and reads it back.
My crystal ball is at the repair shop (high mileage; needs a big overhaul).

Is a 1000 line code, you really want me to post it here? xD. My question was simple enough. But well... I have here the extracts from the code that loads the data and writes it on the file:

This is the one that asks the data of the record:
Code: [Select]
Procedure cosecha(c, c1: string);

Var
   archCult: tArchCult;
   arch: tArchSiemCos;
   reg: tSiemCos;
   clave: integer;

begin
   Assign(arch, c1);
   reset(arch);
   Assign(archCult, c);
   Reset(archCult);
   If (FileSize(archCult)>=0) then
   begin
      Repeat
      begin
         Write('Ingrese el codigo de especie: ');
         Read(clave);
         If existeCult(archCult, clave) then
         begin
            reg.codEsp:= clave;
            completaCosecha(reg);
            insertaReg(arch, reg);
         end
         else
            Writeln('No existe Cultivo');
      end;
      Until confirma('Finalizar? (S/N)');
   end
   else
      Writeln('No hay Cultivos activos');
   Close(arch);
   Close(archCult);
end;

Now the function that makes sure that the data we're entering is valid (checking on another file)
Code: [Select]
Function existeCult(var arch: tArchCult; clave: integer): boolean;

Var
   regCu: tCult;
   existe: boolean;

begin
   existe:= false;
   Seek(arch, 0);
   Read(arch, regCu);
   While (not existe and not Eof(arch)) do
   begin
      If (clave<>regCu.codEsp) then
         Read(arch, regCu)
      else
         existe:= true;
   end;
   existeCult:= existe;
end;

In this one the record is filled:
Code: [Select]
Procedure completaCosecha(reg: tSiemCos);

Var
   a, m, d: integer;

begin
   Repeat
   begin
      Repeat
      begin
         Write('Ingrese el anio de la cosecha: ');
         Read(a);
         m:= enteroEnRango('Ingresar el mes de la cosecha: ', 1, 12);
         d:= enteroEnRango('Ingresar el dia de la cosecha: ', 1, 31);
      end;
      Until fechaValida(a, m, d);
      Writeln ('Anio: ',a, ', Mes: ', m, ', Dia: ', d);
   end;
   Until confirma('Finalizar? (S/N)');
   reg.anio:=a;
   reg.mes:=m;
   reg.dia:=d;
   Write('Ingresar las unidades cosechadas: ');
   Repeat
         Read(reg.cant);
   Until reg.cant>0;
end;

This one is the one that writes the record on the file in the correct orde (for the listing afterwards):
Code: [Select]
Procedure insertaReg(var arch: tArchSiemCos; regN: tSiemCos);
(* Inserta en el archivo el registro nuevo respetando el orden (por año y mes).
Precondición: arch= Archivo ordenado. Ingresado como parámetro.
              regN= Registro nuevo a insertar de manera ordenada en el archivo.
Poscondición: arch= Ordenado y con regN insertado en su orden.
*)

Var
   reg: tSiemCos;
   pos: integer;
   encontrePos: boolean;

   begin
         pos:= FileSize(arch) - 1;
         encontrePos:= False;
         if (not eof(arch)) then    // Entra si el archivo no esta vacío
         begin
            While (pos>=0)and(not encontrePos) do
            begin
               Seek(arch, pos);
               read(arch, reg);
               If (reg.anio>regN.anio) then
               begin
                  Write(arch, reg);
                  pos:= pos - 1;
               end
               else
               begin
                  If (reg.anio=regN.anio) then
                  begin
                     If (reg.mes>regN.mes) then
                     begin
                        Write(arch, reg);
                        pos:= pos - 1;
                     end
                     else
                     begin
                        If (reg.mes=regN.mes) then
                        begin
                           If (reg.dia>regN.dia) then
                           begin
                              Write(arch, reg);
                              pos:= pos - 1;
                           end
                           else
                           begin
                              If (reg.dia=regN.dia) then
                              begin
                                 If (reg.codEsp>regN.codEsp) then
                                 begin
                                    Write(arch, reg);
                                    pos:= pos - 1;
                                 end
                                 else
                                 begin
                                    If (reg.codEsp=regN.codEsp) then
                                    begin
                                       Seek(arch, pos);
                                       Write(arch, reg);
                                    end
                                    else
                                    encontrePos:= True;
                                 end;
                              end
                              else
                                 encontrePos:= True;
                           end;
                        end
                        else
                           encontrePos:= True;
                     end;
                  end
                  else
                     encontrePos:= True;
                  end;
            end;
         end
         else                  // Si el archivo esta vacío...
            Write(arch, reg);  // Escribe el primer registro ingresado al archivo.
   end;

This is the one that prints on the screen in order:
Code: [Select]
Procedure listaCos(c1, c2: string);
(* Lista las cosechas ordenadas por código de especie, año y mes.
Precondición: c1, c2= Nombre de los archivos necesarios a abrir para recuperar datos.
Poscondición: --
*)

Const
   tope=30;

Var
   archCu: tArchCult;
   archCos: tArchSiemCos;
   regCos, ant: tSiemCos;
   cMes, cEsp, hojas, lineas: integer;

begin
   cEsp:= 0;
   cMes:= 0;
   hojas:= 0;
   Assign(archCu, c1);
   Reset(archCu);
   Assign(archCos, c2);
   Reset(archCos);
   iniciaAnterior(archCos, ant);                   // This procedure copies the first record on the file for the control breaks of the list
   Seek(archCos, 0);
   encabezadoAnio(ant.anio, hojas, lineas);
   encabezadoCos(lineas);
   While not Eof(archCos) do
   begin
      Read(archCos, regCos);
      If (regCos.codEsp<>ant.codEsp) then
      begin
         subtotalMes('Subtotal mes: ', cMes, cEsp, lineas);
         subtotalEsp('Subtotal especie: ', cEsp, lineas);
         encabezadoCos(lineas);
      end
      else
      begin
         if (regCos.mes<>ant.mes) then
         begin
            subtotalMes('Subtotal mes: ', cMes, cEsp, lineas);
            encabezadoCos(lineas);
         end;
      end;
      ant:= regCos;
      If (lineas>tope) then
      begin
         pieDePagina();
         encabezadoAnio(regCos.anio, hojas, lineas);
         encabezadoCos(lineas);
      end;
      mostrarReg(archCu, regCos);
      lineas:= lineas + 1;
      cMes:= cMes + 1;
   end;
   subtotalMes('Subtotal mes: ', cMes, cEsp, lineas);
   subtotalEsp('Subtotal especie: ', cEsp, lineas);
   Close(archCu);
   Close(archCos);
End;

And this is what I get on cmd:
http://imagizer.imageshack.us/a/img540/2472/xx7Lce.jpg

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Record type file doesn't print integer data properly
« Reply #4 on: November 23, 2014, 09:46:39 am »
My question was simple enough. But well... I have here the extracts

Simple answer: you are both the author and have all the code (the design, the full picture), and cannot successfully debug it. Yet you expect others who have never seen most of your code to divine where the error(s) are by looking at fragments?
With some puzzles (deciphering the Dead Sea Scrolls, for example) you may be restricted to fragments. But not in this case.

Zilveztre

  • New member
  • *
  • Posts: 7
Re: Record type file doesn't print integer data properly
« Reply #5 on: November 23, 2014, 11:22:52 am »
My question was simple enough. But well... I have here the extracts

Simple answer: you are both the author and have all the code (the design, the full picture), and cannot successfully debug it. Yet you expect others who have never seen most of your code to divine where the error(s) are by looking at fragments?
With some puzzles (deciphering the Dead Sea Scrolls, for example) you may be restricted to fragments. But not in this case.

Ok then, here it is the full code!

Code: [Select]
program Cosechas;

// Declaración de librerías
uses
   crt;

// Declaración de tipos de datos
Type
   tCult= record
             codEsp: integer;
             nomb: string[15];
             resist: string[15];
             metod: string[10];
             mes: integer;
             dia: integer;
          end;
   tSiemCos= record
                codEsp: integer;
                anio: integer;
                mes: integer;
                dia: integer;
                cant: integer;
             end;
   tArchCult= File of tCult;
   tArchSiemCos= File of tSiemCos;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//                                SUBPROGRAMAS                                //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Function confirma(c: string): boolean;

Var
   resp: char;

begin
   Write(c);
   Repeat
      Read(resp);
   Until (resp in ['n','N','s','S']);
   confirma:= (resp in ['s','S']);
end;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Function enteroEnRango(c: string; t1, t2: integer): integer;

Var
   nro: integer;

begin
   Repeat
   begin
      Write(c);
      Read(nro);
   end;
   Until (nro>= t1)and(nro<=t2);
   enteroEnRango:= nro;
end;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Function existeArch(nombre:string):boolean;
Var
   F:File;
Begin
   Assign(f, nombre);
   {$I-}
   reset(f);
   close(f);
   existeArch:= (IOResult = 0);
   {$I+}
End;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Procedure pieDePagina();
(* Muestra el pie de página al finalizar de listar una hoja.
Precondición: --
Poscondición: --
*)

begin
   Write('Presione cualquier tecla para continuar.');
   ReadKey;
End;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Procedure encabezadoSie(var lineas: integer);
(* Muestra el encabezado  de la siembra que se esta mostrando.
Precondición: líneas= Contador de control. Cuenta las líneas impresas en pantalla.
Poscondición: líneas= Aumenta en la cantidad de líneas utilizadas por el encabezado.
*)

begin
   Writeln('Mes         Dia           Nombre Especie        Cantidad Sembrada');
   Writeln('');
   lineas:= lineas + 1;
End;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Procedure encabezadoCos(var lineas: integer);
(* Muestra el encabezado  de la cosecha que se esta mostrando.
Precondición: líneas= Contador de control. Cuenta las líneas impresas en pantalla.
Poscondición: líneas= Aumenta en la cantidad de líneas utilizadas por el encabezado.
*)

begin
   Writeln('Mes         Dia           Nombre Especie        Cantidad Cosechada');
   Writeln('');
   lineas:= lineas + 2;
End;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Procedure encabezadoAnio(anio: integer; var hojas: integer; var lineas: integer);
(* Muestra el encabezado del año y página.
Precondición: año= Año del que se esta listando.
              hojas= Número de hoja que se esta imprimiendo.
              líneas= Contador de control. Cuenta las líneas impresas en pantalla.
Poscondición: hojas= Aumenta en 1 para su próxima aparición en pantalla.
              lineas= aumenta en la cantidad de líneas utilizadas por el encabezado.
*)

begin
   clrscr;
   hojas:= hojas + 1;
   Writeln('Año: ', anio, '      Hoja: ', hojas);
   Writeln('');
   lineas:= lineas + 2;
End;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Procedure subtotalMes(c: string; var cMes: integer; var cEsp: integer; var lineas: integer);
(* Muestra el subtotal del mes listado.
Precondición: c= Mensaje a mostrar
              cMes= Contador de elementos listados por mes(descarga su valor en cEsp).
              cEsp= Contador de elementos listados por especie.
              Líneas= Contador de control. Cuenta las líneas impresas en pantalla.
Poscondición: --
*)

begin
   Writeln('');
   Writeln(c, cMes);
   cEsp:= cEsp +cMes;
   cMes:= 0;
   lineas:= lineas + 2;
End;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Procedure subtotalEsp(c: string; var cEsp: integer; var lineas: integer);
(* Muestra el subtotal de la especie listada
Precondición: c= Mensaje a mostrar.
              cEsp= Contador de lista
              líneas= Contador de control. Cuenta las líneas impresas en pantalla.
Poscondición: --
*)

begin
   Writeln(c, cEsp);
   cEsp:= 0;
   lineas:= lineas + 1;
End;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Function buscaNombre(var arch:tArchCult; cod: integer): string;
(* Busca el nombre del cultivo coincidente con el código de especie ingresado.
Precondición: cod= Código de especie ingresado para su comparación.
arch= Archivo dentro del que se debe encontrar el nombre coincidente con cod.
Poscondición: c: cadena= Nombre del cultivo recuperado de la búsqueda realizada.
*)

Var
   encontre: boolean;
   reg: tCult;
   nomb: string[15];

begin

   encontre:= false;
   seek(arch, 0);
   While (not Eof(arch)) and (not encontre) do
   begin
      Read(arch, reg);
      If reg.codEsp = cod then
      begin
         nomb:= reg.nomb;
         encontre:= True;
      end;
   end;
   buscaNombre:= nomb;
end;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Procedure mostrarReg(var arch: tArchCult; reg:tSiemCos);
(* Muestra los datos necesarios del registro en pantalla.
Precondición: reg= Registro a mostrar.
arch= Necesario para recuperar el nombre del cultivo al que apunta el código
  de especie de reg.
Poscondición: --
*)

Var
   nomb: string;

begin
   nomb:= buscaNombre(arch,reg.codEsp);
   Writeln(reg.mes, '  ',reg.dia,'  ',nomb,'  ',reg.cant);
End;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Procedure iniciaAnterior(var arch:tArchSiemCos; var ant:tSiemCos);
(* Inicializa el primer registro del archivo en una variable ant para su comparación. Una vez hecho esto vuelve el puntero interno a la posición con la que entro al Procedimiento.
Precondición: arch= Archivo con datos de tipo registro. Ingresa como parámetro y es de E/S.
Poscondición: ant= Estructura de tipo registro que almacena el primer registro del archivo leído.
*)

Var
   pos: integer;

begin
   pos:= FilePos(arch);
   read(arch, ant);
   Seek(arch, pos);
End;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Procedure listaSie(c1, c2: string);
(*  Lista las siembras ordenadas por código de especie, año y mes.
Precondición: c1, c2= Nombres de los archivos necesarios a abrir para la recuperación de datos.
Poscondición: --
*)

Const
   tope= 30;

var
   archCu: tArchCult;
   archSiem: tArchSiemCos;
   regSiem, ant: tSiemCos;
   cMes, cEsp, hojas, lineas: integer;

begin
   cMes:= 0;
   cEsp:= 0;
   hojas:= 0;
   Assign(archCu, c1);
   Reset(archCu);
   Assign(archSiem, c2);
   Reset(archSiem);
   iniciaAnterior(archSiem, ant);
   Seek(archSiem, 0);
   encabezadoAnio(ant.anio, hojas, lineas);
   encabezadoSie(lineas);
   While not Eof(archSiem) do
   begin
      Read(archSiem, regSiem);
      If (regSiem.codEsp<>ant.codEsp) then
      begin
         subtotalMes('Subtotal mes: ', cMes, cEsp, lineas);
         subtotalEsp('Subtotal especie: ', cEsp, lineas);
         encabezadoSie(lineas);
      end
      else
      begin
         if (regSiem.mes<>ant.mes) then
         begin
            subtotalMes('Subtotal mes: ', cMes, cEsp, lineas);
            encabezadoSie(lineas);
         end;
      end;
      ant:= regSiem;
      If (lineas>tope) then
      begin
         pieDePagina();
         encabezadoAnio(regSiem.anio, hojas, lineas);
         encabezadoSie(lineas);
      end;
      mostrarReg(archCu,regSiem);
   end;
   subtotalMes('Subtotal mes: ', cMes, cEsp, lineas);
   subtotalEsp('Subtotal especie: ', cEsp, lineas);
   Close(archCu);
   Close(archSiem);
End;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Procedure listaCos(c1, c2: string);
(* Lista las cosechas ordenadas por código de especie, año y mes.
Precondición: c1, c2= Nombre de los archivos necesarios a abrir para recuperar datos.
Poscondición: --
*)

Const
   tope=30;

Var
   archCu: tArchCult;
   archCos: tArchSiemCos;
   regCos, ant: tSiemCos;
   cMes, cEsp, hojas, lineas: integer;

begin
   cEsp:= 0;
   cMes:= 0;
   hojas:= 0;
   Assign(archCu, c1);
   Reset(archCu);
   Assign(archCos, c2);
   Reset(archCos);
   iniciaAnterior(archCos, ant);
   Seek(archCos, 0);
   encabezadoAnio(ant.anio, hojas, lineas);
   encabezadoCos(lineas);
   While not Eof(archCos) do
   begin
      Read(archCos, regCos);
      If (regCos.codEsp<>ant.codEsp) then
      begin
         subtotalMes('Subtotal mes: ', cMes, cEsp, lineas);
         subtotalEsp('Subtotal especie: ', cEsp, lineas);
         encabezadoCos(lineas);
      end
      else
      begin
         if (regCos.mes<>ant.mes) then
         begin
            subtotalMes('Subtotal mes: ', cMes, cEsp, lineas);
            encabezadoCos(lineas);
         end;
      end;
      ant:= regCos;
      If (lineas>tope) then
      begin
         pieDePagina();
         encabezadoAnio(regCos.anio, hojas, lineas);
         encabezadoCos(lineas);
      end;
      mostrarReg(archCu, regCos);
      lineas:= lineas + 1;
      cMes:= cMes + 1;
   end;
   subtotalMes('Subtotal mes: ', cMes, cEsp, lineas);
   subtotalEsp('Subtotal especie: ', cEsp, lineas);
   Close(archCu);
   Close(archCos);
End;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Function esBisiesto(anio: integer): boolean;
(* Verifica si un año dado es bisiesto o no.
Precondición: año = A, valor entero ingresado como parámetro.
Poscondición: Verdadero= Si el año se verifica como bisiesto.
              Falso= Si el año no es bisiesto.
*)

begin
   esBisiesto:= ((anio MOD 4 = 0)and(anio MOD 100 <> 0))or(anio MOD 400 = 0);
end;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Function fechaValida(a, m, d: integer): boolean;
(* Verifica que la fecha ingresada sea válida.
Precondición: a= Dato entero representativo del año ingresado.
              m= Dato entero representativo del mes ingresado.
              d= Dato entero representativo del día ingresado.
Poscondición: Verdadero= Si la fecha es válida.
              Falso= Si la fecha ingresada no es válida.
*)

Var
   topeD: integer;

begin
   case m of
      1, 3, 5, 7, 8, 10, 12: topeD:= 31;
      4, 6, 9, 11: topeD:= 30;
      2: if esBisiesto(a) then
            topeD:= 29
         else
            topeD:= 28;
   end;
   fechaValida:= (d<= topeD)and(d>0);
end;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Procedure completaCosecha(reg: tSiemCos);
(* Completa los datos del registro de cosechas.
Precondición: reg= Registro a modificar. Ingresado como parámetro.
Poscondición: reg= Registro modificado.
*)

Var
   a, m, d: integer;

begin
   Repeat
   begin
      Repeat
      begin
         Write('Ingrese el anio de la cosecha: ');
         Repeat
            Read(a);
         until a>0;
         m:= enteroEnRango('Ingresar el mes de la cosecha: ', 1, 12);
         d:= enteroEnRango('Ingresar el dia de la cosecha: ', 1, 31);
      end;
      Until fechaValida(a, m, d);
      Writeln ('Anio: ',a, ', Mes: ', m, ', Dia: ', d);
   end;
   Until confirma('Finalizar? (S/N)');
   reg.anio:=a;
   reg.mes:=m;
   reg.dia:=d;
   Write('Ingresar las unidades cosechadas: ');
   Repeat
         Read(reg.cant);
   Until reg.cant>0;
end;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Function existeCult(var arch: tArchCult; clave: integer): boolean;
(* Verifica si existe el cultivo del que se ingresó la clave.
Precondición: clave = Dato entero ingresado como parámetro.
              c= Nombre del archivo a verificar.
Poscondición: Verdadero= Si existe la clave(y por ende también el cultivo) en el archivo.
              Falso= SI la clave no se corresponde con ninguna dentro del archivo.
*)

Var
   regCu: tCult;
   existe: boolean;

begin
   existe:= false;
   Seek(arch, 0);
   Read(arch, regCu);
   While (not existe and not Eof(arch)) do
   begin
      If (clave<>regCu.codEsp) then
         Read(arch, regCu)
      else
         existe:= true;
   end;
   existeCult:= existe;
end;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Procedure insertaReg(var arch: tArchSiemCos; regN: tSiemCos);
(* Inserta en el archivo el registro nuevo respetando el orden (por año y mes).
Precondición: arch= Archivo ordenado. Ingresado como parámetro.
              regN= Registro nuevo a insertar de manera ordenada en el archivo.
Poscondición: arch= Ordenado y con regN insertado en su orden.
*)

Var
   reg: tSiemCos;
   pos: integer;
   encontrePos: boolean;

   begin
         pos:= FileSize(arch) - 1;
         encontrePos:= False;
         if (not eof(arch)) then    // Entra si el archivo no esta vacío
         begin
            While (pos>=0)and(not encontrePos) do
            begin
               Seek(arch, pos);
               read(arch, reg);
               If (reg.anio>regN.anio) then
               begin
                  Write(arch, reg);
                  pos:= pos - 1;
               end
               else
               begin
                  If (reg.anio=regN.anio) then
                  begin
                     If (reg.mes>regN.mes) then
                     begin
                        Write(arch, reg);
                        pos:= pos - 1;
                     end
                     else
                     begin
                        If (reg.mes=regN.mes) then
                        begin
                           If (reg.dia>regN.dia) then
                           begin
                              Write(arch, reg);
                              pos:= pos - 1;
                           end
                           else
                           begin
                              If (reg.dia=regN.dia) then
                              begin
                                 If (reg.codEsp>regN.codEsp) then
                                 begin
                                    Write(arch, reg);
                                    pos:= pos - 1;
                                 end
                                 else
                                 begin
                                    If (reg.codEsp=regN.codEsp) then
                                    begin
                                       Seek(arch, pos);
                                       Write(arch, reg);
                                    end
                                    else
                                    encontrePos:= True;
                                 end;
                              end
                              else
                                 encontrePos:= True;
                           end;
                        end
                        else
                           encontrePos:= True;
                     end;
                  end
                  else
                     encontrePos:= True;
                  end;
            end;
         end
         else                  // Si el archivo esta vacío...
            Write(arch, reg);  // Escribe el primer registro ingresado al archivo.
   end;

Zilveztre

  • New member
  • *
  • Posts: 7
Re: Record type file doesn't print integer data properly
« Reply #6 on: November 23, 2014, 11:23:58 am »
Here's the second part... I couldn't post it as a whole because of characters limit on the forum:

Code: [Select]
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Procedure cosecha(c, c1: string);
(* Carga o modifica el archivo que registra las cosechas.
Precondición: c= Nombre del archivo a modificar
              c1= Nombre del archivo de referencia para verificar la existencia de la especie.
Poscondición: arch= Archivo de nombre c, modificado con un registro nuevo.
*)

Var
   archCult: tArchCult;
   arch: tArchSiemCos;
   reg: tSiemCos;
   clave: integer;

begin
   Assign(arch, c1);
   reset(arch);
   Assign(archCult, c);
   Reset(archCult);
   If (FileSize(archCult)>=0) then
   begin
      Repeat
      begin
         Write('Ingrese el codigo de especie: ');
         Read(clave);
         If existeCult(archCult, clave) then
         begin
            reg.codEsp:= clave;
            completaCosecha(reg);
            insertaReg(arch, reg);
         end
         else
            Writeln('No existe Cultivo');
      end;
      Until confirma('Finalizar? (S/N)');
   end
   else
      Writeln('No hay Cultivos activos');
   Close(arch);
   Close(archCult);
end;


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Procedure completaSiemb(var reg:tSiemCos);
(* Completa los datos del registro de siembra.
Precondición: reg= Registro a modificar. Ingresado como parámetro.
Poscondición: reg= Registro modificado.
*)

Var
   a, m, d: integer;

begin
   Repeat
   begin
      Repeat
      begin
         Writeln('Ingresar el anio de la siembra: ');
         Read(a);
         m:= enteroEnRango('Ingresar el mes de la siembra: ', 1, 12);
         d:= enteroEnRango('Ingresar el dia de la siembra: ', 1, 31);
      end;
      Until fechaValida(a, m, d);
      writeln ('Anio: ',a, ', Mes: ', m, ', Dia: ', d);
   end;
   Until confirma('Fecha Correcta? (S/N)');
   reg.anio:=a;
   reg.mes:=m;
   reg.dia:=d;
   Writeln('Ingresar las unidades sembradas');
   Repeat
         Read(reg.cant);
   Until (reg.cant>0);
end;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Procedure siembra(c, c1: string);
(* Carga o modifica el archivo que registra las siembras
Precondición: c= Nombre del archivo a modificar (Ingresado como parámetro).
Poscondición: arch= Modificado con el nuevo registro añadido.
*)

Var
   archCult: tArchCult;
   arch: tArchSiemCos;
   reg: tSiemCos;
   clave: integer;

begin
   Assign(arch, c1);
   Reset(arch);
   Assign(archCult, c);
   Reset(archCult);
   If (fileSize(archCult)>=0) then
   begin
      Repeat
      begin
         Writeln('Ingrese el código de especie: ');
         Read(clave);
         If existeCult(archCult, clave) then
            begin
            reg.codEsp:= clave;
            completaSiemb(reg);
            insertaReg(arch, reg);
            end
         else
             writeln('No existe Cultivo');
      end;
      Until confirma('Finalizar? (S/N)');
   end
   else
      Writeln('No hay Cultivos activos');
   Close(arch);
   Close(archCult);
end;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Function claveEnUso(var arch:tArchCult; dato: integer): boolean;
(* Busca en el archivo si la clave está en uso
Precondición: arch= Archivo abierto e ingresado como parámetro.
              dato= Código de especie ingresado por parámetro para la verificación.
Poscondición: Verdadero= Si la clave está en uso.
              Falso= Si la clave no está en uso.
*)

Var
   pos: integer;
   val: boolean;
   reg: tCult;

begin

   val:= false;
   pos:= FilePos(arch);
   seek(arch, 0);
   while ((not Eof(arch)) and (not val)) do
   begin
      read(arch, reg);
      if (reg.codEsp=dato) then
         val:=true;
   end;
   seek(arch,pos);
   claveEnUso:= val
end;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Procedure ingresarResistenciaHeladas(var res: integer);
(* Valida el ingreso del tipo de resistencia a heladas del cultivo siendo procesado
Precondición: res= Variable de tipo entero ingresada por parámetro.
Poscondición: res= R, Valor entero representativo del tipo de resistencia a las heladas.
*)

begin
   writeln('Indique la resistencia del cultivo a las heladas.');
   writeln('   1. Muy Resistente');
   writeln('   2. Resistente');
   writeln('   3. Muy Sensible');
   writeln('   4. Sensible');
   Writeln('');
   res:= enteroEnRango('Ingrese el tipo de resistencia: ', 1, 4);
   Writeln('');
   Writeln('');
end;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Procedure ingresarMetodoSiembra(var res: integer);
(* Valida el ingreso del método de siembra del cultivo siendo procesado.
Precondición: res= Variable de tipo entero ingresada como parámetro.
Poscondición: res= R, Valor representativo del método de siembra utilizado para el cultivo.
*)

begin
   writeln('Ingrese el metodo de siembra del cultivo.');
   writeln('   1. Directo');
   writeln('   2. Almacigo');
   Writeln('');
   res:= enteroEnRango('Ingrese el metodo de siembra: ', 1, 2);
   Writeln('');
   Writeln('');
end;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Function confirmaNomb(var arch: tArchCult; nomb:string): boolean;

var

   reg: tCult;
   encontre: boolean;
   pos:integer;

begin
   pos:= FilePos(arch);
   encontre:=false;
   seek (arch,0);
   while ((not Eof(arch))and(not encontre)) do

    begin
      read(arch, reg);  // Recupera el primer registro del archivo
      if (nomb=reg.nomb) then  // Si los nombres son iguales...
              encontre:= true
 //     else
 //        begin
 //             if not Eof(arch)then
 //             read(arch, reg);  // Si los nombres no son iguales sigue leyendo
 //        end;
   end;
   confirmaNomb:= encontre;
   seek(arch,pos);
end;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Procedure completaCult(var reg:tCult);
(* Completa el registro con los valores del cultivo.
Precondición:
Poscondición:
*)

Var
   res, dia: integer;

begin
   res:= 0;
   Write('Ingrese el nombre del cultivo: ');
   REPEAT
         readln(reg.nomb);
   until (reg.nomb<>'');
   Writeln('');
   Writeln('');

  ingresarResistenciaHeladas(res);
   case res of
      1: reg.resist:= 'Muy Resistente.';
      2: reg.resist:= 'Resistente.';
      3: reg.resist:= 'Muy Sensible.';
      4: reg.resist:= 'Sensible.';
   end;
   ingresarMetodoSiembra(res);
   case res of
      1: reg.metod:= 'Directo.';
      2: reg.metod:= 'Almacigo.';
   end;
   reg.mes:= enteroEnRango('Ingrese el mes de plantacion: ', 1, 12);
   write('Ingrese la cantidad de dias antes de la cosecha: ');
   Repeat
         Read(dia);
   Until (dia>0);
   reg.dia:= dia;

end;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Procedure modifCult(c: string);
(* Modifica el cultivo seleccionado
Precondición: c= Nombre del archivo a modificar. Ingresa como parámetro.
Poscondición: arch= Archivo modificado con el registro nuevo en la posición(clave) del registro
anterior.
*)

Var
   arch: tArchCult;
   reg: tCult;
   clave: integer;

begin
   assign(arch, c);
   reset(arch);
   If FileSize(arch)>0 then
   begin
      Repeat
      begin
         Repeat
         begin
            Writeln('Ingrese el código de especie: ');
            Read(clave);
         end;
         Until confirma('Dato correcto? (S/N)');
         If claveEnUso(arch,clave) then
         begin
            Seek(arch, clave);
            Read(arch, reg);
            completaCult(reg);
            Seek(arch, clave);
            Write(arch, reg);
            Writeln('Cultivo ', reg.nomb, ' modificado.');
         end
         else
            Writeln('Codigo de especie no existente.');
      end;
      Until confirma('Finalizar modificacion? (S/N)');
   end;
   If FileSize(arch)=0 then
   Writeln('Archivo vacio. No se hizo nada.');
   Writeln('');
   Close(arch);
end;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Procedure altaCult(c: string);
(* Modifica el archivointroduciendo un nuevo registro de cultivo.
Precondición: c= Nombre del archivo a modificar. Ingresa como parámetro.
Poscondición: archCu= Con un nuevo registro escrito en una nueva posición.
*)

Var
   arch: tArchCult;
   reg: tCult;


begin
   Assign(arch, c);
   Reset(arch);                         // Abre el archivo
   Repeat
   begin
      Seek(arch, FileSize(arch));       // Se posiciona al final del archivo
      reg.codEsp:= FileSize(arch);      // Guarda la ultima posición del archivo como clave
      Writeln('Se va a realizar el alta de un cultivo.');
      Writeln('');
      If (fileSize(arch)>=0) then
         begin
              completaCult(reg);
              If not confirmaNomb(arch,reg.nomb) then
              begin
                   Write(arch, reg);
                   Writeln('Cultivo ', reg.nomb, ' dado de alta con el codigo ', reg.codEsp);
              end
              else
              begin
                   Writeln('Nombre de cultivo en uso. Ingrese otro.');
              end;
         end;

   end;

   until confirma('Finalizar carga? (S/N)');
   close(arch);
end;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Procedure menu(var o1:integer; var o2:integer);

begin
   clrscr;
   Repeat
      Writeln('1. Realizar altas/modificaciones.');
      Writeln('2. Mostrar listado de siembras/cosechas.');
      o1:= enteroEnRango('Ingrese opcion: ', 1, 2);
      Writeln('');
      If o1=1 then
      begin
         Writeln('1. Dar de alta un cultivo.');
         Writeln('2. Modificar un cultivo.');
         Writeln('3. Registrar siembra.');
         Writeln('4. Registrar cosecha.');
         o2:= enteroEnRango('Ingrese opcion: ', 1, 4);
         Writeln('');
      end;
      If o1=2 then
      begin
         Writeln('1. Listar siembras.');
         Writeln('2. Listar cosechas.');
         o2:= enteroEnRango('Ingrese opcion: ', 1, 2);
         Writeln('');
      end;
   Until not confirma('Reingresar opciones? (S/N)');
   clrscr;
end;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Procedure creaArchivos(c1, c2, c3: string);
(* Crea los archivos necesarios para la ejecución del programa.
Precondición: c1, c2, c3= nombres de los archivos a crear.
Poscondición: --
*)

Var
   archCult: tArchCult;
   archSiemCos: tArchSiemCos;

begin
   if not existeArch(c1) then
   begin
      assign(archCult, c1);
      rewrite(archCult);
      close(archCult);
   end;
   if not existeArch(c2) then
   begin
      assign(archSiemCos, c2);
      rewrite(archSiemCos);
      close(archSiemCos);
   end;
   if not existeArch(c3) then
   begin
      assign(archSiemCos, c3);
      rewrite(archSiemCos);
      close(archSiemCos);
   end;
end;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//                            Programa principal                              //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

Var
   opc1, opc2: integer;
   c1, c2, c3: string[70];

begin
   opc1:= 0;
   opc2:= 0;
   c1:= 'Cultivos.dat';
   c2:= 'Cosecha.dat';
   c3:= 'Siembra.dat';
   creaArchivos(c1, c2, c3);
   Repeat
   begin
      menu(opc1, opc2);
      if opc1=1 then
      begin
         case opc2 of
            1: altaCult(c1);
            2: modifCult(c1);
            3: siembra(c1, c3);
            4: cosecha(c1, c2);
         end;
      end;
      if opc1=2 then
      begin
         case opc2 of
            1: listaCos(c2, c1);
            2: listaSie(c3, c1);
         end;
      end;
   end;
   until confirma('Salir? (S/N)');
end.   

I didn't wanted to put the code in here because it's for an assignment I have in college. So I just wanted some posibilities on why the program may behave like that so I could fix it myself instead of feeling like I'm cheating asking for help in here and get the code solved. But whatever... at this point I'm desperated and can't see the mistake -.-

Thanks!
« Last Edit: November 23, 2014, 11:29:38 am by Zilveztre »

eny

  • Hero Member
  • *****
  • Posts: 1634
Re: Record type file doesn't print integer data properly
« Reply #7 on: November 23, 2014, 02:25:53 pm »
I didn't wanted to put the code in here because it's for an assignment I have in college.
That was already clear because 'files of <Type>' are typical assignment topics :)

Quote
So I just wanted some posibilities on why the program may behave like that so I could fix it myself instead
Writing programs is the easy part.
Debugging is the hard part when results are not as expected.
It's impossible to guess what is causing your particular problem just from a small piece of code (especially if it's a piece of code that is not the actual cause of the problem).
Try to go through your program with the Lazarus debugger and inspect each (lcoal) variable and parameter to see if it contains the value you are expecting.
So you can narrow down to where exactly in the program things go wrong.
In other words: try to find the least number of steps to execute, that produce an erroneous result.

I looked at your program. What seems odd in function buscaNombre: could it be that this function is called with a non-existing value of 'cod'?
So the value of local variable 'nomb' and so the function result is undefined?
It's good to set this value to nil (empty string) at the beginning of the function, so you don't get unexpected results.
Code: [Select]
Function buscaNombre(var arch:tArchCult; cod: integer): string;
Var
   encontre: boolean;
   reg: tCult;
   nomb: string[15];
begin
   nomb := '<missing>';         // <------- Set to a known value (or '')
   encontre:= false;
   seek(arch, 0);
   While (not Eof(arch)) and (not encontre) do
   begin
      Read(arch, reg);
      If reg.codEsp = cod then
      begin
         nomb:= reg.nomb;
         encontre:= True;
      end;
   end;
   buscaNombre:= nomb;
end;

Also insertaReg: I'm guessing you try to insert the new record in an ordered way.
The parameter record regN is never actually inserted; you only move existing records.
I would also recommend splitting this function in 3 seperate steps:
1. Identify the insertion point (a. position 0, b. somewhere in the middle, or c. at the end)
2. Move records backward in case of a. or b.
3. actually insert the new record.

Good luck!
All posts based on: Win10 (Win64); Lazarus 2.0.10 'stable' (x64) unless specified otherwise...

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Record type file doesn't print integer data properly
« Reply #8 on: November 23, 2014, 03:12:57 pm »
A further point is that you use the Seek() function to locate records ordered sequentially in a file of record.
Unless you specify otherwise Seek assumes a record size of 128.
You need to modify all code such as
Code: [Select]
   Assign(arch, ...);
   Reset(arch);
to
Code: [Select]
   Assign(arch, ...);
   Reset(arch, SizeOf(tCult)); // or SizeOf(tSiemCos) as appropriate

Also, if you set critical file-access portions of your code to the {$I-} state you can check for IO errors at the point where they arise using IOResult, rather than just seeing them much later as garbage displayed from incorrect reading/writing of a file.

eny

  • Hero Member
  • *****
  • Posts: 1634
Re: Record type file doesn't print integer data properly
« Reply #9 on: November 23, 2014, 03:26:10 pm »
A further point is that you use the Seek() function to locate records ordered sequentially in a file of record.
Unless you specify otherwise Seek assumes a record size of 128.
IIRC this is done automatically for a file of <type>.
The compiler handles this transparently based on the record type/size.
All posts based on: Win10 (Win64); Lazarus 2.0.10 'stable' (x64) unless specified otherwise...

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11444
  • FPC developer.
Re: Record type file doesn't print integer data properly
« Reply #10 on: November 23, 2014, 03:56:02 pm »
A further point is that you use the Seek() function to locate records ordered sequentially in a file of record.
Unless you specify otherwise Seek assumes a record size of 128.
IIRC this is done automatically for a file of <type>.
The compiler handles this transparently based on the record type/size.

Indeed. Howard's remark is true, but just for standalone"afilevar: file;"

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Record type file doesn't print integer data properly
« Reply #11 on: November 23, 2014, 08:45:00 pm »
@eny and @marcov - thanks for the correction.
I wonder why school assignments push students into using files-of-record and fairly low-level file access routines rather than encouraging them to use a database (or even TIniFile)?

Bart

  • Hero Member
  • *****
  • Posts: 5288
    • Bart en Mariska's Webstek
Re: Record type file doesn't print integer data properly
« Reply #12 on: November 23, 2014, 09:30:46 pm »
I wonder why school assignments push students into using files-of-record and fairly low-level file access routines rather than encouraging them to use a database (or even TIniFile)?

Because they use some basic/stadard pascal,and the objective is to understand the basics of programming (algorithm + datatypes).

Bart

Zilveztre

  • New member
  • *
  • Posts: 7
Re: Record type file doesn't print integer data properly
« Reply #13 on: November 24, 2014, 04:05:06 am »
I wonder why school assignments push students into using files-of-record and fairly low-level file access routines rather than encouraging them to use a database (or even TIniFile)?

Because they use some basic/stadard pascal,and the objective is to understand the basics of programming (algorithm + datatypes).

Bart

That's exactly why, bart. I'll check the advises you all gave me to see if I can fix the problem! Thanks!

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11444
  • FPC developer.
Re: Record type file doesn't print integer data properly
« Reply #14 on: November 24, 2014, 12:44:14 pm »
I wonder why school assignments push students into using files-of-record and fairly low-level file access routines rather than encouraging them to use a database (or even TIniFile)?
Because they use some basic/stadard pascal,and the objective is to understand the basics of programming (algorithm + datatypes).

School also stick to fairly (and often outdated) constructs because they are simpler to teach to the uninitiated. 

 

TinyPortal © 2005-2018