跳到主要内容

基础数据类型

Sii 2 提供了丰富的数据类型系统,包括基础类型、复合类型和用户定义类型。本章将详细介绍所有可用的数据类型。

类型系统概述

Sii 2 的类型系统是静态的、强类型的,这意味着:

  • 编译时类型检查:所有类型错误在编译时被发现
  • 类型安全:不能将不兼容的类型赋值给变量
  • 类型推断:在某些情况下可以自动推断类型(但显式标注更推荐)

基础类型(标量类型)

整数类型 (int)

int 类型表示整数,可以是正数、负数或零。

整数字面量

let positive: int = 42;
let negative: int = -10;
let zero: int = 0;
let large: int = 1000000;

整数运算

let a: int = 10;
let b: int = 3;

let sum: int = a + b; // 13
let diff: int = a - b; // 7
let product: int = a * b; // 30
let quotient: int = a / b; // 3 (整数除法)
let remainder: int = a % b; // 1 (取余)

整数范围

int 类型的范围取决于目标平台,通常为:

  • 32位平台:-2,147,483,648 到 2,147,483,647
  • 64位平台:-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807

浮点数类型

Sii 2 提供两种浮点数类型:

单精度浮点数 (singlef)

singlef 类型用于表示单精度浮点数,通常占用 32 位。

let pi: singlef = 3.14159;
let temperature: singlef = 36.5;
let negative: singlef = -10.5;

多精度浮点数 (multif)

multif 类型用于表示多精度浮点数,通常占用 64 位,精度更高。

let precise: multif = 3.141592653589793;
let scientific: multif = 1.23e-4; // 科学计数法

浮点数运算

let a: singlef = 10.5;
let b: singlef = 3.2;

let sum: singlef = a + b; // 13.7
let diff: singlef = a - b; // 7.3
let product: singlef = a * b; // 33.6
let quotient: singlef = a / b; // 3.28125

浮点数注意事项

  • 浮点数运算可能存在精度误差
  • 比较浮点数时应该使用误差范围,而不是直接相等比较
let a: singlef = 0.1;
let b: singlef = 0.2;
let sum: singlef = a + b;
// sum 可能不等于 0.3,而是 0.30000000000000004

布尔类型 (bool)

bool 类型表示布尔值,只有两个可能的值:truefalse

布尔字面量

let isActive: bool = true;
let isComplete: bool = false;

布尔运算

let a: bool = true;
let b: bool = false;

let andResult: bool = a && b; // false (逻辑与)
let orResult: bool = a || b; // true (逻辑或)
let notResult: bool = !a; // false (逻辑非)

布尔转换

let num: int = 10;
let isPositive: bool = num > 0; // true

let text: string = "hello";
let isEmpty: bool = text.length() == 0; // false

字符类型 (str)

str 类型表示单个字符。

字符字面量

let letter: str = 'A';
let digit: str = '5';
let space: str = ' ';
let newline: str = '\n';

字符转义序列

let tab: str = '\t';        // 制表符
let newline: str = '\n'; // 换行符
let carriage: str = '\r'; // 回车符
let backslash: str = '\\'; // 反斜杠
let singleQuote: str = '\''; // 单引号
let doubleQuote: str = '\"'; // 双引号

字符串类型 (string)

string 类型表示字符串,是字符的序列。

字符串字面量

let greeting: string = "Hello, World!";
let empty: string = "";
let multiline: string = "Line 1\nLine 2\nLine 3";

字符串拼接

let firstName: string = "John";
let lastName: string = "Doe";
let fullName: string = firstName + " " + lastName; // "John Doe"

字符串插值(如果支持)

let name: string = "Alice";
let age: int = 25;
// 注意:Sii 2 可能不支持字符串插值,需要使用拼接
let message: string = "Name: " + name + ", Age: " + age.toString();

字符串操作

let text: string = "Hello, World!";

// 获取长度
let len: int = text.length();

