摘要

仓颉的语法设计既保留了 C 族语言的熟悉性,又融入了现代语言的表达力。本文详解基础语法、原始类型、复合类型、类型转换,通过丰富代码示例帮助初学者快速上手,为学习高阶特性奠定基础。


一、语言基础语法

1.1 变量与常量

// 常量声明(编译时已知,不可变)
const MAX_SIZE: Int32 = 100
const PI: Float64 = 3.14159

// 可变变量
var age: Int32 = 25
age = 30  // ✓ 允许

// 不可变变量(let 绑定)
let name: String = "Alice"
// name = "Bob"  // ✗ 编译错误

// 类型推断
let count = 42       // 推断为 Int32
let factor = 1.5     // 推断为 Float64
let message = "Hi"   // 推断为 String

1.2 注释风格

// 单行注释
let x = 10  // 行尾注释

/* 
   多行注释
   可以跨越多行
*/

/*! 文档注释 - 会被文档生成器读取 */
func example() {
    // ...
}

/// 文档注释 - 用于函数/类型前
/// @param input 输入参数
/// @return 返回值说明
func process(input: String): String {
    return input.toUpperCase()
}

二、原始数据类型详解

2.1 整数类型

整数类型
有符号整数
无符号整数
Int8
-128 to 127
Int16
-32768 to 32767
Int32
最常用
Int64
大数值
UInt8
0 to 255
UInt16
UInt32
UInt64
// 不同位宽的整数
let byte_val: Int8 = 127
let short_val: Int16 = 32000
let int_val: Int32 = 2_147_483_647  // 下划线便于阅读
let long_val: Int64 = 9_223_372_036_854_775_807

// 无符号整数
let unsigned: UInt32 = 4_294_967_295

// 溢出检查(发布模式自动禁用)
let result = byte_val + 1  // 调试模式会检查溢出

// 进制表示
let decimal = 255
let hex = 0xFF
let binary = 0b11111111
let octal = 0o377

2.2 浮点数类型

// 浮点数类型
let single: Float32 = 3.14
let double: Float64 = 3.14159265359

// 科学计数法
let large = 1.23e10    // 1.23 × 10^10
let small = 1.5e-5     // 0.000015

// 特殊值
let infinity = Float64.POSITIVE_INFINITY
let neg_infinity = Float64.NEGATIVE_INFINITY
let not_a_number = Float64.NaN

// 浮点数比较(需谨慎)
func almostEqual(a: Float64, b: Float64, epsilon: Float64 = 1e-9): Bool {
    return (a - b).abs() < epsilon
}

2.3 布尔与字符

// 布尔类型
let isActive: Bool = true
let isEmpty: Bool = false

// 布尔运算
let result1 = true && false   // 逻辑与
let result2 = true || false   // 逻辑或
let result3 = !true           // 逻辑非

// 字符类型
let char_a: Char = 'A'
let char_emoji: Char = '😀'
let char_code = char_a.toInt32()  // 65

// 字符串类型
let str = "Hello"
let multiline = """
    第一行
    第二行
    第三行
    """

三、复合数据类型

3.1 数组类型(Array)

// 数组声明与初始化
let arr1: Array<Int32> = [1, 2, 3, 4, 5]
let arr2 = [10, 20, 30]  // 类型推断
let arr3 = Array<String>(capacity: 10)  // 指定容量

// 数组访问与修改
var numbers = [1, 2, 3]
println(numbers[0])      // 输出: 1
numbers[1] = 20          // 修改元素
numbers.append(4)        // 追加元素
numbers.insert(0, at: 0) // 在索引 0 处插入

// 数组遍历
for (index, value) in numbers.enumerated() {
    println("Index: \(index), Value: \(value)")
}

// 数组操作
let doubled = numbers.map { x => x * 2 }
let filtered = numbers.filter { x => x > 2 }
let sum = numbers.reduce(0) { acc, x => acc + x }

// 切片操作
let slice = numbers[0..<3]  // 获取前 3 个元素
let tail = numbers[2...]   // 从索引 2 到末尾

3.2 字典类型(Dictionary)

// 字典声明与初始化
let dict1: Dictionary<String, Int32> = ["apple": 5, "banana": 3]
let dict2 = ["name": "Alice", "city": "Beijing"]

// 字典访问
if let value = dict1["apple"] {
    println("Apple count: \(value)")
}

// 字典修改
var settings = ["theme": "dark", "language": "zh"]
settings["theme"] = "light"
settings["newKey"] = "newValue"

// 字典遍历
for (key, value) in settings {
    println("\(key): \(value)")
}

// 字典操作
let keys = settings.keys
let values = settings.values
let count = settings.count

3.3 元组类型(Tuple)

// 元组声明
let point: (Int32, Int32) = (10, 20)
let person = (name: "Alice", age: 28, city: "Beijing")

// 元组访问
let x = point.0
let y = point.1

let name = person.name
let age = person.age

// 元组作为函数返回值
func divideWithRemainder(a: Int32, b: Int32): (quotient: Int32, remainder: Int32) {
    return (a / b, a % b)
}

let (q, r) = divideWithRemainder(17, 5)
println("17 ÷ 5 = \(q) 余 \(r)")  // 输出: 3 余 2

// 元组解构
let (firstName, lastName, _) = ("John", "Doe", "Jr")
// _ 用于忽略不需要的值

四、字符串处理

4.1 字符串基础

// 字符串声明
let str1 = "Hello, Cangjie!"
let str2: String = "World"

