Search code examples
loopscompiler-errorspascalgoto

How I can fix this error? Pascal


PROGRAM RandomNumber;
Var rand,count,guess : integer;
LABEL correct, loop, wrong, end1;
begin
{Initialization, so that random numbers are drawn}
 Randomize;
  count :=0;
  repeat
      loop:
      count := count+1;
{Random(i) Creates random numbers between 0 and i.}
      rand := Random(10);
      guess := Random(10);
      if rand=guess
      then
          goto correct
      else
          goto wrong;
  until count > 10;
  goto end1;
  correct :
      WriteLn('Correct');
      goto end1;
  wrong :
      WriteLn('False Guess');
      goto loop;
  end1 :
      WriteLn;
end.

The goal of the program is to find a random number in 10 tries. I managed to compile it with Free Pascal IDE and the problem then is that the program does not stop until the number is found. However, when I tried to compile it with an online compile it gives this error:

prog.pas: In main program:

prog.pas:26: error: `goto' to invalid target

Is it because labels/goto can`t jump right away in loops?


Solution

  • The proximate "why does't it work?!" answer is exactly as lamas shaikh says: A missing semicolon.

    Don't feel bad. It's an easy thing to miss. Pascal allows either a single line of code after after a conditional or loop structure, or a begin/end sequence as a virtual statement. That choice interacts badly with Pascal's use of semicolons as statement separators rather than terminators (a fine distinction to parser designers but one that over the years has proven subtle and error-prone, especially for those new to the language. Beware both missing and extra semicolons!

    Two things that can help: Always, always, always use strong, consistent, disciplined indentation to help show you the logical structure of the code. And you may find it easier to just always use begin/end blocks in any context that either a statement or a multi-statement block might fit (even if the block contains contains a single line). That may seem goofy at first, but as you start adding statements to programs (including temporary debugging print statements), working with a single construct that works in all cases really helps.

    The less immediate reason that your program fails isn't the semicolon. It's that you're using a completely unstructured approach to control flow in your program. You're GOTOing all over the place, even when you don't need to, and even though there are simpler, cleaner, better structured alternatives. For example, consider:

    PROGRAM RandomNumber;
    Var rand, count, guess, MaxGuesses : integer;
    
    begin
        {Initialization, so that random numbers are drawn}
        Randomize;
        MaxGuesses := 10;
        count := 0;
        repeat
            count := count + 1;
            {Random(i) Creates random numbers between 0 and i.}
            rand  := Random(10);
            guess := Random(10);
            if rand = guess
            then begin
                WriteLn('Correct');
                break
            end
            else
                WriteLn('False Guess');
        until count >= MaxGuesses;
        WriteLn;
        if (rand = guess)
        then
            WriteLn('We had a winner (', guess, ') in ', count, ' tries.')
        else
            WriteLn('Sorry! No winner in ', MaxGuesses, ' tries.');
        WriteLn;
    end.
    

    Compiled and run a few times, it looks like:

    $ ./guess
    False Guess
    Correct
    
    We had a winner (1) in 2 tries.
    
    $ ./guess
    False Guess
    False Guess
    False Guess
    False Guess
    False Guess
    False Guess
    False Guess
    False Guess
    False Guess
    False Guess
    
    Sorry! No winner in 10 tries.
    
    $ ./guess
    False Guess
    Correct
    
    We had a winner (8) in 2 tries.
    

    Pascal was part and parcel of the revolution in programming in the 1960s and 1970s that brought "structured programming" into widespread use. Don't use lower-level goto-laden code when better structures are so eagerly available.