// 获取字符(如果支持索引)
// let firstChar: str = text[0]; // 取决于实现

// 查找子字符串
// let found: bool = text.contains("World"); // 取决于实现

空值类型 (void)

void 类型表示"无值",主要用于函数没有返回值的情况。

func printMessage(msg: string): void {
sii.io.print(msg);
// 没有返回值,返回类型为 void
}

未知类型 (unknown)

unknown 类型表示类型未知的值,通常用于处理动态输入或外部数据。

// 获取用户输入
let userInput: string = sii.io.readLine(); // 读取字符串输入
sii.io.print(userInput);

// 读取不同类型输入
let age: int = sii.io.readInt(); // 读取整数
let price: singlef = sii.io.readSinglef(); // 读取单精度浮点数
let value: multif = sii.io.readMultif(); // 读取多精度浮点数

复合类型

数组类型 (arr)

数组是相同类型元素的集合。Sii 2 支持泛型数组类型,可以指定元素类型。

数组语法结构

数组类型声明:

let 变量名: arr<元素类型> = 初始值;
// 或
let 变量名: arr = 初始值; // 元素类型为 unknown

数组字面量:

[元素1, 元素2, 元素3, ...]

数组访问:

数组名[索引表达式]

数组赋值:

数组名[索引表达式] =;

push 语句:

push 值 -> 数组名[索引];

rmv 语句:

rmv 数组名[索引];

out 语句:

out 数组名[索引] as 变量名 {
代码块
}

数组类型语法

// 非泛型数组(元素类型为 unknown)
let arr1: arr = new Array();

// 泛型数组(指定元素类型)
let arr2: arr<int> = [1, 2, 3];
let arr3: arr<string> = ["a", "b", "c"];

数组声明和初始化

// 声明空数组
let numbers: arr = new Array();

// 初始化数组元素
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;

// 或者使用数组字面量
let numbers2: arr = [10, 20, 30];

// 声明泛型数组类型
let numbers3: arr<int> = [1, 2, 3, 4, 5];

数组访问和修改

let numbers: arr<int> = [10, 20, 30];

// 获取元素
let first: int = numbers[0]; // 10

// 修改元素
numbers[0] = 100; // 将索引 0 的元素改为 100

// 数组赋值
numbers[1] = 200; // 将索引 1 的元素改为 200

数组操作语句

Sii 2 提供了三个特殊的数组操作语句:

1. push 语句 - 添加元素

let numbers: arr<int> = new Array();

// push 语法:push 值 -> 数组[索引];
push 1 -> numbers[0];
push 2 -> numbers[1];
push 3 -> numbers[2];

2. rmv 语句 - 删除元素

let numbers: arr<int> = [10, 20, 30, 40];

// rmv 语法:rmv 数组[索引];
rmv numbers[1]; // 删除索引 1 的元素(20)
// 删除后数组变为 [10, 30, 40]

3. out 语句 - 遍历元素

let numbers: arr<int> = [10, 20, 30];

// out 语法:out 数组[索引] as 变量名 { 代码块 }
out numbers[0] as item {
sii.io.print(item.toString()); // 输出 10
}

数组方法

length() - 获取数组长度

let numbers: arr<int> = [1, 2, 3, 4, 5];
let len: int = numbers.length(); // 5

// 检查数组是否为空
if (numbers.length() == 0) {
sii.io.print("数组为空");
}

cutIt() - 截取数组

let numbers: arr<int> = [1, 2, 3, 4, 5];

// cutIt(start) - 从 start 索引开始截取到末尾
let sub1: arr<int> = numbers.cutIt(2); // [3, 4, 5]

// cutIt(start, end) - 从 start 索引开始截取到 end 索引(不包含 end)
let sub2: arr<int> = numbers.cutIt(1, 4); // [2, 3, 4]

splice() - 切片操作

let numbers: arr<int> = [1, 2, 3, 4, 5];

