Как вызвать процедуру, когда внутри другой процедуры в Паскале - PullRequest
6 голосов
/ 19 марта 2011
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 ]

14 голосов
/ 19 марта 2011

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

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

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

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, посредствомиспользование * предварительной декларации`.Например:

procedure B; forward;

procedure A;
begin
  B;
end;

procedure B;
begin
  A;
end;

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

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

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

6 голосов
/ 19 марта 2011

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

Чаще всего проект 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. Часть interface содержит только объявления (функций, процедур, типов, констант и переменных); объявленные здесь функции и процедуры определены (то есть реализованы) в разделе implementation. Обратите внимание, что в разделе implementation могут быть определены функции и процедуры, которые не имеют объявлений в разделе interface.

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

Это очень элегантный подход. В разделе interface описано, как этот модуль используется в других модулях (например, какие функции существуют и как они используются), а подробности реализации «скрыты» в разделе implementation.

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

2 голосов
/ 19 марта 2011

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

...