                    第五章   变量控制和流程控制 
 
                    第一节  序言 
  到今天，你应该能自己编写一些简单的 Object 了，通过使用你所在 
的 Mud 的标准的 Object 库。 你应该知道什么是继承了，还有你应该 
能自己写一些函数来表现你自己的 Object 特有的性质了。在这一章， 
你将知道 Lpc 的最基本的一些元素，比如：表达式、操作符等，在你 
自己写的函数通过一些基本元素的组合来操纵变量，通过流程控制来使 
的你的函数更为复杂，而不是线性执行到最后。 
 
                    第二节 变量 
 
2.1 值和变量 
  从根本来说，任意两个 Object 不同的地方有两个方面： 
1) 一些函数不同 
2) 各个变量的值不同 
 
  举个例子，所有的玩家 Object 有完全一样的函数。因此他们不同的 
只是保持的值不同。比如，玩家名字叫做 "falcon" 和 "trill" 不同， 
其最根本的不同的是因为变量 "dbase/id" 这个值不同，一个是"falcon" 
另一个是 "trill" 。 
  因此，在 Mud 中的变化就是各个 Object 中的值的变化。函数是用来 
命名那些可以改变操纵变量的特殊的一些过程。举个例子，函数 create() 
就是这样一个过程：初始化一个 Object 的各个变量的值的一个过程。 
在函数里面，有个特别的东西叫做 指令 用于直接改变操纵变量。 
 
2.2 局部和全局变量 
 
  和大多数的编程语言一样，Lpc 的变量可以被声明成一个函数的局部 
变量，也可以是全局变量(这个全局变量只在一个 Object 内部是全局的， 
对于其他 Object 的函数是不能访问的)。局部变量在一个函数定义内部 
声明，只在这个函数内部使用。别的函数无法得知它的存在。全部变量 
则只要所在的 Object 存在时间内，可以被这个 Obejct 声明的任何函数 
调用，就是它一直在内存中存在。看看下面的两个例子： 
 
----- 
int x; 
 
int GetX() 
{ 
    return x; 
} 
 
void SetX( int y ) 
{ 
    x = y; 
} 
----- 
 
----- 
void SetX( int y ) 
{ 
    int x; 
 
    x = y; 
    write( "x is set to x" + x + " and will now be forgotten.\n" ); 
} 
----- 
 
在第一个例子里面，x 在所有的函数的外部声明，所以它可以被它后面 
的任何函数使用。在这个例子中，x 就是一个全局变量。 
在第二个例子中，x 在函数 SetX() 的内部声明。它只有在函数 SetX() 
被执行时才存在。然后，它就消失了。在这个例子中，x 是局部变量。 
 
2.2 表达式和操作符 
 
  在 Lpc 中表达式和操作符的意义和 C/C++ 的完全一样，如果你在这个 
方面一无所知，那就去找一本 C/C++ 的入门的书。 
  在本章的附录中列出 Lpc 常用的各个操作符的用法，以及 MudOS提供 
的一些特别操作符。 
 
2,3 小结 
  现在你应该知道在不同地方声明一个变量的区别了。我们在上面说的 