// splice(start) - 从 start 索引开始切片
let result1: arr<int> = numbers.splice(2); // [3, 4, 5]

// splice(start, deleteCount, ...items) - 删除并插入元素
let result2: arr<int> = numbers.splice(1, 2, 10, 20);
// 从索引 1 开始删除 2 个元素,然后插入 10 和 20

数组遍历

方法1:使用 forloop

let numbers: arr<int> = [10, 20, 30];

forloop (let i: int = 0; i < numbers.length(); i.getUp(1)) {
let value: int = numbers[i];
sii.io.print(value.toString());
}

方法2:使用 out 语句

let numbers: arr<int> = [10, 20, 30];

// out 语句用于遍历单个元素
out numbers[0] as item {
sii.io.print(item.toString());
}

数组操作完整示例

// 创建数组
let scores: arr<int> = new Array();

// 添加元素
push 85 -> scores[0];
push 90 -> scores[1];
push 78 -> scores[2];

// 获取长度
let count: int = scores.length(); // 3

// 访问元素
let firstScore: int = scores[0]; // 85

// 修改元素
scores[1] = 95;

// 截取数组
let topScores: arr<int> = scores.cutIt(1); // [95, 78]

// 删除元素
rmv scores[2]; // 删除最后一个元素

// 遍历数组
forloop (let i: int = 0; i < scores.length(); i.getUp(1)) {
sii.io.print("Score " + i.toString() + ": " + scores[i].toString());
}

数组类型安全

// 泛型数组确保类型安全
let numbers: arr<int> = [1, 2, 3];

// 类型检查
let index: int = 0;
if (index >= 0 && index < numbers.length()) {
let value: int = numbers[index];
sii.io.print(value.toString());
} else {
sii.io.print("索引越界");
}

对象类型 (obj)

obj 类型表示动态对象,可以包含任意属性和方法。使用 crob 关键字创建对象。

crob person = new Object();
person.name = "Alice";
person.age = 25;
person.isActive = true;

类型转换

显式类型转换

Sii 2 支持显式的类型转换:

数值转换

let num: int = 10;

// 转换为字符串 - 使用方法调用
let text: string = num.toString(); // "10"

// 转换为浮点数
let float: singlef = num.toSinglef(); // 10.0
let double: multif = num.toMultif(); // 10.0

字符串转换

let text: string = "123";

// 转换为整数
let num: int = text.toInt(); // 123

// 转换为浮点数
let float: singlef = text.toSinglef(); // 123.0

布尔转换

let text: string = "true";
let boolValue: bool = text.toBool(); // true

let num: int = 1;
let isTrue: bool = num != 0; // true (非零为真)

类型检查

使用 typeins 函数检查值的类型:

// 类型检查示例
let value: int = 42;

let typeName: string = typeins(value);
sii.io.print("Type: " + typeName);

if (typeName == "int") {
let num: int = value;
sii.io.print("Number: " + num.toString());
}

类型别名

可以使用 type 关键字创建类型别名:

type UserId = int;
type UserName = string;
type UserAge = int;

let id: UserId = 1001;
let name: UserName = "Alice";
let age: UserAge = 25;

类型别名不会创建新类型,只是为现有类型提供更有意义的名称。

类型安全最佳实践

  1. 始终显式标注类型:提高代码可读性
  2. 使用 const 保护常量:防止意外修改
  3. 进行类型检查:在使用 unknown 类型时
  4. 避免不必要的类型转换:保持类型一致性
  5. 使用类型别名:提高代码可读性

小结

本章介绍了 Sii 2 的所有基础数据类型:

  • 整数类型:int
  • 浮点数类型:singlef, multif
  • 布尔类型:bool
  • 字符类型:str
  • 字符串类型:string
  • 特殊类型:void, unknown
  • 复合类型:arr, obj
  • 类型转换和检查:显式转换和类型检查机制

下一章我们将学习如何使用函数来组织和重用代码。