c语言 printf_第五节 LPC语言基本数据类型

LPC语言的数据类型基本和C语言类似,但是和C语言相同和相似的数据类型只有:整型(int)、浮点型(float)、字符串(string)、数组(array)、结构体(struct)。C语言中的其它数据类型在LPC语言中没有。

1. 有符号整型(int)

在C语言中的整数分 short、int、long,还有无符号数 unsigned,但在LPC语言中,只有 int 类型

在 fluffos 驱动中,int 的长度是8个字节,长度和C语言64 位 Linux 及 Mac OS 下的长整型一样,取值范围是-263 ~ 263-1,即-9223372036854775808~9223372036854775807。

在C语言中,如果数值超出取值范围会超成数据溢出,如下C语言代码,在64位 Linux 系统下,因为溢出,输出结果变成:-9223372036854775808

#include <stdio.h>
int main()
{
    long i = 9223372036854775808;
    printf("%ldn", i);
    return 0;
}

但是在LPC中,对数据溢出的处理方式不太一样,如果变量赋值超出最大值,取最大值,如果赋值小于最小值,取最小值(截止2019-04-20,fluffos最小值有BUG,实际值为-9223372036854775807),但是对赋值后的变量做运算,会和C语言一样的溢出。

我们在 /cmds/test/ 目录新建文件 2.1.1.c ,代码如下:

// 示例:2.1.1
int main(object me, string arg)
{
    // MAX_INT、MIN_INT 为 fluffos 定义宏
    int a = MAX_INT, b = MIN_INT;
    // 赋值时做运算
    int c = MAX_INT + 1, d = MIN_INT - 1, e = d - 1;
    // 赋值超出取值范围(10倍)
    int f = 92233720368547758070, g = -92233720368547758080;
    printf("a = %dnb = %dnc = %dnd = %dne = %dnf = %dng = %dn", a, b, c, d, e, f, g);

    return 1;
}

然后输入指令 2.1.1 ,输出结果如下:

a =  9223372036854775807
b = -9223372036854775807
c = -9223372036854775808
d = -9223372036854775808
e =  9223372036854775807
f =  9223372036854775807
g = -9223372036854775807

代码中的 MAX_INTMIN_INT 是 fluffos 宏定义的整形最大值和最小值,变量 a、f都取最大值,变量 b、g都取最小值,但从结果看,最小值输出比实际大了1,这是 fluffos 的 BUG。变量 c 运算后溢出,变量 d 理论上应该溢出,但因为系统 BUG ,造成实际取了真实的最小值,变量 e 在真实的最小值上运算后溢出。

注意,如果在运行时修改了代码,需要重新编译文件(指令:update)或者重启系统(指令:shutdown)才能生效。

示例代码中的 printf() 函数是LPC语言的 efun,可以理解为类似C语言的库函数(Library Function),因为LPC是从C语言衍生的,语法结构和C语言基本一样,但是C语言的库函数在LPC中不存在,千万不要直接把C语言中的函数在LPMUD开发中直接用,LPC语言中有很多和C语言同名且功能相同或相似的函数,如 printf(),但也有很多和C语言同名但功能不太一样的函数,如 sizeof(),还有更多C语言中没有的函数,如 this_player(),这些独有的函数让LPC开发网络游戏变的更为便捷,关于函数,后续章节会重点介绍。

为方便学习,这里先补充一下格式化输出函数 printf()的用法,在LPC语言中的用法和C语言中的同名函数基本一样,只是格式控制修饰符和数据类型有一些差异。printf() 格式控制符的完整形式如下:

%[flag][width][.precision]type
[ ] 表示此处的内容可有可无,是可以省略的。

和C语言相比,标志控制符(flag)增加了“|”(列居中对齐)、“=”(字符串纵列模式)、“'X'”(使用指定字符填充空位,X代表任意字符)和 “@”(指明参数为数组);修改了“#”的作用为字符串输出为表格模式。

输出类型(type)只有 "c"、"s"、"d/i"、"f"、"o"、"x/X",作用和C语言一致,同时新增了"O"表示LPC语言数据类型(可输出LPC语言的任何类型),关于 printf 函数的说明文档可看这里:printf/sprintf。

这里需要特别说明的是,LPC语言中没有字符型(char),但是在输出中可以把整型输出为字符,而且和C语言一样,可以直接把字符赋值给整型变量。C语言中的整数除了可以使用十进制,还可以使用八进制和十六进制,在LPC语言中,整数只能用十进制和十六进制赋值,可以用八进制输出,但不能用八进制赋值,而且和C语言一样既不能用二进制赋值也无法用二进制输出。

新建示例文件 2.1.2.c,代码如下:

// 示例:2.1.2
int main(object me, string arg)
{
    int a = 16, b = 'a', c = 0xF;

    printf("a 十进制为%d,八进制为%o,十六进制为%xn", a, a, a);
    printf("b 十进制为%d,ASCII字符为%cn", b, b);
    printf("c 十进制为%d,十六进制为%x或%Xn", c, c, c);

    return 1;
}

输出结果为:

a 十进制为16,八进制为20,十六进制为10
b 十进制为97,ASCII字符为a
c 十进制为15,十六进制为f或F

如果修改代码使用八进制赋值会发现其实还是十进制,而用二进制赋值的话,代码编译报错。

2. 单精度浮点型(float)

在LPC语言中,小数只有 float 类型,但是实际和C语言中的 double 类型一样,取值范围为 ±1.7E-308 和 ±1.7E308 之间。

和C语言不同的是,LPC语言中的浮点数只能用十进制形式表示,不可以使用指数形式,如果使用指数形式赋值会报错。另外,因为LPC语言中只有一种小数类型,所以,也就没有C语言中的数字加后缀L或F指明类型了。

在 fluffos 中,也定义了二个宏表示特定的浮点数,MAX_FLOAT 表示浮点数的最大值,但是 MIN_FLOAT 却是表示 0.00000,这很奇怪,应该是 BUG。另外,在不同的操作系统下,浮点数的最大值和最小值是不一样的。

使用以下代码试试看,会输出一个大到你数不出来的数字(整数部分309位)。

// 示例:2.1.3
int main(object me, string arg)
{
    float fa = MAX_FLOAT;
    // 最小值定义有错
    float fi = MIN_FLOAT;

    printf("fa = %fnfi = %fn", fa, fi);

    return 1;
}

输出结果不同系统下精度不太一样哦。

3. 字符串类型(string)

和C语言差别比较大的一种数据类型,我们知道,C语言严格上说没有字符串数据类型,字符串类型实际上是字符数组,可以使用以下几种方式赋值:

#include <stdio.h>

int main(int argc, char const *argv[])
{
    char str1[] = {"mud.ren"};
    char str2[] = "mud.wiki";
    char *str = "www.mud.ren";

    printf("str1 = %snstr2 = %snstr = %sn", str1, str2, str);
    return 0;
}

在LPC语言中,没有字符类型,无法使用这种方式赋值字符串,但是单独增加了字符串类型(string),可以直接赋值并使用。

// 示例:2.1.4
int main(object me, string arg)
{
    string s = "www.mud.ren";
    printf("s = %sn",s);

    return 1;
}

在C语言中""包围起来的字符串中间不能换行,但是,在LPC语言中,""中的内容可以换行,看看以下的例子:

// 示例:2.1.5
int main(object me, string arg)
{
    string qr="
█████████████████████████████████████
█████████████████████████████████████
████ ▄▄▄▄▄ █▀▀ ██  ▀██ █▀█ ▄▄▄▄▄ ████
████ █   █ █▄▀██▀█▀ █▄ ▀▄█ █   █ ████
████ █▄▄▄█ █ ▄ █ █▄▀▄█  ██ █▄▄▄█ ████
████▄▄▄▄▄▄▄█ █ ▀▄█▄█▄▀▄▀ █▄▄▄▄▄▄▄████
████▄▄▀▄▀█▄ █▀█  ▀ ▀ ▀▀▄█▀ ▄▄▀▄▄▀████
████▀  ▄▄▀▄█▀▀▀  ▀█▀ ▄█ ██▀ ▄▄  █████
█████ ▀██ ▄▄▀█▄ █ █▀███   ▄██▄█▄▄████
████▀ █▄▄▀▄▄▀   █▀▄▀█ ██ ▀███ ▄ ▄████
█████▄▄▄▀▀▄ ▄▄▄█  ▀▄ ▄▀█▄ ▀ █▀█▄▀████
████▄█▀ █▄▄█  ▄▄ █▀▀▄ ▄▀██ █▀██  ████
████▄█▄██▄▄▄ ▀▀▀▄ ▀█▀▄▀▀ ▄▄▄ █ ▀▀████
████ ▄▄▄▄▄ █▄▀▀▀▄▀██▀▄▀█ █▄█ ▀▀▄█████
████ █   █ █▀▀  ▄▄███ ▀█ ▄   ▀▀ █████
████ █▄▄▄█ █▀ ▄ █▀▄█▄    ▄█▄▄▄▄▀▄████
████▄▄▄▄▄▄▄█▄██▄▄▄██▄▄█▄▄██▄▄██▄█████
█████████████████████████████████████
█████████████████████████████████████

        扫码加雪风微信 ^_^
";
    printf("%sn", qr);
    return 1;
}

在LPC语言中,对字符串取子字符串的操作很别致而灵活,使用子字符串操作符,形式是:

