头衔 小混混
|
ivy | 门派 秋林拾叶 职务 总舵主 人物等级 炉火纯青 江湖威望 +8 江湖阅历 30 门派贡献 1507 实战经验 22561 文章 534 注册 05-01-09 22:36
|
|
|
发表 2007-04-12 17:47:08 人气:626
LPC的函式
4.1 回顾
现在, 你应该了解 LPC 物件由许多处理变数的函式所组成. 函式执行时就处理 变数, 而经由「呼叫」执行这些函式. 在一个档案裡, 函式之间的前后顺序是无关紧要的. 变数在函式裡面被处理, 变数储存在电脑的记忆体中, 而电脑把它们 当作 0 与 1 来处理. 利用定义资料型态这种方法, 这些 0 与 1 被转换成 可使用的输出及输入结果. 字串 (string) 资料型态告诉 driver , 让你看到或你输入的资料应该是许多字元及数字的形式. 整数 (int) 型态的变数对你来说 就是整数值. 状况 (status) 型态对你来说就是 1 或 0. 无 (void) 资料型态 对你或对机器而言都没有值, 并不是用於变数上的资料型态.
4.2 什麼是函式 ?
就像数学函式, LPC 函式获得输入值, 然后传回输出值. 像 Pascal 语言把程序 (procedure) 和函式 (function) 区分开来. 但是 LPC 不这样做, 而知道这种 区分也是有用的. Pascal 称為程序的东西, 在 LPC 就是无传回值 (void) 型 态的函式. 也就是说, 程序或无传回值函式没有传回输出值. Pascal 称為函式 的东西, 就是有传回输出值的. 在 LPC 裡, 最短的正确函式是:
-------
void do_nothing() { }
-----
这个函式不接受输入, 没有任何指令, 也不传回任何值.
要写出正确的 LPC 函式有三个部分:
1) 宣告 (declaration)
2) 定义 (definition)
3) 呼叫 (call)
就像变数一样, 函式也要宣告. 这样一来, 让 driver 知道: 1) 函式输出的资料是什麼型态 2) 有多少个输入的资料以及它们的型态為何. 比较普通的讲法称 这些输入為参数 (parameter).
所以, 宣告一个函式的格式如下:
传回值型态 函式名称 (参数 1, 参数 2, ..., 参数 N);
底下宣告一个 drink_water() 的函式, 它接受一个字串输入, 而输出一个整数:
-----
int drink_water(string str);
-----
str 是输入的变数名称, 会用於函式之中.
函式定义是描述函式实际上如何处理输入值的程式码.
呼叫则是其他函式之中, 呼叫并执行此函式的地方. 对 write_vals() 和 add() 两个函式来说, 你可能会有这些程式码:
-----
/* 首先, 是函式宣告. 它们通常出现在物件码的开头.
*/
void write_vals();
int add(int x, int y);
/* 接著是定义 write_vals() 函式. 我们假设这函式将会在物件以外被呼叫.
*/
void write_vals() {
int x;
/* 现在我们指定 x 為呼叫 add() 的输出值. */
x = add(2, 2);
write(x+"\n");
}
/* 最后, 定义 add() */
int add(int x, int y) {
return (x + y);
}
-----
请记得, 哪一个函式定义在前都没有关係. 这是因為函式并不是由前往后连续执 行的. 函式只有被呼叫时才会执行. 唯一的要求是, 一个函式的宣告必须出现在 函式的定义之前, 而且也必须在任何函式定义呼叫它之前.
4.3 外部函式 (efuns)
也许你已经听过有人提过外部函式. 它们是外部定义的函式. 跟名称一样, 它们 由 mud driver 所定义. 如果你已经撰写 LPC 程式码很久, 你大概已经发现你 听到的一些式子, 像是 this_player(), write(), say(), this_object()... 等等, 看起来很像函式. 这是因為它们是外部函式. 外部函式的价值在於它们比 LPC 函式要快得多, 因為它们早已经以电脑了解的二进位格式存在著.
在前面的 write_vals() 函式裡, 呼叫了两个函式. 第一个是 add() 函式, 是你宣告及定义的函式. 第二个, 则是称做 write() 的外部函式. driver 早就 帮你宣告并定义这个函式. 你只需要呼叫它.
创造外部函式是為了处理普通的、每天都用得到的函式呼叫、处理 internet socket 的输出与输入、其他用 LPC 难以处理的事. 它们是在 game driver 内以 C 写成的, 并与 driver 一起编译在 mud 开始之前, 让它们执行起来快 得多. 但是对你来说, 外部函式呼叫就像对你的函式呼叫一样. 不过, 任何外部 函式还是要知道两件重要的事: 1) 它的传回值是什麼, 2) 它要什麼参数.
外部函式的详细资料, 像是输入参数和传回值, 常常可以在你的 mud 中的 /doc/efun 目录找到. 我没有办法在这裡详细介绍外部函式, 因為每种 driver 的外部函式都不相同. 但是, 你常常可以藉由「man」 或「help」指令 (视 mudlib 而定) 找到详细的资料. 例如指令「man write」会给你 write 外部 函式的详细资料. 如果都不行, 「more /doc/efun/write」也可以.
看过 write 的详细资料之后, 你应该找到 write 是宣告成这样:
-----
void write(string);
-----
这样告诉你, 要正确呼叫 write 不应该期待它有传回值, 而且要传入一个字串型态的参数.
4.4 定义你自己的函式
虽然在档案中, 你的函式次序谁先谁后都没有关係, 但是定义一个函式的程式码 的先后顺序就非常重要. 当一个函式被呼叫时, 函式定义中的程式码按照出现的 先后顺序执行. 先前的 write_vals() 中, 这个指令:
-----
x = add(2, 2);
-----
如果你想看到 write() 使用正确的 x 值, 就必须把它放在 write() 呼叫之前.
当函式要传回一个值时, 由「return」指令之后跟著与函式相同资料型态的值所完成. 在先前的 add() 之中, 指令「return (x+y);」 把 (x+y) 的值传回给 write_vals() 并指定给 x. 在更普通的层次上来说, 「return」停止执行函式 , 并传回程式码执行的结果给呼叫此函式的函式. 另外, 它将跟在它后面任何式子的值传回呼叫的函式. 要停止执行失去控制的无传回值函式, 使用 return; 而后面不用加上任何东西. 请再次记得, 使用「return」传回任何式子的资料型态「必须」与函式本身的资料型态相符合.
4.5 本章总结
定义 LPC 物件的档案是由函式所组成的. 函式依次由三个部分组成:
1) 宣告
2) 定义
3) 呼叫
函式宣告通常出现在档案的最前面, 在任何定义之前. 不过函式只要求在函式定义之前以及任何函式呼叫它之前宣告它.
函式定义可以任何顺序出现在档案裡, 只要它们都放在宣告之后. 另外, 你不可 以再一个函式裡面定义另一个函式.
函式呼叫则出现在其他任何函式中, 任何程式码想执行你的函式的地方. 呼叫也可以出现在自己的函式定义中, 但是这种做法并不建议给新手去做, 因為它很容易变成无穷迴圈.
函式定义依序由底下的部分所组成:
1) 函式传回值型态
2) 函式名称
3) 一个左小括号 ( 接著列出参数再加上一个右小括号 )
4) 一个左大括号 { 指示 driver 从这裡开始执行
5) 宣告只用在这个函式中的任何变数
6) 指令、式子、视需要呼叫其他函式
7) 一个右大括号 } 描述函式码在此结束. 对於无传回值函式来说, 如果 在此还没有碰到「return」指令 (只适用於无传回值函式) , 会如同有 碰到「return」指令一样回到原来呼叫的函式执行.
最短的函式是:
-----
void do_nothing() {}
-----
因為这个函式不接受任何输入, 不做任何事, 也不传回任何输出.
任何无传回值型态以外的函式「必须」传回一个与函式资料型态相同的值.
每一种 driver 都有一套早已经帮你定义好的函式, 它们叫做外部函式. 你不需 要宣告或定义它们, 因為它们早已经帮你做好这些事. 更深入一点, 执行这些函 式比起执行你的函式要快得多, 因為外部函式是 driver 的一部份. 再者, 每一 个 mudlib 都有特殊函式像是外部函式一样, 早已经為你宣告并定义好. 但是不 同的是, 它们用 LPC 定义在 mudlib 裡面. 它们叫做模拟外部函式 (simul_efuns, 或 simulated efuns). 在大多数的 mud 裡, 你可以在 /doc/efun 目录底下找到关於它们的详细资料. 另外, 很多 mud 有称作 「man 」或「help」的命令, 让你可以方便地叫出这些资料档案.
程式风格的註解:
有些 driver 可能不会要求你宣告函式, 有些不会要求你指定函式的传回值型态. 无论如何, 底下有两个理由劝你不要省略以上这些动作:
1) 对其他人来说 (还有你自己过了一段时间之后) , 会比较容易读懂你的 程式码并了解程式码的意义. 这对除错时特别有用, 有很多错误 (除了放错地方的各种括号) 发生在资料型态上 (有没有碰过「Bad arg 1 to foo() line 32」? (程式第三十二行, 呼叫 foo() 时的第二个参数有错) ).
2) 大家认為这样子写程式是个好习惯.
|
相关帖子 | |
LPC教学手册 (ivy,5457,2007-04-12 17:41:06) | LPC基本简介 (ivy,869,2007-04-12 17:43:36) | LPC的资料型态 (ivy,538,2007-04-12 17:45:51) | LPC的函式 (ivy,626,2007-04-12 17:47:08) | LPC的基础继承 (ivy,454,2007-04-12 17:48:56) | LPC的变数处理 (ivy,382,2007-04-12 17:49:51) | LPC的流程控制 (ivy,482,2007-04-12 17:52:24) | LPC的物件资料型态 (ivy,586,2007-04-12 17:53:16) | 好复杂啊。。。。 (gfdsa1,361,2007-05-20 04:00:57) |
|
|