LPC 语言基础教程:6.4 字符串操作及常用外部函数

本文节选自《LPC语言基础教程:从零学习游戏开发》,版权归@mudren,欢迎转载,但必须注明来源(mud.ren)。

LPC 语言中的字符串在第二章数据类型中已经做了讲解,这里做个回顾,并补充相关外部函数的使用。

字符串赋值

字符串赋值直接使用以下方法:

string s = "字符串...";

在LPC中赋值时还支持换行这种奇怪的操作,如:

write("
美人卷珠帘,
深坐颦蛾眉。
但见泪痕湿,
不知心恨谁。
");

内行格式会原样输出,具体可以参考示例 2.1.5.c,不过这种用法非主流,C语言下这样用会报错的,个人不推荐使用。如果需要保持字符串内容原样输出,推荐使用 定界符格式,这是很多编程语言都支持的一种格式。以下是使用示例6.4.1.c

// 示例:6.4.1
int main(object me, string arg)
{
    string qr = @EOF
█████████████████████████████████████
█████████████████████████████████████
████ ▄▄▄▄▄ █▀█ █▄▄▄▀ ██▄ █ ▄▄▄▄▄ ████
████ █   █ █▀▀▀█ ▀ ▀█▀▄ ▄█ █   █ ████
████ █▄▄▄█ █▀ █▀▀ ▀▀ ▀▀▄▀█ █▄▄▄█ ████
████▄▄▄▄▄▄▄█▄▀ ▀▄█ █▄█▄█ █▄▄▄▄▄▄▄████
████▄ ▄  █▄  ▄▀▄▀▄ █▀ █ ▀ ▀ ▀▄█▄▀████
████▀█▀▄█▀▄▀██▄█▀██  █ ▀ ▀▄▄ ▀█▀█████
████▀▀▀▄▄▀▄▄ ▄▄█▄▄ ▄ ▄▄ ▀▀▀▀▀▄▄█▀████
████▀▄  ▄ ▄█ █▄ ▄█▄▄██ ▀▄▄▄▀█▄▄▀█████
████ ▄▀▄▄▀▄▀ ▀▀▄ ▄▄▄▄ ▄▀▀█▀█▀▄ █▀████
████ █▄█▄ ▄▀▄█▀▀ █▀ ██▄▀▀ ██▀█▄▀█████
████▄█▄▄▄█▄█ ▀ ▄  ▄█▀▄▄▄ ▄▄▄ ▀   ████
████ ▄▄▄▄▄ █▄█▄█▀██▄▀▄█▄ █▄█ ▄▄▀▀████
████ █   █ █ ▄ ▀▀ ▄▄ ▄▄▀▄▄▄ ▄▀ ▀ ████
████ █▄▄▄█ █ █▄▀ █▄  ██▀  ▄   ▄ █████
████▄▄▄▄▄▄▄█▄▄▄██▄█▄▄▄▄▄████▄▄▄██████
█████████████████████████████████████
█████████████████████████████████████
            支付宝扫码打赏
EOF;
    printf("%s\n", qr);
    return 1;
}

LPC 语言中 定界符格式 要求以 @ + 标志字符开始,以顶格标志字符结束,如以上 EOF,可以换成任何字符串,只要前后一致,且结束的标志字符前面没有任何内容。

@marker
<... text block ...>
marker

字符串合并

字符串合并使用 + 运算符,如果要合并的二个字符串都不是字符串变量,+ 都可以直接省略。如:

write(HIR "字符串输出" NOR);

以上示例中 HIRNOR 都是 ansi.h 中的宏定义,都是字符串常量,和字符串合并时无需 +

请注意以下内容输出本质上也是多个字符串合并,输出样式和前面换行的不同,这种用法在C语言中也支持,大家应该就陌生:

write(
"美人卷珠帘,"
"深坐颦蛾眉。"
"但见泪痕湿,"
"不知心恨谁。"
);

字符串与字符

在C语言中字符串是字符数组,在LPC语言中没有字符型变量,但也可以类似字符数组的方式取字符串中的字符,str[n]返回的是字符的码位(code point),数据为int型,如:“abcde”[0]返回97,即为字符'a'

C语言规定,在每一个字符串常量的结尾,系统都会自动加一个字符'\0'作为该字符串的“结束标志符”,系统据此判断字符串是否结束。在LPC语言中类似,字符串"china"长度是5,但实际上在内存中占6个字节,"china"[5]不会报数组越界错误,而是返回0,而"china"[6]才会越界报错。

还可以使用<n从字符串末尾开始取值,str[<x] 相当于 str[strlen(str) - x],比如:"china"[<1]相当于"china[4]",因为字符串是0值结束,"china"[<0]则会返回0,所以如果从尾部开始取第一个字符是<1,即"china[<1]""a"

子字符串操作

在LPC语言中,对字符串取子字符串的操作形式是:

str[n1..n2];

具体用法第二章已经介绍,示例代码为 2.1.5.c,这里复习一下:

n1和n2为子字符串的下标范围,对长度为n的字符串,n1最小值为0,n2最大值为n-1。和取单个字符不同,子字符串下标范围越界不会报错,而是有以下规则:

  1. 如果n1小于0,那么相当于0
  2. 如果n2大于n-1,那么相当于n-1

另外还有以下规则:

  1. 如果n1 > n-1n1 > n2,返回空字符串""
  2. 和在字符串中取字符类似,子字符串下标加'<'代表从字符串尾部开始。
  3. 如果直接取值到字符串尾,n2可以省略,str[n1..] 等价于 str[n1..<1](注意:n1不可省略)。

提示:请注意str[n..n]str[n]的区别。

字符串比较

LPC语言中字符串比较可以直接使用比较运算符,也可以使用外部函数 strcmp(),这个外部函数的用法和C语言中的同名函数完全相同。普通比较使用运算符就好,但结合数组排序外部函数 sort_array() 使用时用 strcmp() 更方便。

// 示例:6.4.2
int main(object me, string arg)
{
    string *arr = ({"master", "apply", "efun", "mud", "fluffos", "test"});
    printf("原始数组 = %O\n", arr);
    printf("排序后数组 = %O\n", sort_array(arr, (: strcmp :)));
    return 1;
}

部分字符串相关外部函数

字符串处理相关外部函数是比较多的,常用的有:capitalizecryptexplodeimplodelower_caseoldcryptrepeat_stringreplace_stringsprintfsscanfstrcmpstringpstrlenstrsrchtrimltrimrtrim

这些函数具体用法请看:https://wiki.mud.ren/index.php?title=Lpc:Efun

其中 sscanf() 外部函数常用来处理玩家输入指令,具体语法说明如下:

名称

sscanf() - 从一个字符串匹配格式化输入

语法

int sscanf( string str, string fmt, mixed var1, mixed var2 ... );

描述

以格式 `fmt` 分析字符串 `str`,返回值是匹配字符串的格式定义符数量。`fmt` 可以包含使用 `%d` 或 `%s` 分隔的字符串,每一个 `%d` 和 `%s` 按顺序对应一个变量参数 `var1`、`var2`...。`%d` 读入整数到变量,`%s` 读入字符串到变量。* 也可以用在格式定义符中(如 %*d 和 %*s),表示忽略对应的内容(不分配给变量)。

LPC语言中的 sscanf() 函数和C语言中的同名函数功能类似,但又稍有不同,一方面不需要像C语言一样对普通变量使用取地址运算符 &,另一方面在LPC语言中 sscanf(str, "%s %s", str1, str2) 会把第一个单词分配给变量str1,剩余部分分配给str2,而在C语言中str2只会是第二个单词。请注意 %s%s 是不能使用的。

外部函数 crypt() 用来加密字符串,常用来存储玩家密码,fluffos 和 mudos 的加密方式不同,如果要兼容,只能使用 oldcrypt() 外部函数加密。具体语法说明如下:

名称

crypt() - 加密一个字符串

语法

string crypt( string str, string seed );

描述

以字符串 `seed` 为种子加密字符串 `str`,如果 `seed` 是 0,使用随机种子。

如果以字符串 str 加密后的字符串做为种子继续对字符串 str 加密,返回字符串还是这个种子。用 crypt() 函数验证密码的示例:

if (crypt(pwd, crypt_pwd) == crypt_pwd)
{
    // ...
}

以上示例中 pwd 为玩家输入的密码,crypt_pwd 为系统保存的加密密码。

京ICP备13031296号-4