Search code examples
pascal

Pascal read command


I built a program in pascal using FPC but after this I installed lazarus. So now I'm editing this same pascal program in Lazarus. It works very well to insert, modify and list: name, surname and telephone in a array of record of this type. But the read command is not working for me in this modify procedure. But the read command works well on my Delete procedure for example.

Main problem: **These 3 read command did not work so I modified to readln which fixed it for me and now each one reads my inputs but only with readln, but not with read. **

But why ?

    gotoxy(24,8);
    read(modificar_nome);
    gotoxy(24,9);
    read(modificar_sobrenome);
    gotoxy(24,10);
    read(modificar_telefone); 

Complete Procedure

//---------------------------------------
// MODIFICAR escolha
//---------------------------------------
procedure modificar_pessoa(var pessoa: type_pessoas);
var i,achou: integer;
var buscar_pessoa, modificar_nome, modificar_sobrenome, modificar_telefone: string;

begin

  clrscr;
  writeln('****************************************************************************************');
  writeln('* Modificar pessoa                                                                     *');
  writeln('****************************************************************************************');
  writeln('* Nome:                                                                                *');
  writeln('****************************************************************************************');
  gotoxy(9,4); readln(buscar_pessoa);
  
  for i:=0 to length(pessoa)-1 do
  begin
    if (pessoa[i].primeiro_nome = buscar_pessoa) then
    begin
      achou := 1;
      break;
    end;
  end;

  if achou = 1 then
  begin
    writeln('****************************************************************************************');
    writeln('* Preencher so o que deseja modificar (ou ENTER para ignorar):                         *');
    writeln('****************************************************************************************');
    writeln('* Novo Primeiro Nome?                                                                  *');
    writeln('* Novo Sobrenome?                                                                      *');
    writeln('* Novo Telefone?                                                                       *');
    writeln('****************************************************************************************');
    gotoxy(24,8);
    read(modificar_nome); // not waiting for my input ???????????
    gotoxy(24,9);
    read(modificar_sobrenome);
    gotoxy(24,10);
    read(modificar_telefone);

    if modificar_nome <> '' then
      pessoa[i].primeiro_nome := modificar_nome;

    if modificar_sobrenome <> '' then
      pessoa[i].ultimo_nome := modificar_sobrenome;

    if modificar_telefone <> '' then
      pessoa[i].telefone := modificar_telefone;

    gotoxy(1,13);
    writeln;
    writeln('Pessoa ''', buscar_pessoa, ''' modificada com sucesso!');
  end
  else
    begin
      gotoxy(1,13);
      writeln;
      writeln('ERRO: Pessoa ''', buscar_pessoa, ''' não foi localizada!');
    end;

  writeln;
  writeln('Pressione qualquer tecla para retornar ao menu...'); ReadAnyKey;

end;

Funny is this other procedure to delete (exclude) people, the read command works fine and waits for my input

//---------------------------------------
// EXCLUIR escolha
//---------------------------------------
procedure excluir_pessoa(var pessoa: type_pessoas);
var i,achou: integer;
var del_pessoa: string;

begin

  clrscr;
  writeln('****************************************************************************************');
  writeln('* Excluir pessoa                                                                       *');
  writeln('****************************************************************************************');
  writeln('* Nome:                                                                                *');
  writeln('****************************************************************************************');

  gotoxy(9,4); read(del_pessoa);

  for i:=0 to length(pessoa)-1 do
  begin
    if (pessoa[i].primeiro_nome = del_pessoa) then
    begin
      achou := 1;
      pessoa[i].primeiro_nome := '';
      pessoa[i].ultimo_nome   := '';
      pessoa[i].telefone      := '';
      break;
    end;
  end;

  gotoxy(1,6);
  if achou = 1 then
    writeln('Pessoa ''', del_pessoa, ''' excluida com sucesso!')
  else
    writeln('ERRO: Pessoa ''', del_pessoa, ''' nao foi localizada!');

  writeln;
  writeln('Pressione qualquer tecla para retornar ao menu...'); ReadAnyKey;

end;         



Solution

  • I think that the short answer to this is that your observation is correct and that the reason is that Read is working as designed. Once FPC's runtime has executed the firstRead it behaves as if it has seen an Eol after what the user typed, and therefore the second and subsequent calls to Read return immediately without waiting for any further user input.

    The reason it behaves this was seems to be historical. FPC was based on the Object Pascal of the commercial RAD system Delphi, and although the two have diverged somewhat over the years (e.g. in their different implementations of generics), FPC faithfully reproduces many of the basic details of the Object Pascal language and runtime, including its file handling, of which keyboard input is a special case.

    I think that it is legitimate. therefore, to look at the Delphi/Object Pasval documentation of Read. In the online help of Delphi 7, which dates from 20 years ago, the section on Read includes

    Description

    The Read procedure can be used in Delphi code in the following ways.

    For typed files, it reads a file component into a variable. For text files, it reads one or more values into one or more variables.

    With a type string variable:

    Read reads all characters up to, but not including, the next end-of-line marker or until Eof(F) becomes true; it does not skip to the next line after reading. If the resulting string is longer than the maximum length of the string variable, it is truncated. After the first Read, each subsequent Read sees the end-of-line marker and returns a zero-length string.

    Use multiple Readln calls to read successive string values.[emphasis added]

    So, the Delphi OLH documents exactly the behaviour you are seeing (that the second and subsequent calls to Read return immediately without gathering any user input) and describes the remedy, which is to use Readln instead. And that's why you see the same behaviour + remedy in FPC.