背景:
阅读文章

LPC 程式基本能力测验

[日期:2008-12-25] 来源:  作者: [字体: ]

1. (1) 代表 true
    [初级 LPC: 运算式 - 条件运算式]
  (2) str[1..6]
    [初级 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或者加新功能),良好的排版格式能够使阅读代码更轻松,如果再配上良好的注释的话就更好了
代码除了拿来运行,还需要别人维护,编写代码的时候使用良好的排版和注释能够极大降低维护成本
排版和注释是最基本的要求
收藏 推荐 打印 | 录入:sbso | 阅读:
相关内容      
本文评论   [发表评论]   全部评论 (0)
内容推送
52mud提供
一起回忆泥巴游戏QQ群68186072
52mud官方微信公众平台
热门评论