vast 发表于 2009-2-18 11:25:37

LPC 程式基本能力测验及答案(转载)

中级 LPC 程式基本能力测验

本试题共有 25 大题,每大题 4 分,测验时间为 24 小时,准许翻阅任何资料,询问他人
,无论任意方式达成作答目的者均被允许,但切忌不知所云的胡乱复制不相关的程式作答
,或是随便剪下一段参考资料内容贴上来作答,违者该题不予计分。此试题并不牵涉于「
效率」、「进阶流程控制」以及「演算法」的考虑和设计阶段,仅测验对于 MudOS 所提供


之 LPC 语言的熟练度和相关知识,以及与 LPC 相关的一些 MudOS 本身之动作和行为,另
外,可能会测验一些程式写作上被要求的一些基本习惯。

此试题适合系统架构者(system architect - arch)之中级以上之巫师作答,满分 100 分,
及格分数为 60 分。
--------------------------------------------------------------------------------
1. (1) LPC 中的条件叙述结果为非零值时代表的意义为何? (1%)
(2) 如何取出一个字串中第 2 到第 7 个字之间的字串(含第 2 及第 7 个字元)? (1%)
(3) 观察以下程式码:

      mapping m;

      void create()

      {
          m["id"] = 10;
      }

    试问此程式码何处有误?应如何修改? (1%)
(4) 如果不希望物件中某个全域变数被 save_object 这个 efun 所储存,该如
    何宣告变数? (1%)
--------------------------------------------------------------------------------
2. [题组] LPC 提供物件储存资料内容的功能,则:
(1) 试列出 LPC 支援之资料型别名称。 (1%)
(2) 哪些资料型别可被 MudOS 内建之 efun 所储存? (1%)
(3) 哪些资料型别无法被 MudOS 内建之 efun 所储存? (1%)
(4) 承上题,试说明这些资料型别无法被储存之可能原因。 (1%)
--------------------------------------------------------------------------------
3. [题组] LPC 之函示呼叫提供 call by reference 的方式,试问:
(1) 哪些资料型态在呼叫时预设为 call by reference? (1%)
(2) 如何使这些资料型别之变数在传递时模拟 call by value? (1%)
(3) 自动 call by reference 之变数在其所呼叫的目的函式中,有可能经由
    assignment operator 消除其 reference 的关系,试举出一个例子。 (1%)
(4) 试撰写一个 swap_value 函式,以 call by reference 的方式交换传入之两
    引数内容值,该函式传回型别为 void。 (1%)
--------------------------------------------------------------------------------

4. MudOS 为物件为基本元素所组成之系统,试问:
(1) load_object 与 new 这两个 efun 所传回之物件有何不同? (1%)
(2) 物件名称是否一定与程式档案名称有关?试说明原因。 (1%)
(3) 当一个物件 A 被 shadow 到物件 B,且两者均有一名称为 func 之函式时,
    在何种情况下仍能使用 call_other 方式呼叫 B 中被遮蔽之函式? (1%)
(4) 一个物件中的程式码如果将自己摧毁,是否会立即停止程式执行?有什么该
    注意的地方? (1%)
--------------------------------------------------------------------------------
5. [题组] LPC 中支援 function pointer 的资料型别,试问
(1) 每个 function pointer 指向一个函式后,会自动被指定一个 owner,请问
    该如何强制变更其 owner? (1%)
(2) 试利用上题的方式,于物件 A 中撰写一段程式码,以 fetch_variable 这个
    efun 取得物件 B 中的全域变数内容值。 (1%)
(3) function pointer 的操作可以使用 (: func(ob, $1) :) 的语法来指定执行
    此 function pointer 时的引数传递方式,试说明 $1 的作用。 (1%)
(4) 承上题,如果 ob 为 local variable,会因为程式执行离开其有效范围后消
    失,因此 MudOS compiler 会在编译时段产生错误讯息,试修改上题之语法
    使其能够正常运作。 (1%)
(5) 一个 function pointer 的 owner 被摧毁后,执行此 function pointer 将
    会发生执行期错误,试问该如何避免此错误发生?
--------------------------------------------------------------------------------
6. [题组] LPC 提供物件继承的功能,试问:

(1) 假设 A 继承 B,两者中均有同名函式 func 时,A 该如何呼叫 B 中的 func?
    (1%)
(2) 承上题,如果希望 B 中函式 func,不能被继承 B 的物件所覆盖,或是不希望
    被其他物件以 shadow 覆盖,应如何宣告此函式? (1%)
(3) 试说明修饰字 private 及 protected 在继承上的影响性。 (1%)
(4) 若 A 继承 B,且 A 继承 C,但 B 与 C 并无继承关系,仅同时被 A 所继承,
    如果 C 中有一 private function 名称为 func,该如何于 B 中撰写程式码以
    呼叫 C 中的 func? (1%)