全局变量和一般的 C/C++ 中的全局变量的意义不同。一般的，在 C/C++ 
的全局变量在这个程序执行整个过程一直存在，但是 Lpc 的全局变量实 
际是“类变量”，或者说是“Ojbect 变量”，一个 Object 的全局变量， 
在 Object 存在时存在，而没有真正的永远存在的“全局变量”。通过 
对操作符，变量、常量和函数的组合，你能得到一个很复杂的表达式， 
比如： 
    i = ( x = sizeof( users() ) > 0 ) ? 
        x -- : ( ( sizeof( children( NPC ) - 1 ); 
  现在大家应该能知道上面的表达式的值了吧？其中 efun users() 返回 
所有的玩家，children( NPC ) 返回所有 NPC 复制的 Object, sizeof()能 
得知一个 array 或者 mapping 的大小。 
 
                    第三节 流程控制 
 
2.1 流程控制 
  在上一节的例子中： 
 
----- 
void SetX( int y ) 
{ 
    int x; 
 
    x = y; 
    write( "x is set to x" + x + " and will now be forgotten.\n" ); 
} 
----- 
 
  你可能只想在 y > 1 时候把这个值赋予 x。怎么办，那就是流程控制 
的。流程控制，就是控制程序的执行过程。Lpc 和流程控制和 C/C++ 
几乎可以说是完全一样。 
 
2.2 流程控制语句 
  由于 Lpc 的流程控制实际上 C 的一样，我就不再介绍了。在本章的 
附录二中，列出了 Lpc 的流程控制语句。 
  强调一点，switch 可以完全由 if else if else 替代，比如： 
 
    switch ( id ) 
    { 
    case "trill" : 
        write( "你是飞鸟。\n" ); 
        break; 
    case "falcon" : 
        write( "你是狐儿。\n" ); 
        break; 
    case "qyz" : 
        write( "你是小马。\n" ); 
        break; 
    default : 
        write( "你是谁？\n" ); 
        break; 
    } 
 
可以写成这样： 
 
    if ( id == "trill" ) 
    { 
        write( "你是飞鸟。\n" ); 
    } 
    else if ( id == "falcon") 
    { 
        write( "你是狐儿。\n" ); 
    } 
    else if ( id == "qyz" ) 
    { 
        write( "你是小马。\n" ); 
    } 
    else 
    { 
        write("你是谁？\n"); 
    } 
 
  但是 switch 语句更加贴近 CPU 的执行方式，也更自然。所以最好使 
用 switch 语句，而不是 if else if else 的形式。 
 
小结： 
  这一章介绍的实际是 C 的东西，所以如果你对于 C 语言不熟悉的话， 
就找一本入门的书，看看变量，常量和流程控制的介绍。如果你对 C 有 
写了解了，到现在，你应该能很容易的写一些简单的 room, npc 了。 
 
附录一 
Lpc 操作符 
 
  在这一附录，详细说明大部分的 Lpc 操作符。 
 
  Lpc 的操作符大概有下面这些： 
=   +   -   *   /   %   +=  -=  *=  /=  %= 
--  ++  ==  !=  >   <   >=  <=  !   &&  || 
->  ? :     >>  <<  <<= >>= &   |   ^   &= 
|=  ^=  ... 
 
  这些操作符的说明有点枯燥无味，但是最好还是看看，因为有些操作 
符的行为有些怪异。 
 
= 赋值操作符 ( assignment operator ): 
    例子: x = 5; 
    操作值 把等号右边表达式的值赋予左边的变量。等号左边只能是 
            变量，就是说你不能赋予一个表达式值。 
 
+ 加号 ( addition operator ): 
    例子: x + 7 
    操作值：把加号左右的两个表达式的值(如果都是数值)加在一起， 
            得到一个值。如果有一个表达式的值是 string 类型的，一 
            个是 int 或者 float 类型，就直接把 int 和 float 的数值 
            变成相应的字符串，接在 string 的对应的左边或右边。如 
            果两个都是数组，那么就把两个数组和在一起得到一个新的 
            数组。 
 
- 减号 (subtraction operator ): 
    例子: x - 7 
    操作值：这个和 + 刚好现反。 
 
* 乘号 ( multiplication operator ): 
    例子: x * 7 
    操作值：和数学上的乘法没有什么区别。 
 
/ 除法 ( division operator ): 
    例子: x / 7 
    操作值：和数学上的除法没有什么区别。 
 
+= additive assignment operator: 
    例子: x += 5 
    操作值：如果是 a += b，那就就是 a = a + b。 
 
-= subtraction assignment operator 
    例子: x -= 7 
    操作值：如果是 a -= b，那就就是 a = a - b。 
 
*= multiplicative assignment operator 
    例子: x *= 7 
    操作值：如果是 a *= b，那就就是 a = a * b。 
 
/= division assignment operator 
    例子: x /= 7 
    操作值：如果是 a /= b，那就就是 a = a / b。 
 
++ post/pre-increment operators 
    例子: i ++ or ++ i 
    操作值： 
      i ++ 返回的值是 i，然后在把 i 加 1 
      ++ i 返回的值是 i + 1 
 
-- post/pre-decrement operators 
    例子: i-- or --i 
    操作值： 
      i -- 返回的值是 i 
      -- i 返回的值是 i - 1 
 
== equality operator 
!= inequality operator 
＞ greater than operator 
< less than operator 
＞= greater than or equal to operator 
<= less than or equal to operator 
    例子: x == y x != y x > y x < y    x >= y    x <= y 
&& logical and operator 
|| logical or operator 
    例子: x && y      x || y 
! negation operator 
    例子: !x 
-> the call other operator 
    例子: this_player()->GetKeyName() 
    操作值：调用一个 Object 的一个成员函数，左边必须是一个 Object 
            右边是 Object 的一个函数，如果不存在，那么就返回 0。 
    例子：task->event 
    操作值：返回一个 class 类型的变量的中的一个变量 
 
? : conditional operator 
    例子: x ? y : z 
    返回值：如果 x 是为真，那么就返回 y 的值，为假，就返回 z 的值 
 
这些操作符和 C 语言的完全一样。 
 
下面的是高颁布的 MudOS 提供的： 
 
＞> << 
    循环右移和左移 
& | ^ 
    按位做 与 或 异或 
<<= >>= &= |=  ^= 
    如果是 a X= b 那么就是 a = a X b 
这些和 C 的也一样。 
 
... 
    返回一个数组的第一个元素。 
 
 
附录二 
流程控制语句： 
if ( 表达式 ) 
{ 
    指令集 
} 
 
if ( 表达式 ) 
{ 
    指令集 
} 
else 
{ 
    指令集 
} 
 
if( 表达式 ) 
{ 
    指令集 
} 
else if ( 表达式 ) 
{ 
    指令集 
} 
else 
{ 
    指令集 
} 
 
while ( 表达式 ) 
{ 
    指令集 
} 
 
 
switch ( 表达式 ) 
{ 
case ( 表达式 ): 
    指令集; 
    break; 
default: 
    指令集 
} 
 
for( 表达式; 表达式; 表达式 ) 
这些和 C 的完全一样 
 
return 
    结束这次函数的执行 
continue 
    忽略这次循环 
break 
    跳出循环体 
 
高颁布的 MudOS 新提供的： 
 
foreach()循环 
 
foreach ( 变量类型 in 数组 ) 
比如： 
 
void test() 
{ 
    foreach( object player in users() ) 
    { 
        tell_object( player, "hi..just a test." ); 
    } 
} 
users() 这个 efun 返回一个 Object 的数组，所有在线的玩家。 
 
foreach () 循环对数组中的每个元素，做一次循环。

