【问题标题】:How do I Invoke a procedure when inside another procedure in Pascal如何在 Pascal 中的另一个过程中调用一个过程
【发布时间】:2011-07-18 19:26:12
【问题描述】:
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;          

加、乘、减、除都是过程。如果我把它放在主程序中,它会正常工作,但是当我把它作为一个过程本身时,我得到错误未声明的标识符。我在很多网站上都看过这样的例子,但我找不到。

如何使加法、乘法、减法、除法从这个内部进入它们的程序?

【问题讨论】:

  • 您不是转到一个过程,而是调用调用一个过程。区别可能看起来很肤浅,但 Delphi 有一个您不想使用的 goto 关键字。你甚至还不想了解它。
  • @Cosmin, @David:纯 Pascal 中没有 case 语句吗?
  • @Andreas Pascal 的 case 语句与 Delphi 相同
  • @Cosmin goto 在 Pascal 中可能很有用,因为它没有异常
  • @Cosmin 我感觉原来的 Pascal 没有 break 或 exit ,这使得 goto 更引人注目!但我不会对那个断言束手无策。

标签: delphi pascal procedure


【解决方案1】:

您必须在调用它们的例程之前声明过程。虽然您没有展示其他例程是如何定义的,但我推断它们是在您展示的例程之后声明的。

因此您可以简单地重新排序您的代码,以便在调用它们的过程之前定义加法、乘法、减法和除法。

所以这会起作用:

procedure add;
begin
  //do something;
end;

procedure questiontype;  
begin  
  add;  
end;

但这不会编译:

procedure questiontype;  
begin  
  add;  
end;

procedure add;
begin
  //do something;
end;

Pascal 及其变体在单遍中编译,如果编译器在提到它时不知道例程,它就无法继续。

Pascal 通过使用 *forward 声明支持 A 调用 B 和 B 调用 A 的协同例程。例如:

procedure B; forward;

procedure A;
begin
  B;
end;

procedure B;
begin
  A;
end;

当然,这是一个无限循环,它将以堆栈溢出终止(多么合适!),但当然也有真实的例子证明这是必要的。

但是,很少需要前向声明,应尽可能避免,因为它们会增加复杂性。总是可以通过简单地重新排序您的声明来找到解决方案。

最后,声明在使用之前发生的排序约束在 Brian Kernighan 的著名文章 Why Pascal is Not My Favorite Programming Language 中明确提到。

【讨论】:

  • @David,最近几天你投了多少票?明显比平时多?在我看来,这就像一场流行病。自从我开设 SO 帐户以来,我总共收到了 8 次反对票,其中 4 次是在过去 4 天内。我的数字在统计上无关紧要,它们太小了。
  • 我的猜测是,downvoter 只阅读了问题的第一个标签,即[delphi],并注意到您对interface 部分只字未提。或者,也许投反对票的人只是心情不好。尽管如此,IMO,你永远不应该在不发表评论的情况下投反对票。
  • @Cosmin:几周前,有人(显然)否决了我上周左右给出的每个答案。
  • @Cosmin 最近几天不少。具有讽刺意味的是,投票者只是在剥夺自己的代表权!
  • @Andreas,我时不时地在不离开 cmets 的情况下投反对票,原因有二:受到冒犯的用户以更多反对票的形式进行报复(这发生在我身上两次),而且有时问题是形式太糟糕了,有无人参与的澄清请求或我觉得评论是浪费时间的事情,但你仍然可以通过投票来做出贡献,以便有一天自动删除这些质量差的问题。
【解决方案2】:

我看到你已经标记了你的问题[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 变量以及DoThisDoThat 这两个过程。但是你只能在这个单元中使用InitFunction(例如,insideDoThisDoThat)。此外,常量BUFFER_SIZE 在这个单元之外也是不可见的。

这是一种非常优雅的方法。 interface 部分描述了该单元如何在其他单元中使用(例如,有哪些功能以及如何使用它们),实现细节在 implementation 部分中“隐藏”。

这种方法的一个好处是它至少可以解决您的问题。 如果addmultiplysubtractdivide 过程应该对其他单元可见,那么它们应该在interface 部分中声明。但是,当涉及到您的questiontype 过程时,编译器确实知道它们,因此即使它们在questiontype 部分内的questiontype 过程下方定义(实现),您也可以使用调用它们。但是,另一方面,如果让其他单位使用这些程序完全没有意义,那么它们不应该在interface 部分中声明,您需要按照 David 的建议进行操作。这也适用于您的项目中根本没有正常单位的情况,也就是说,如果您只有 program 文件,该文件没有分为 interfaceimplementation 部分。

【讨论】:

  • 次要的一点,我不主张OP用forward解决问题。
【解决方案3】:

请注意,OP 的示例有一个仅适用于最后一个“if”的 else。据推测,如果他们输入 1、2 或 3,相应的过程会触发、返回,然后他们会看到“再次选择”。如果他们输入 4,他们不会。这将由 Case 或级联 if..else if 结构很好地服务,其中最后的 else 仅在“当所有其他方法都失败时”触发,这就像 OP 的意图一样。

【讨论】:

  • 是的,这是他 OP 代码中的一个错误。他应该真的在此处使用case 声明(或了解更多关于ifelse 的工作原理)。
  • 请在你的回答中说明这两种方法。
  • 这很尴尬。我现在已经放入了一个案例声明,它工作正常。谢谢。
猜你喜欢
  • 2017-05-23
  • 2012-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多