基础数据类型
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 类型表示布尔值,只有两个可能的值:true 和 false。
布尔字面量
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;
类型别名不会创建新类型,只是为现有类型提供更有意义的名称。
类型安全最佳实践
- 始终显式标注类型:提高代码可读性
- 使用 const 保护常量:防止意外修改
- 进行类型检查:在使用 unknown 类型时
- 避免不必要的类型转换:保持类型一致性
- 使用类型别名:提高代码可读性
小结
本章介绍了 Sii 2 的所有基础数据类型:
- 整数类型:int
- 浮点数类型:singlef, multif
- 布尔类型:bool
- 字符类型:str
- 字符串类型:string
- 特殊类型:void, unknown
- 复合类型:arr, obj
- 类型转换和检查:显式转换和类型检查机制
下一章我们将学习如何使用函数来组织和重用代码。