Solomone Solomone - 4 months ago 19
Pascal Question

Variable or constant expression required , Pascal

constant vs variable

Hi, im currently working with files. Its File of Char that is declared globally. Im trying to find any letter (A,b, etc.) in the file of char and i know there is only one character in each line and i want to change it to dot. (Variable TECKA - DOT)
When i want to write char, it says "Constant expression expected", but when i change it to constant (code in comment section), it says "Variable required". What am i doing wrong here?
Thanks for reply.

procedure TForm1.Button3Click(Sender: TObject);
var znak,tecka:char;
begin
tecka:='.';
assignfile(f,'Znaky.dat');
reset(f);
While not eof(f) do begin
read(f,znak);
Case znak of 'a'..'z','A'..'Z':
seek(f,filepos(f)-1);
Write(f,tecka); // write(f,'.');
end;
end;
closefile(f);
end;

Answer

What you're doing wrong has nothing to do with the line write(f,tecka);, but everything to do with block rules in pascal.

If you want to compiler to stop complaining you need to change the case statement to:

case znak of 
  'a'..'z','A'..'Z': begin
    seek(f,filepos(f)-1);
    write(f,tecka);
  end;
end; {case}

The problem is that the case statement expects one or more constant expressions (e.g. 'a'..'z') after the of. After a : you can only put a single statement or a begin end block. Because you're putting 2 statements after the : Pascal wants to interpret the second statement as another case clause (e.g.: '0'..'9':) which it isn't.

If you want to put multiple statements in a section you must always use a begin-end block.

This is also a gotcha in if-statements:

if x then 
  statement1;
  statement2;  <-- statement2 will always be executed, because it's not part of the if  

This should be:

if x then begin
  statement1;
  statement2;     <-- statement2 depends on x.
end;

It's for this reason that many people always use begin-end blocks.
Even if there is a single statement.
If you change code later you just put your extra statements in the begin-end block that's already there and you can't forget to put it in.

Note that the assignfile-reset-seek etc calls are quite outdated.
In Delphi it's more efficient to use a stringlist to do your processing.

procedure TForm1.Button3Click(Sender: TObject);
var 
  MyText: TStringList;
  i,a: integer;
  znak,tecka:char;
const
  Alpha = 'a'..'z','A'..'Z';
  Filename = 'Znaky.dat';
begin
  tecka:='.';
  MyText:= TStringlits.create;
  MyText.LoadFromFile(Filename);
  //loop though all lines.
  for i:= 0 to MyText.Lines.Count-1 do begin
    //loop though every char in a line (string chars start counting from 1 !)
    for a:= 1 to Length(MyText.Lines[i]) do begin
      case MyText.Lines[i][a] of 
        Alpha: begin
          MyText.Lines[i][a]:= tecka;
        end;
      end; {case} 
    end; {for}
  end; {for}
  MyText.WriteToFile(Filename);
end;

This is more performant because you only do disk IO twice instead of many times.

Personal nitpick: please don't capitalize keywords like case and while, this is Pascal, not VB.

Comments