Как вызвать процедуру, когда внутри другой процедуры в Pascal

procedure questiontype;  
 begin  
  writeln ('Enter the type of question you would like...');  
  writeln ('1. Add');  
  writeln ('2. Multiply');  
  writeln ('3. Subtraction');  
  writeln ('4. Division');  
  readln (typeofquestion);  
   case typeofquestion of
    1: add;
    2: multiply;
    3: subraction;
    4: division   
else writeln ('Choose again'); 
end;
end;          

сложение, умножение, вычитание и деление-это все процедуры. Если я помещу это в основную программу, она будет работать нормально, но когда я сделаю это как процедуру, я получу ошибку необъявленный идентификатор. Я смотрел на многих сайтах, например вот такой, но я не могу найти.

Как сделать сложение, умножение, вычитание, деление перейти к их процедурам изнутри этого?

3 ответов


вы должны объявить процедуры до процедуры, называть их. Хотя вы не показали, как определяются другие процедуры, я делаю вывод, что они объявляются после процедуры, которую вы показали.

таким образом, вы можете просто переупорядочить свой код, чтобы добавить, умножить, вычитание и деление определялись перед процедурой, которая их вызывает.

Так что это будет работать:

procedure add;
begin
  //do something;
end;

procedure questiontype;  
begin  
  add;  
end;

но это не будет компилироваться:

procedure questiontype;  
begin  
  add;  
end;

procedure add;
begin
  //do something;
end;

Pascal и его варианты компилируются за один проход, и если компилятор не знает о подпрограмме в точке, в которой она упоминается, она не может продолжаться.

Pascal поддерживает подпрограммы, в которых a вызывает B и B вызывает A, с помощью a *forward declaration`. Например:

procedure B; forward;

procedure A;
begin
  B;
end;

procedure B;
begin
  A;
end;

естественно, это бесконечный цикл, как написано, который завершится переполнением стека (как уместно!) но есть, конечно, реальные примеры, когда это необходимо.

, прямые объявления редко необходимы, и их следует избегать, если это возможно, поскольку они усложняют работу. Неизменно решение можно найти, просто переупорядочив ваши объявления.

в качестве окончательного в сторону, ограничение порядка, которое происходит перед использованием, явно упоминается в известной статье Брайана Кернигана,почему Паскаль не мой любимый язык программирования.


я вижу, вы пометили свой вопрос [delphi] а также [pascal], поэтому я думаю, что вы на самом деле пишете код Delphi. Тогда у вас есть еще несколько вариантов, помимо заботы о порядке процедур и forward директива обсуждается Дэвидом.

чаще всего a Delphi проект (GUI или консоль) делится на"единицы". Типичная единица выглядит так:

unit MyUnit;

interface

const
  RANDOM_NUMBER = 17;

var
  PrintExtraNiceMessage: boolean;

procedure DoThis;
procedure DoThat;

implementation

const
  BUFFER_SIZE = 256;

procedure InitSomething;
begin
  // TODO: do some internal work...
end;

procedure DoThis;
begin
  // TODO: do something
end;

procedure DoThat;
begin
  // TODO: do something else
end;

вы заметите, что блок разделен на две части:interface часть, и implementation часть. The interface часть содержит только объявления (функций, процедур, типов, констант и переменных); функции и процедуры, объявленные здесь, определены (то есть реализованы) в . Обратите внимание, что могут быть функции и процедуры, определенные в implementation раздел, который не имеет деклараций в .

грандиозная идея заключается в том, что содержание interface раздел виден всем другим блокам в вашей программе, тогда как содержание implementation раздел виден только внутри этого самого блока. Таким образом, любой другой блок в вашей программе может использовать RANDOM_NUMBER константа,PrintExtraNiceMessage переменная и две процедуры DoThis и DoThat. Но вы можете использовать только InitFunction в этом блоке (например, внутри DoThis или DoThat). Кроме того, константа BUFFER_SIZE также не видно за пределами этого самого устройства.

это очень элегантный подход. The описывается эта единица используется в других единицах (например, какие функции есть и как они используются), и детали реализации скрыты в .

преимущество этого подхода заключается в том, что он решает вашу проблему, по крайней мере, возможно. если the add, multiply, subtract и divide процедуры должны быть видны другим единицам, затем они должны быть объявлены в . Но тогда они действительно известны компилятору, когда дело доходит до ваш questiontype процедура, и поэтому вы можете использовать их, даже если они определены (реализованы) ниже questiontype процедура внутри . Но, с другой стороны, если нет никакого смысла позволять другим единицам использовать эти процедуры, то они не должны быть объявлены в interface раздел, и вам нужно сделать, как предлагает Дэвид. Это также применимо, если у вас нет нормальных единиц в вашем проекте, то есть если у вас есть только program файл, который не имеет разделения на interface и implementation запасные части.


обратите внимание, что пример OP имеет еще, который применяется только к последнему "если". Предположительно, если они вводят 1, 2 или 3, соответствующая процедура срабатывает, возвращается, а затем они видят "выбрать снова". Если они входят в 4, они этого не делают. Этому хорошо послужило бы дело или каскадное "если"..иначе, если структура, где окончательное еще срабатывает только "когда все остальное терпит неудачу", что похоже на то, что предназначалось OP.