str[n1..n2];

如果数值超过字符串的长度,视为字符串的长度。如果二个数值相等(str[n1..n1]),则传回字符串的第 n1 个字符。如果二个数值都超过字符串的长度,或者第一个数字所指的位置在第二个数字所指位置之后,会传回空字符串“”。如果要从右如果从左开始使用<n,如 arr[1..<1],从左开始第一个数值为0,如果从右开始第一个数值为1。

测试如下代码:

// 示例:2.1.6
int main(object me, string arg)
{
    string s = "www.mud.ren";

    printf("s = %sn", s);
    printf("s[4..4] = %sn", s[4..4]);
    printf("s[4..6] = %sn", s[4..6]);
    printf("s[0..20] = %sn", s[0..20]);
    printf("s[20..30] = %sn", s[20..30]);
    printf("s[1..0] = %sn", s[1..0]);
    printf("s[4..<1] = %sn", s[4..<1]);
    printf("s[<7..<5] = %sn", s[<7..<5]);

    return 1;
}

输出结果:

s = www.mud.ren
s[4..4] = m
s[4..6] = mud
s[0..20] = www.mud.ren
s[20..30] =
s[1..0] =
s[4..<1] = mud.ren
s[<7..<5] = mud

和C语言不同,LPC语言中的字符串不能当数组操作。

4. 数组类型(array)

数组类型,LPC语言和C语言的差别还是比较大的,在C语言中数组定义方式为:

dataType  arrayName[length];

并且可以使用指针操作数组。例如:

#include <stdio.h>

int main(int argc, char const *argv[])
{
    int arr[] = {1, 2, 3, 4};
    int *p = arr;
    printf("arr[0] = %dn", *p);
    return 0;
}

而在LPC语言中,数组用 ({}) 表示,并且使用类似指针的方式赋值,另外还有使用外部函数 allocate() 初始化的方式。具体定义数组的方式如下:

dataType *arrayName = ({value1, value2,...});    
dataType *arrayName = allocate(size, value);

allocate() 函数说明文档请看:

array/allocate​zhuanlan.zhihu.com

我们继续测试如下代码:

// 示例:2.1.7
int main(object me, string arg)
{
    string *str = ({"www", "mud", "ren"});
    int *arr = allocate(1 + random(9), (: $1 :));

    // @代表参数是数组,使用除@以外的格式循环输出数组的每个元素
    printf("str = %@-4sn", str);
    printf("str[0] = %s, str[1] = %s, str[2] = %sn", str[0], str[1], str[2]);
    printf("arr = %@','-2dn", arr);

    return 1;
}

输出结果如下:

str = www mud ren
str[0] = www, str[1] = mud, str[2] = ren
arr = 0,1,2,3

以上代码中第二种定义中使用了 random() 外部函数,所以 arr 每次输出结果是随机的。

数组严格上说不是一种数据类型,只是一种数据集合,关于数组的使用,后续章节会详细讲解,这里先了解LPC语言中数组定义的方式。

5. 结构体类型(struct)

结构体本质上也不是一种数据类型,而是一种数据集合,在C语言中数组是一组具有相同类型的数据的集合,而结构体用来存放一组不同类型的数据,但是在LPC语言中完全可以使用混合类型数组来实现存放不同类型的数据,或用使用更灵活的映射类型,所以结构体基本没什么大用,这里只做简单的介绍。

在C语言中的结构体类型关键字是 struct,LPC语言中,结构体变量的定义方法和C语言有一点不一样的地方是C语言中结构体定义时 } 后面必须有 分号(;),而LPC语言中不需要,另外LPC语言中结构体赋值取值只能使用 ->

在LPC语言中结构体有点像C++语言的类(class),也增加了关键字 class 可用,而且是使用 new 关键字实例化,看起来好像升级成类了。但是,又和C语言的 struct 一样只能包含成员变量,不能包含成员函数,本质上不能算类。

这里给一个具体的示例:

// 示例:2.1.8
class example {
    string name;
    int age;
    string *lover;
}

int main(object me, string arg)
{
    // 变量
    class example instance = new(class example);
    // 赋值
    instance->age = 24;
    instance->name = "Ivy";
    instance->lover = ({"Alice", "Vivian", "Jessica"});
    // 取值
    printf("name : %s,age : %d, lover : %@-7sn", instance->name, instance->age, instance->lover);
    return 1;
}

输出结果如下:

name : Ivy,age : 24, lover : Alice  Vivian Jessica

因为结构体类型在LPC语言中的定义和声明的方法和 struct 不完全一样,所以推荐使用 class 关键字。当然,以上代码中 class 改成 struct 也可以,甚至混用也没错。习开发的准备工作,为了更好的学习,这里先对基本术语做一个说明。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值