--------------------------------------------------------------------------------
7. MudOS 中提供了一些 driver apply functions,试问:
(1) 哪个 interactive apply function 负责处理使用者的一般性输入? (1%)
(2) 哪个 master apply function 负责处理使用者由外面连线进入时,使该连线
    与某个物件连结使其成为 interactive object? (1%)
(3) 哪些 valid_ 系列的 master apply function 在不定义时自动视为允许? (1%)
(4) 哪个 interactive apply function 负责处理由 message 这个 efun 所传送
    之讯息? (1%)
--------------------------------------------------------------------------------
8. MudOS 中有一防止程式掉入无穷回圈,而有一个 evaluation cost 值,其值在每
次 LPC 程式执行到结束期间,每执行一个指令码就会减一,每次执行结束后将被
重设为最大值,当其归零时发生一个 Too long evaluation 的错误以终止程式执
行,然而有些时候需要执行指令量特别高的程式,请写出三种于这种特殊情形下
仍能使此种程式正常运作的方式。 (4%)

--------------------------------------------------------------------------------
9. LPC 中对 type 3 grammar 以 regular expression 的方式支援,其中 regexp
这个 efun 提供字串及字串阵列的比对搜寻,而 sscanf 中也支援它以便于辅助
拆解一个字串,试回答下列问题:
(1) 试用 regexp 撰写一段程式码,于一个字串阵列中取出小写 t 开头的所有
    elements。 (2%)
(2) 试用 sscanf 配合 regular expression 消除一字串开头的空白。 (2%)
--------------------------------------------------------------------------------
10. MudOS 中有一部份是提供编译 LPC 程式码,将物件载入记忆体及释放的功能,
试问:
(1) MudOS 编译 LPC 程式码的时机为何? (1%)
(2) 一个物件的程式档案开头有一行 #pragma save_binary 对于物件载入的动
    作有何影响? (1%)