// 字符串拼接
let greeting = "Hello" + " " + "World"
let formatted = "Value: \(42)"  // 字符串插值

// 多行字符串
let doc = """
    这是一个多行字符串
    可以包含多行文本
    通常用于文档或 SQL
    """

// 字符串长度与访问
let text = "Cangjie"
println(text.count)      // 字符计数
println(text.length)     // 字节长度
println(text[0])         // 访问第一个字符

// 字符串转义
let escaped = "Line 1\nLine 2\tTabbed"
let path = "C:\\Users\\Name"

4.2 字符串操作

var text = "Hello World"

// 大小写转换
let upper = text.toUpperCase()      // HELLO WORLD
let lower = text.toLowerCase()       // hello world

// 字符串查询
let contains = text.contains("World")     // true
let startsWith = text.startsWith("Hello") // true
let endsWith = text.endsWith("d")         // true
let index = text.find("World")            // 6

// 字符串提取
let substring = text.substring(0, 5)      // "Hello"
let replaced = text.replace("World", "Cangjie")  // "Hello Cangjie"

// 字符串分割与拼接
let parts = "a,b,c".split(",")
let joined = ["x", "y", "z"].join("-")    // "x-y-z"

// 字符串trim
let padded = "  spaces  "
let trimmed = padded.trim()

五、类型转换

5.1 显式类型转换

// 整数转换
let int_val: Int32 = 42
let int64_val: Int64 = Int64(int_val)
let uint_val: UInt32 = UInt32(int_val)

// 浮点数转换
let float_val: Float32 = Float32(3.14)
let double_val: Float64 = Float64(float_val)

// 数值到字符串
let str_from_int = String(42)
let str_from_float = String(3.14)

// 字符串到数值
if let num = Int32.parse("42") {
    println("Parsed: \(num)")
}

if let float = Float64.parse("3.14") {
    println("Float: \(float)")
}

// 字符转整数
let char = 'A'
let ascii = char.toInt32()     // 65
let from_ascii = Char(65)      // 'A'

5.2 as 运算符与类型检查

// 子类型向上转换(always safe)
class Animal {}
class Dog: Animal {}

let dog = Dog()
let animal: Animal = dog as Animal

// 类型转换与类型检查
func describe(_ obj: Any) {
    if let str = obj as? String {
        println("String: \(str)")
    } else if let num = obj as? Int32 {
        println("Int: \(num)")
    } else {
        println("Other type")
    }
}

describe("Hello")  // 输出: String: Hello
describe(42)       // 输出: Int: 42

六、完整示例:数据类型综合应用

// 定义一个学生信息结构体
struct Student {
    var id: Int32
    var name: String
    var scores: Array<Float32>
    var info: (grade: Int32, class: Int32)
}

// 为 Student 实现方法
impl Student {
    // 计算平均分
    func averageScore(): Float32 {
        let sum = scores.reduce(0.0) { acc, x => acc + x }
        return sum / Float32(scores.count)
    }
    
    // 返回学生信息
    func description(): String {
        let avg = averageScore()
        return "\(name) - 平均分: \(avg)"
    }
    
    // 判断是否优秀(平均分 >= 85)
    func isExcellent(): Bool {
        return averageScore() >= 85.0
    }
}

func main() {
    // 创建学生
    var student = Student(
        id: 1001,
        name: "Alice",
        scores: [85.5, 92.0, 88.5, 95.0],
        info: (grade: 10, class: 1)
    )
    
    println(student.description())
    
    if student.isExcellent() {
        println("\(student.name) 是优秀学生!")
    }
    
    // 创建学生数组
    var students = [Student]()
    students.append(student)
    
    // 统计优秀学生
    let excellent = students.filter { s => s.isExcellent() }
    println("优秀学生数: \(excellent.count)")
    
    // 按平均分排序
    students.sort { a, b =>
        a.averageScore() > b.averageScore()
    }
}

七、类型系统最佳实践

7.1 何时使用各类型

场景 推荐类型 原因
整数计数 Int32 平衡性能与范围
大整数 Int64 防止溢出
金融计算 Decimal(第三方库) 精度高
网络编程 UInt32 无符号更方便
科学计算 Float64 精度更高

7.2 避免常见错误

// ✗ 错误:浮点数精度问题
let x = 0.1 + 0.2  // 0.30000000000000004
if x == 0.3 { println("Equal") }  // 不会执行

// ✓ 正确:使用 epsilon 比较
func floatEqual(a: Float64, b: Float64): Bool {
    return (a - b).abs() < 1e-9
}

// ✗ 错误:忽视整数溢出
let large: Int32 = 2_147_483_647
let overflow = large + 1  // 溢出!

// ✓ 正确:使用更大的类型
let large: Int64 = 2_147_483_647
let safe = large + 1

// ✗ 错误:数组索引越界
let arr = [1, 2, 3]
println(arr[10])  // 运行时崩溃

// ✓ 正确:检查边界
if index < arr.count {
    println(arr[index])
}

八、总结与进阶建议

✅ 关键要点

  • 8 种基础类型覆盖日常编程需求
  • 复合类型(数组、字典、元组)灵活强大
  • 类型系统严格在编译期捕获错误
  • 字符串作为一级类型,操作丰富

📚 进阶方向

  • 学习 Trait泛型实现代码复用
  • 深入 所有权系统理解内存管理
  • 掌握 模式匹配优雅处理复杂情况

参考链接


Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