QBasic/子程序和函数
子程序和函数是将代码分解成可重复使用的“块”的方法。它们允许程序员通过调用适当的过程或函数来重复使用一组常见的指令。
例如,假设你需要打印多个值表。一种方法是直接在需要它们的地方输入所有表打印命令。但是,这不仅会使程序非常大,还会使调试或更改表的“样式”更加困难。更简单的方法是创建一个“打印表”过程,并在其中输入所有打印命令。然后,每次需要打印表时,只需使用要打印的值列表“调用”“打印表”过程即可。
过程执行某项操作,不向程序员返回任何内容。例如,过程可以用于设置屏幕模式和调色板。
函数执行某项操作并返回一个值。例如,如果需要找到两个值的平均值,可以编写一个函数,该函数接受两个数字并返回平均值。
GOTO 和 GOSUB 语句是创建子程序的最初方法。它们在较旧的 Basic 实现中最为常见,并出于兼容性原因保留下来;但是,在其他编程语言或大型项目中不建议使用它们,因为 GOTO 使跟踪程序流程变得更加困难,并且 GOSUB 不会“隔离”对任何变量的更改。
这两个命令依赖于标签,标签有两种形式。第一种也是较旧的形式是在每行开头写入行号(通常以 10 为增量)。较新的方法与其他编程语言类似,即一个单词后跟一个冒号。
GOTO 语句很简单;它只是将执行点移动到给定的标签。
GOSUB 语句将控制权转移到给定的标签,但是当遇到 RETURN 语句时,执行将返回到 GOSUB 语句后面的行。对 GOSUB 中进行的任何更改都将是对“主”代码中使用的实际变量的更改。
ON ERROR 允许你为程序定义错误处理程序;当发生错误时,它立即跳转到给定的标签。当程序到达 RESUME 语句时,控制权返回,RESUME 语句可以将控制权返回到同一位置、下一条语句或任何其他所需的标签。
在 Qbasic 中,错误处理程序不能位于任何子程序中。因此,任何错误检查或标志都必须通过使用与主模块共享的变量来处理。
注意:如果你的错误处理例程中没有“resume”语句(即你尝试使用 gotos 完成所有操作),错误处理只会起作用一次 - 下一个“on error”将被忽略,程序将结束,就像你没有“on error”语句一样。这个问题似乎在任何文档中都没有提到。我花了三个小时才弄清楚为什么两个几乎相同的程序部分的行为如此不同。
声明子程序的更好方法是使用 SUB 语句块,因为(默认情况下)在退出时将丢弃子程序中使用的任何新变量。
在 QBasic IDE 中,这样做会将 SUB 块移动到它自己的窗口中,以防止意外删除模块,并允许更容易地组织程序代码。
调用子程序就像编写子程序的名称(传递任何必需的参数)一样简单。如果你愿意,可以使用 CALL 语句来指示其他程序员它是一个子程序。
SUB name (params)
{SHARED variables 'if any}
'{code to execute}
' ...
' ...
{STATIC variables 'if any, to be saved for use next time}
END SUB
虽然传递给子程序的参数是按“引用”传递的(即它们在 SUB 中采用新的名称),但对值进行的任何更改都将“反映回”原始值。默认情况下,在到达 END SUB 时(或执行 EXIT SUB 时)将丢弃 SUB 中使用的所有其他变量,除了以下情况:-
要“保留”SUB 中使用的变量的值以在下次调用时重新使用,请在末尾使用 STATIC 关键字。
如果需要访问变量(没有作为参数传递),请使用 SHARED 关键字在子程序开始时定义每个变量(共享变量保留其名称)。
函数是返回值的子程序形式。定义子程序中适用的所有内容也适用于函数。在函数中,返回值是通过将函数名用作变量来创建的 - 当到达有效的退出或结束调用时,返回值将传递给调用表达式。有两种方法可以从函数返回,一种方法是到达 END FUNCTION 语句,另一种方法是调用 EXIT FUNCTION。END FUNCTION 和 EXIT FUNCTION 之间的区别在于,只能有一个 END FUNCTION,它必须出现在函数的所有其他代码之后,因为它表示代码块的结束。EXIT FUNCTION 可以多次出现,可以放置在任何认为合适的地方。
FUNCTION name (params)
' Shared variable declarations
name = result
' ...
END FUNCTION
函数的声明方式与变量相同 - 它返回定义为返回的变量类型,与定义变量包含其指定类型的方式相同。默认情况下,它是一个数字,但附加一个美元符号表示它返回一个字符串。
函数只能在表达式中调用;与子程序不同,它们不是独立的语句。