(3) 当一个物件被载入后,其非复制物件(即广义上物件名称无 # 号的物件)称
    为原始物件,其在记忆体中占有资料区块和程式区块,复制物件则无程式
    区块,程式部分参考著原始物件的程式区块。请问当原始物件被摧毁并重
    新被载入后,原先的复制物件使用的是新的程式区块还是旧的程式区块?
    (1%)
(4) 试写一段程式码,摧毁一个原始物件以及其所有的复制物件。 (1%)
--------------------------------------------------------------------------------
11. [题组] LPC 中的 present efun 提供寻找物件的功能,试问:
(1) 使用 present 在许多物件中寻找一个物件时,会逐一呼叫每个物件中的那

    个 apply function? (1%)
(2) 承上题,如果这些物件中有三个物件符合搜寻条件,那么该如何取得第二
    个相符的物件? (1%)
(3) 请用一些文字叙述假设一些物件的环境,并撰写一些程式码,说明 present
    的动作。 (1%)
--------------------------------------------------------------------------------
12. [题组] MudOS 提供了各种错误的处理和记录功能,试问:
(1) 哪个 master apply function 在 compilation error 发生时会自动被呼叫?
    (1%)
(2) 哪个 master apply function 在 runtime error 发生时会自动被呼叫? (1%)
(3) 承上题,当此 apply function 在执行时也发生错误时,MudOS 会如何处理?
    (1%)
(4) 承上题,当 runtime error 发生时,如果该 error 发生于 catch 区块中,
    此 apply function 是否仍会被呼叫? (1%)
--------------------------------------------------------------------------------
13. MudOS 会遵循一些设定而周期性的呼叫一些物件的 apply functions,请列出这些
apply functions,并说明如何使其开始被 MudOS 周期性呼叫,以及停止方式(没有
的请注明无)。 (4%)
--------------------------------------------------------------------------------
14. MudOS 所创造出来的世界之基本元素为物件,而这些物件在被产生、消灭及彼此间
的互相关系上也有许多支援,试问:
(1) 一个物件被创造出来时,哪个 function 会被 MudOS 自动呼叫? (1%)

(2) 一个物件被摧毁时,被摧毁的物件上有什么 function 会被 MudOS 自动呼叫?
    (1%)
(3) 一个物件的 environment object 被摧毁时,该物件身上哪个 function 会自
    动被 MudOS 呼叫? (1%)
(4) 如果希望 /obj 路径下的所有物件档案均不能被载入,且物件中任一行程式码均
    没有机会被执行,应该如何作此限制? (1%)
--------------------------------------------------------------------------------
15. MudOS 的世界里物件与物件之间,有著空间上的相对关系,试问:
(1) 如果玩家物件 A 为某一房间物件的内容物(即 A 位于此房间中),应该透过什么
    efun 取得此房间物件? (1%)
(2) 如果玩家物件 A 的内容物里有许多道具(即 A 身上有许多道具),我们该透过什
    么 efun 一次取得这些道具的集合(即物件阵列)? (1%)
(3) 试用一些文字叙述假设几个物件环境,以及一些程式码,来说明如何移动一个物
    件。 (1%)
(4) 当一个物件被移动到一个物件中之后,该物件是否还能 shadow 到另一个物件身
    上? (1%)
--------------------------------------------------------------------------------
16. 试以目前所学的技术,设计一个物件程式码,其中有全域变数 basic_data、abilities
以及 magics,其型态均为 mapping,建立一些资料,并以 save_object 储存其内容至
一个档案。并设计一个指定变数回存的功能,也就是撰写一个函式,传入变数名称,该
变数之值即会被回存至上次存档时的内容。 (4%)
---------------------------------------------------------------------------------

17. 试撰写一个简易 mudlib 的几个基本物件程式码,使这个 mudlib 能够提供基本连线,
在连线成功后,可用 edit <filename> 的指令格式编辑档案,以 update <filename>
来将 filename 所产生的原始物件摧毁,并重新载入,以 quit 指令离线,并且能使用
shutdown 指令关闭 mud (请记得标明档名,以及这些档案在 runtime configuration
file 中的定义)。 (4%)
--------------------------------------------------------------------------------
18. 目前有一个函式,其传入值代表整数型态,代表输入模式,并以 switch case 述句来
判断其值,以执行相关程式码,其值为 1 时代表进行单行输入,为 2 时代表多行输入
,为 3 时代表不处理输入(即拦截),其它情形则发生错误,此函式内容如下:

    void start_input(int mode)
    {
      switch(mode) {
          case 1:
            // some codes for single line input...
            return;
          case 2:
            // some codes for multi line input...
            return;
          case 3:
            return;
          default:

            error("No handler for this input mode.\n");
      }
    }

很明显的此程式码可读性不佳,尤其在使用上,呼叫部分使用 start_input(1)、
start_input(2)等等的方式容易使人无法立即理解,且容易误传其它无效的值进
入,试修改及增加一些程式码,使其更容易阅读,且在使用上较不容易传入无意
义值。 (4%)
--------------------------------------------------------------------------------
19. 有一未经缩排处理的程式码如下:

void do_something()
{
int a, b, c, d, e, f, g, h;

if(!a) a = 10;
b = 5;
if(b)
if(!c)
c = 3;
else
b = 10;

else
b = 20;
h = 16;
for(d=0;d<5;d++)
for(e=0;e<5;e++)
f = 100;
g += f;
}

试将此程式码作正确的缩排处理,使其层次正确以便于区分 if、else、for 述句之
影响范围。 (4%)
--------------------------------------------------------------------------------
20. [题组] LPC 的 function pointer 提供指向 anonymous function 的功能,则:
(1) 试撰写一段程式码,将一个 function pointer 变数指向一个 anonymous
      function,该 anonymous function 接受 2 个整数值输入,回传结果为两传
      入变数之和 (2%)
(2) 将此 function pointer 的 owner 设定给 this_player()。 (1%)
(3) 最后再撰写一行执行此 function pointer 的范例程式码。 (1%)
--------------------------------------------------------------------------------
21. [题组] LPC 中的 0 分为两种,一种是常数零值 (constant zero),一种是未定义之
      常数零值(constant zero & undefined),试问:
(1) LPC 中的变数,分别在什么情况下会有这两种不同的 0 值? (1%)

(2) 我们该如何测试该变数目前是哪种 0 值? (1%)
(3) 此二种 0 值在 if、while 等条件述句中代表的意义为何? (1%)
(4) 试撰写一个程式码,使一个已被指定值的 mapping 变数值,回到未定义之常数
    零值。 (1%)
--------------------------------------------------------------------------------
22. 假设我们有一个房间物件,其中有一个整数 status 储存著房间的状态旗号,我们假设
status 最右边的位元(第一位元)被设定为 1 时,无法使用战斗指令。第二位元则是灯
光开关的状态,1 为点亮,0 为关闭,当我们每次按下开关时,0 与 1 会相互切换
,请设计以下几个函式:

    战斗限制部分: (2%)
      set_flag - 用来将 status 的某个位元设定为 1
      clear_flag - 用来将 status 的某个位元设定为 0
   
    灯光部分: (2%)
      inverse_flag - 用来将 status 的某个位元由 1 转为 0,或由 0 转为 1
      push_button - 按下灯光开关时会被呼叫
--------------------------------------------------------------------------------
23. (1) 请按照以下规格及功能要求设计出 simul_efun:
      prototype: mixed *keys(mapping m);
      当 m 为 0 值时不发生错误,传回空阵列。 (2%)
(2) 设法防止 efun::keys(m); 在 simulated external function object 之外的地

    方被执行成功。 (2%)
--------------------------------------------------------------------------------
24. LPC 提供了对于 socket 的支援,试依照下列要求撰写 LPC 程式码:
(1) 建立一个 LPC 物件,并监听 port 60000,有连线产生即接受其连线,当使用者
    传送讯息为「quit」时,中断此名使用者的连线,当讯息为「shutdown」时,与
    此使用者终止连线,并停止监听 port 60000。 (2%)
(2) 承上题,试撰写另一物件,使其能藉由呼叫前一物件之函式,取得正在监听 port
    60000 之 socket 所有权,并能持续提供相同的连线与指令处理功能。 (2%)
--------------------------------------------------------------------------------
25. LPC 提供 virtual object 的支援,带给许多便利性,如大规模的制造房间,构成整
块大陆,可由此功能完成,请作答以下问题:
(1) 试列出并撰写相关函式,以产生任一物件名称为「/domain/test/17,15」之
    virtual object,此物件并不需具备任何功能,请记得标明哪个函式属于哪
    些物件程式档案里。 (2%)
(2) 承上题,在此物件中宣告一字串变数,并指定其值后以 save_object 存入资料
    档中,试设计一简单的自动读取程式,使此物件下次被 load_object 载入完毕
    并被传回后,该字串变数已经回复到上次储存的状态。 (2%)
—————————————————————————————

[ 本帖最后由 vast 于 2009-2-18 11:28 AM 编辑 ]

vast 发表于 2009-2-18 11:29:29

答案

1. (1) 代表 true
    [初级 LPC: 运算式 - 条件运算式]
(2) str
    [初级 LPC: 字串变数基本操作 - 子字串操作]
(3) 此 mapping 变数尚未指定初值即被使用,会造成执行期错误。
    解决方式可用 mapping m = ([]); 指定以指定初值,或是:


      void create()
      {
          if(!m) m = ([ "id" : 10, ]);
          else m["id"] = 10;
      }
    [初级 LPC: 变数操作 - 变数初始化]
    [初级 LPC: 基本除错 - 可见错误讯息之执行期错误]
(4) 使用 nosave 修饰字,早期 MudOS 提供的修饰字是 static。
    [初级 LPC: 修饰字 - 变数修饰字]
    [中级 LPC: 物件属性 - 储存与读取]

注: Mon Oct 28 17:14:29 EST 1996 所诞生之 v22.1a8 (时间在 v22pre11 之前,
    然而 v22pre 与 v22.1a 为不同步更新,无以下所提及之选项)于 options.h
    中新增了 SENSIBLE_MODIFIERS 的选项,如果 #define 此选项,则不可储存之
    变数修饰字由 static 改为 nosave,范围受保护之变数或函式修饰字由 static
    变更为 protected。

2. (1) status, int, float, string, buffer, object, mapping, function, class,
    mixed, array (包含前面各形式的 array,#define ARRAY_RESERVED_WORD 所编
    译出来的 MudOS 提供 array 关键字,与 mixed * 同义)
    [初级 LPC: LPC 基本资料型态]
(2) int, float, string, mapping, class 及其所组成之 array,mixed 为此
    类型态时亦可。
    [中级 LPC: 物件属性 - 可储存类型与不可储存类型]
(3) buffer、object 和 function。另外 mixed 存放的是可储存以外型态的型
    态,则无法储存,如不可储存型态之 array,此外,mixed array 中有无
    法储存之型态者,或 mapping 中的 key/value 含有其型态时,该位置在
    储存时将被留空,下次读入时被设为常数零且未定义之值(称为 undefined
    zero)。
    [中级 LPC: 物件属性 - 可储存类型与不可储存类型]
(4) buffer 不可储存之原因主要为 MudOS 本身为 C 程式语言所撰写,而它在于
    save_object/restore_object 上使用标准 C 字串,即字元阵列方式处理档
    案内容,如 buffer 资料中含有 NULL 值,则会造成读取错误,故不得储存。

    object 为一物件指标,指标类型的资料型态通常在物件摧毁后会被自动设定
    为 undefined zero,当 MudOS shutdown 时物件即被摧毁,并没有储存的必
    要,事实上在 MudOS 设计层面而言,它只是临时参考一个物件区块的位址,
    记忆体位址在每次使用时并不可能一样,因此不能够储存。即使硬是设计成
    可储存,如果该物件为复制物件,LPC 是不容许指定载入一复制物件的。
    (此部分重点是 object 为「指标」型态,储存无意义。)
   
    同 object 之叙述部分,function 型态事实上亦是参考一位址,没有储存的
    意义。
    [中级 LPC: driver 原理之观察与推断]
   
注: Sat Dec 11 21:43:08 CST 1993 所诞生之 v0.9.18.21 中于 options.h 增加
    之 DISALLOW_BUFFER_TYPE 在被定义时,所产生出来的 MudOS 并无 buffer
    型态,此外 Fri Mar 24 20:59:08 EST 1995 所诞生之 v21.2a6 及 v21.1b7
    将 DISALLOW_BUFFER_TYPE 改名为 NO_BUFFER_TYPE。

    Thu Oct 6 19:22:48 EDT 1994 时的 v20.13 中移除了 status 资料型态,可
    藉由在 options.h 中 #define HAS_STATUS_TYPE 启用。

3. (1) mapping 和 class
    [初级 LPC: 函式呼叫 - 隐含传参呼叫(implicit call by reference)]
(2) 以 copy() 这个 efun 复制一份资料后再传入,如 foo(copy(map_value));

    其中 foo 为呼叫的函式, map_value 为一 mapping 变数。
    [初级 LPC: 变数操作 - 变数参考关系的消除]
(3) void push_data(mapping info)
    {
      info = ([ "test" : 0 ]);
    }
    当 assignment operator 左边为传入值的本身(即 info ),则互相参考关系
    消灭。若左边为 info["xxxx"] 这类子值,则参考关系不变,因此内容值亦
    会一起改变。
    [初级 LPC: 变数操作 - 变数参考关系的消除]
(4) void swap_value(int ref a, int ref b)
    {
      int c;
      
      c = a;
      a = b;
      b = c;
    }
    [初级 LPC: 函式 - call by reference]

注: Thu Aug 3 20:25:27 EDT 1995 所诞生的 v21.6b3 中的 copy() 即支援
    class 型态,Mon Dec 5 12:14:46 EST 1994 时出产的 v20.23 即支援

    了此 efun。欲使用此 efun 必须在 options 中 #define PACKAGE_CONTRIB
    ,此选项预设为启用。

    Mon Oct 28 17:14:29 EST 1996 的 v22.1a8 中增加了 call by reference
    功能,当 options.h 中的 REF_RESERVED_WORD 被 #define 后,即可使用
    此关键字,Wed Mar 4 04:57:16 EST 1998 的 v22.2a25 及 v22.2b21 中
    如果在 options.h 里 #define COMPAT_32,则 ref 可用 & 符号代替。如
    应考者使用 v22.1a8 之前的版本(v22pre11 及其以下亦符合)。

4. (1) load_object() 传回的为原始物件,new() 传回的则为复制物件。在最常见
    的情形下,原始物件用 clonep() 测试会传回 0,复制物件为 1,然而当原
    始物件为虚拟物件时,clonep() 有可能会传回 1,此处必须注意。
    [初级 LPC: LPC OOP 理论 - 原始物件与复制物件]
(2) 不一定有关,虚拟物件可以由载入或复制该物件的函式命名物件名称。
    [初级 LPC: LPC OOP 理论 - 物件名称与虚拟物件]
(3) 在 A 物件程式码中使用 B->func() 即可呼叫到原本 B 中的函式 func。
    [初级 LPC: LPC OOP 理论 - 物件投影]
(4) 不会停止执行,此时物件中的资料区块已被摧毁,如果再继续使用的话会发
    生执行期错误,因此最好在摧毁后直接 return 出去。
    [初级 LPC: LPC OOP 理论 - 摧毁物件]


5. (1) 使用 bind 这个 efun 变换。
    [初级 LPC: 变数操作 - 函式指标]
(2) evaluate(bind((: fetch_variable("var_name") :), B));
    [初级 LPC: 变数操作 - 函式指标]
(3) $1 代表执行此函式指标时,传入的第一个引数会送到此位置。
    如: evaluate((: find_object($1) :), "/obj/user");
    [初级 LPC: LPC 运算式与述句 - 函式指标]
(4) local variable 要使用 $() 包住,以便在离开有效范围后保留其内容值,
    答案为 (: func($(ob), $1) :)
    [初级 LPC: LPC 运算式与述句 - 函式指标]
(5) 使用 if(functionp(f) & FP_OWNER_DESTED) 来测试即可。
    [初级 LPC: 变数操作 - 函式指标]

6. (1) 使用 scope resolution operator 来呼叫,即在 A 中使用 ::func() 呼叫。
    [初级 LPC: 物件继承 - 覆写物件方法]
(2) 在宣告行前端加上 nomask 修饰字,如 nomask void func()
    [初级 LPC: 物件继承 - 覆写物件方法]
    [初级 LPC: LPC 修饰字]
(3) private 修饰字修饰的函式,仅在物件本身内部才能被呼叫,当此物件被继承
    时,于继承树同一层的平行物件,可经由宣告 prototype 呼叫。经由 protected
    修饰过的函式
    [初级 LPC: LPC 修饰字]

    [初级 LPC: 物件继承 - LPC 继承阶层概念]
(4) 只需要在 B 中宣告该函式即可,如
      private void func();
    [初级 LPC: LPC 修饰字]
    [初级 LPC: 物件继承 - LPC 继承阶层概念]

7. (1) process_input
    [中级 LPC: driver applies]
(2) connect
    [中级 LPC: driver applies]
(3) valid_object
    [中级 LPC: driver applies]
(4) receive_message
    [中级 LPC: driver applies]

8. (1) 执行该段程式之前用 set_eval_limit() 改变 evaluation cost 的起始值。
(2) 此种程式多为回圈,可于每次回圈开头加上 reset_eval_cost()。
(3) 使用 call_out() 延迟法分段跳开。
[初级 LPC: 基本除错 - 可见错误讯息之执行期错误]

9. (1) regexp(str_array, "^t");
    [中级 LPC: regular expression]

(2) sscanf(str, "%*( *)%s", str);
    [中级 LPC: regular expression]

10. (1) 当一个物件的原始物件不存在时,遇到 load_object(), find_object(file, 1),
    new(), clone_object(), call_other() 的时候。
    [初级 LPC: LPC OOP 理论 - 物件的载入与程式码的编译]
(2) MudOS 中每个物件程式码被编译后会产生一中间码,save_binary 主要是储存这些
    码在 runtime configuration file 指定的 binary 目录中,如果在载入物件时其
    对应的 binary 档案存在,MudOS 将不编译该物件之原始程式码档案,而直接读取
    其 binary 档案载入物件。
    [初级 LPC: LPC OOP 理论 - 物件的载入与程式码的编译]
    [初级 LPC: LPC 前置处理器 - #pragma 编译器选项 - save_binary]
(3) 原先的复制物件依然使用旧的程式区块。
    [初级 LPC: LPC OOP 理论 - 原始物件与复制物件]
(4) foreach(object ob in children("/obj/test")) destruct(ob);
    [初级 LPC: LPC OOP 理论 - 原始物件与复制物件]
    [中级 LPC: 常见 efun 的使用]

11. (1) 呼叫物件身上的 id()。
    [中级 LPC: driver applies]
(2) present("obj_id 2", env_ob);
    [初级 LPC: LPC OOP 理论 - 空间概念]

    [中级 LPC: 常见 efun 的使用]
    [中级 LPC: driver applies]
(3) 假设物件 PPL_A 存在于一个环境物件 ROOM_A 之中,他的身上带有 OBJ_A 及
    OBJ_B,而 PPL_A 的 inventory list 中的顺位是 OBJ_A 在 OBJ_B 之前,且
    PPL_A 中有一段程式码:
      int id(string str) { if(str == "guard") return 1; else return 0; }
    而 OBJ_A 中有一段程式码:
      int id(string str) { if(str == "sword") return 1; else return 0; }
    至于 OBJ_B 中有一段与 OBJ_A 完全相同的程式码:
      int id(string str) { if(str == "sword") return 1; else return 0; }
    则 present("sword", PPL_A); 可以取得 OBJ_A,present("guard", ROOM_A);
    可取得 PPL_A,于 PPL_A 物件程式码中撰写 present("sword") 可得到 OBJ_A,
    于 ROOM_A 物件程式码中撰写 present("guard") 可得到 PPL_A。
   
    要取得 OBJ_B 则可使用 present("sword 2", PPL_A);
    [初级 LPC: LPC OOP 理论 - 空间概念]
    [中级 LPC: 常见 efun 的使用]
    [中级 LPC: driver applies]

12. (1) log_error
    [中级 LPC: driver applies]
    [中级 LPC: LPC 错误处理机制]

(2) error_handler
    [中级 LPC: driver applies]
    [中级 LPC: LPC 错误处理机制]
(3) MudOS 会略过 error_handler() 的呼叫,自行将内定错误讯息写入 runtime
    configuration file 中指定的 debug log file 中,同时将错误讯息输出至
    stderr。
    [中级 LPC: LPC 错误处理机制]
(4) error_handler 仍会被呼叫,但是第二个参数会接收到 1,以作为区别。
    [中级 LPC: driver applies]
    [中级 LPC: LPC 错误处理机制]
13. MudOS 会遵循一些设定而周期性的呼叫一些物件的 apply functions,请列出这些
apply functions,并说明如何使其开始被 MudOS 周期性呼叫,以及停止方式(没有
的请注明无)。 (4%)
reset,cleanup,swap**?
--------------------------------------------------------------------------------
14. MudOS 所创造出来的世界之基本元素为物件,而这些物件在被产生、消灭及彼此间
的互相关系上也有许多支援,试问:
(1) 一个物件被创造出来时,哪个 function 会被 MudOS 自动呼叫? (1%)
create
(2) 一个物件被摧毁时,被摧毁的物件上有什么 function 会被 MudOS 自动呼叫?
(1%)
destruct?remove? 模糊的问题...
(3) 一个物件的 environment object 被摧毁时,该物件身上哪个 function 会自
动被 MudOS 呼叫? (1%)
move_or_destruct??? 或者 destruct_env_of???
(4) 如果希望 /obj 路径下的所有物件档案均不能被载入,且物件中任一行程式码均
没有机会被执行,应该如何作此限制? (1%)
rm -rf /obj,嘿嘿,要不就限制所有相关 efun.好像前面的问题里面提到过
compile_object update_file 限制?
--------------------------------------------------------------------------------
15. MudOS 的世界里物件与物件之间,有著空间上的相对关系,试问:
(1) 如果玩家物件 A 为某一房间物件的内容物(即 A 位于此房间中),应该透过什么
efun 取得此房间物件? (1%)
environment(A)??? 这些属于增加不少问题难度级别
(2) 如果玩家物件 A 的内容物里有许多道具(即 A 身上有许多道具),我们该透过什
么 efun 一次取得这些道具的集合(即物件阵列)? (1%)
all_inventory(A)???
(3) 试用一些文字叙述假设几个物件环境,以及一些程式码,来说明如何移动一个物
件。 (1%)
是想问move_object还是move呢??
(4) 当一个物件被移动到一个物件中之后,该物件是否还能 shadow 到另一个物件身
上? (1%)
shadow没用过,,,这个不会哦。。。
--------------------------------------------------------------------------------
16. 试以目前所学的技术,设计一个物件程式码,其中有全域变数 basic_data、abilities
以及 magics,其型态均为 mapping,建立一些资料,并以 save_object 储存其内容至
一个档案。并设计一个指定变数回存的功能,也就是撰写一个函式,传入变数名称,该
变数之值即会被回存至上次存档时的内容。 (4%)
回存? restore??晕哦。。。
去copy save.c 就可以咯。。。。
还有restore.c
---------------------------------------------------------------------------------
17. 试撰写一个简易 mudlib 的几个基本物件程式码,使这个 mudlib 能够提供基本连线,
在连线成功后,可用 edit <filename> 的指令格式编辑档案,以 update <filename>
来将 filename 所产生的原始物件摧毁,并重新载入,以 quit 指令离线,并且能使用
shutdown 指令关闭 mud (请记得标明档名,以及这些档案在 runtime configuration
file 中的定义)。 (4%)
记得以前有个mowang版本的mini mudlib,去搞一个...
--------------------------------------------------------------------------------
18. 目前有一个函式,其传入值代表整数型态,代表输入模式,并以 switch case 述句来
判断其值,以执行相关程式码,其值为 1 时代表进行单行输入,为 2 时代表多行输入
,为 3 时代表不处理输入(即拦截),其它情形则发生错误,此函式内容如下:
void start_input(int mode)
{
    switch(mode) {
      case 1:
      // some codes for single line input...
      return;
      case 2:
      // some codes for multi line input...
      return;
      case 3:
      return;
      default:
      error("No handler for this input mode.\n");
    }
}
很明显的此程式码可读性不佳,尤其在使用上,呼叫部分使用 start_input(1)、
start_input(2)等等的方式容易使人无法立即理解,且容易误传其它无效的值进
入,试修改及增加一些程式码,使其更容易阅读,且在使用上较不容易传入无意
义值。 (4%)
不懂,,难道是考多态么??那就分别写三个咯...
--------------------------------------------------------------------------------
19. 有一未经缩排处理的程式码如下:
void do_something()
{
int a, b, c, d, e, f, g, h;
if(!a) a = 10;
b = 5;
if(b)
if(!c)
c = 3;
else
b = 10;
else
b = 20;
h = 16;
for(d=0;d<5;d++)
for(e=0;e<5;e++)
f = 100;
g += f;
}
试将此程式码作正确的缩排处理,使其层次正确以便于区分 if、else、for 述句之
影响范围。 (4%)
有**啊。。。不过这个题真的可以用来考非软件从业人员....
--------------------------------------------------------------------------------
20. [题组] LPC 的 function pointer 提供指向 anonymous function 的功能,则:
(1) 试撰写一段程式码,将一个 function pointer 变数指向一个 anonymous
    function,该 anonymous function 接受 2 个整数值输入,回传结果为两传
    入变数之和 (2%)
见3
(2) 将此 function pointer 的 owner 设定给 this_player()。 (1%)
是考bind么?
见3
(3) 最后再撰写一行执行此 function pointer 的范例程式码。 (1%)
这三个估计可以考倒不少人,嘿嘿
evaluate( bind((: $1 + $2 :), me), 1, 2)
--------------------------------------------------------------------------------
21. [题组] LPC 中的 0 分为两种,一种是常数零值 (constant zero),一种是未定义之
    常数零值(constant zero & undefined),试问:
(1) LPC 中的变数,分别在什么情况下会有这两种不同的 0 值? (1%)
0+2 ------ return 0,false 然后 notify_fail 是这个意思么?还是别的???
别的就不明白了,或者是指 null??????
(2) 我们该如何测试该变数目前是哪种 0 值? (1%)
intp??
(3) 此二种 0 值在 if、while 等条件述句中代表的意义为何? (1%)
flase??
(4) 试撰写一个程式码,使一个已被指定值的 mapping 变数值,回到未定义之常数
零值。 (1%)
mapping m;
m 就是说的这个 0 吧?
用 0 swap value? 别的方法暂时没想到...
--------------------------------------------------------------------------------
22. 假设我们有一个房间物件,其中有一个整数 status 储存著房间的状态旗号,我们假设
status 最右边的位元(第一位元)被设定为 1 时,无法使用战斗指令。第二位元则是灯
光开关的状态,1 为点亮,0 为关闭,当我们每次按下开关时,0 与 1 会相互切换
,请设计以下几个函式:
战斗限制部分: (2%)
    set_flag - 用来将 status 的某个位元设定为 1
&oxfff之类的??
    clear_flag - 用来将 status 的某个位元设定为 0

灯光部分: (2%)
    inverse_flag - 用来将 status 的某个位元由 1 转为 0,或由 0 转为 1
    push_button - 按下灯光开关时会被呼叫
--------------------------------------------------------------------------------
23. (1) 请按照以下规格及功能要求设计出 simul_efun:
    prototype: mixed *keys(mapping m);
    当 m 为 0 值时不发生错误,传回空阵列。 (2%)
if (!mapp(m)) m=([])?????
(2) 设法防止 efun::keys(m); 在 simulated external function object 之外的地
方被执行成功。 (2%)
valid_override 限制?
--------------------------------------------------------------------------------
24. LPC 提供了对于 socket 的支援,试依照下列要求撰写 LPC 程式码:
(1) 建立一个 LPC 物件,并监听 port 60000,有连线产生即接受其连线,当使用者
传送讯息为「quit」时,中断此名使用者的连线,当讯息为「shutdown」时,与
此使用者终止连线,并停止监听 port 60000。 (2%)
去copy ftpd.c就可以了
(2) 承上题,试撰写另一物件,使其能藉由呼叫前一物件之函式,取得正在监听 port
60000 之 socket 所有权,并能持续提供相同的连线与指令处理功能。 (2%)
又是bind??或者传说中的shadow? 那个shadow不会用,没接触过....
--------------------------------------------------------------------------------
25. LPC 提供 virtual object 的支援,带给许多便利性,如大规模的制造房间,构成整
块大陆,可由此功能完成,请作答以下问题:
(1) 试列出并撰写相关函式,以产生任一物件名称为「/domain/test/17,15」之
virtual object,此物件并不需具备任何功能,请记得标明哪个函式属于哪
些物件程式档案里。 (2%)
virtual object 也没用过
(2) 承上题,在此物件中宣告一字串变数,并指定其值后以 save_object 存入资料
档中,试设计一简单的自动读取程式,使此物件下次被 load_object 载入完毕
并被传回后,该字串变数已经回复到上次储存的状态。 (2%)
18题是希望你将参数定义一些对应的宏或者直接使用字符串做参数
19题是最有意义的题目,任何人写的代码都不可能一步到位,你总有需要修改以前写的代码的时候(改BUG或者加新功能),良好的排版格式能够使阅读代码更轻松,如果再配上良好的注释的话就更好了
代码除了拿来运行,还需要别人维护,编写代码的时候使用良好的排版和注释能够极大降低维护成本
排版和注释是最基本的要求
—————————————————————————————

becool 发表于 2009-2-18 11:29:36

zeze
不过没答案啊

vast 发表于 2009-2-18 11:30:54

有答案,呵呵

becool 发表于 2009-2-18 11:39:38

哦,是我瞎了。。。ttk_27

pkuxkx 发表于 2009-2-18 11:44:33

答案在哪里?答案在vast心里

picewolf 发表于 2009-2-18 15:58:44

1分。。yeah!!

zgbl 发表于 2009-2-21 01:26:46

靠,看不懂。。。编程学的还是太少。。。
话说前天转图书馆貌似是看见过有lpc的书

vast 发表于 2009-2-21 08:58:49

看不懂的主要原因可能是这个文章里面的术语一口台湾腔吧:lol:

picewolf 发表于 2009-2-21 09:09:26

确实有这个原因在。。。
页: [1] 2
查看完整版本: LPC 程式基本能力测验及答案(转载)