【仓颉语言入门 · 第6课】字符串详解与字符串插值

上节课我们用循环让程序学会了"重复干活"。不过前几课输出的还都是干巴巴的数字,而真实程序处理得最多的数据其实是文本:用户名、文件路径、一句话、一条日志……第 3 课我们简单用过双引号字符串,这节课把它彻底讲透——怎么把变量嵌进句子里(字符串插值)、怎么取出其中一部分(切片)、英文和汉字长度为什么不一样(UTF-8),以及一大批开箱即用的字符串方法。

本文是系列第 6 课:正式学习仓颉的 String(字符串)Rune(字符)、转义字符、特殊字符串(raw 串 / 多行串)、切片与常用方法,最后用一个"句子分析器"综合实战收尾。


目录(系列导航)

整套路线共 7 个模块、30 课,按每周 2~3 课的节奏,大约 2~3 个月可以走完一遍:

模块课次内容
一、环境与入门01~05环境搭建与 Hello World、变量与基本类型、运算符与输入输出、分支、循环
二、常用类型与数据组织06~10字符串、数组与区间、ArrayList/HashMap/HashSet、可空类型、错误处理
三、函数与函数式11~14函数、Lambda 与高阶函数、闭包、迭代器与惰性序列
四、面向对象与类型系统15~20struct/class、构造与属性、接口、枚举与 match 模式匹配、泛型、扩展
五、工程化与标准库21~25cjpm 包管理与多文件、文件 IO、JSON 处理、网络编程、单元测试
六、并发编程26~28线程、Channel 通道与同步原语、并发实战
七、项目实战29~30命令行小工具、GeoJSON 数据处理实战
  1. 环境搭建与第一个仓颉程序
  2. 变量与常量:let / var 与基本数据类型
  3. 运算符与标准输入输出
  4. 分支结构:if 与 match 表达式
  5. 循环结构:while / for / Range
  6. 字符串详解与字符串插值(本文)
  7. 数组 Array 与区间 Range
  8. 集合框架:ArrayList、HashMap、HashSet
  9. 可空类型 ? 与 Option
  10. 错误处理:异常机制与 Result
  11. 函数定义、参数与返回值
  12. Lambda 与高阶函数
  13. 闭包、作用域与函数类型
  14. 迭代器 Iterator 与 Sequence
  15. 结构体 struct 与类 class
  16. 构造函数、属性与方法
  17. 接口 interface 与实现
  18. 枚举 enum、代数数据类型与 match 模式匹配
  19. 泛型编程
  20. 扩展、类型别名与可见性控制
  21. cjpm 包管理与多文件项目组织
  22. 文件与目录 IO
  23. JSON 处理(结合 stdx 扩展库)
  24. 网络编程入门
  25. 单元测试
  26. 并发基础:线程的创建与等待
  27. Channel 通道与同步原语
  28. 并发实战:多线程任务处理
  29. 实战一:带文件持久化的命令行小工具
  30. 实战二:GeoJSON 数据处理程序

一、认识 String:文本的容器

双引号括起来的一段文字就是字符串字面量,类型是 String

package helloCangjie

main(): Int64 {
    let greeting = "你好,仓颉"
    let language = "Cangjie"

    // ① 用 + 拼接两段字符串
    println(greeting + ",欢迎学习 " + language + "!")

    // ② 用 * 让字符串重复出现
    println("重要的事情说三遍:" + "冲!" * 3)

    // ③ 按内容比较,用 == / < / >
    println("abc" == "abc")
    println("apple" < "banana")

    // ④ 判空:字符串里一个字符都没有
    println("空串吗:" + "".isEmpty().toString())
    return 0
}

运行结果:

你好,仓颉,欢迎学习 Cangjie!
重要的事情说三遍:冲!冲!冲!
true
true
空串吗:true

四点说明:

  • + 拼接:左右两边都必须是字符串(数字想拼进来要用下一节的插值,不能直接 "年龄" + 3);
  • * 重复"ab" * 3 得到 "ababab",画分隔线时很好用;
  • 比较的是内容== 判断文字是否完全相同,< / > 按字典序比较,直接写就行;
  • "" 是空字符串:它是一个真实存在的对象,只是长度为 0,用 isEmpty() 判断。

💡 String不可变类型:所有"修改"操作(拼接、替换、大小写转换……)都不会改动原来的字符串,而是返回一个新字符串。原变量想变,必须用 var 声明并重新赋值:s = s + "!"


二、字符串插值:让程序"好好说话"

+ 拼句子很快就会变成灾难:引号、逗号、类型转换混在一起。仓颉提供了字符串模板插值——在字符串里写 ${表达式},运行时自动求值并"嵌"进去:

package helloCangjie

main(): Int64 {
    let name = "小明"
    let age = 18
    let height = 1.75

    // ${} 里可以是变量
    println("我叫 ${name},今年 ${age} 岁")

    // ${} 里也可以是表达式:算术、方法调用、甚至另一个字符串
    println("再过 10 年我就 ${age + 10} 岁了")
    println("这句话是 ${"abc" == "abc"} 的:身高 ${height} 米")

    // 数字转字符串:插值是首选;也可以显式调用 toString()
    let scoreText = 95.toString()
    println("成绩:" + scoreText)
    return 0
}

运行结果:

我叫 小明,今年 18 岁
再过 10 年我就 28 岁了
这句话是 true 的:身高 1.750000 米
成绩:95

从第 1 课的 println("Hello World") 起你其实一直在用插值——${sum}${i} 都是它。记住三个要点:

  1. 花括号不能省:是 ${name} 不是 $name
  2. 花括号里是完整表达式:变量、四则运算、方法调用、比较运算都可以;
  3. 自动转字符串:数字、Bool 等类型插值时自动变成文本,不用手动转。

反向转换(字符串 → 数字)还是第 3 课的 Int64.parse,它住在 std.convert 包里,使用前要 import:

package helloCangjie

import std.convert.*;
import std.env.getStdIn;

main(): Int64 {
    print("请输入一个整数:")
    let text: String = getStdIn().readln().getOrThrow();
    let n = Int64.parse(text)
    println("解析后加 8 等于:${n + 8}")
    return 0
}

运行结果:

请输入一个整数:解析后加 8 等于:50

print 不换行,运行时输入的内容会接在提示后面显示;这里字符串直接给了 "42",所以提示语和结果在同一行。)


三、转义字符与特殊字符串

3.1 转义字符:让字符串"特殊一点"

字符串里有些字符没法直接敲出来(换行、制表符),有些会和语法冲突(字符串里出现双引号)。用反斜杠 \ 开头的转义字符表达:

写法含义
\n换行
\t制表符(Tab,一次跳一段空白)
\"双引号(不再被当成字符串结束)
\\一个反斜杠本身
\u{4ED3}按 Unicode 码点输出字符(4ED3 正是"仓"字)
package helloCangjie

main(): Int64 {
    println("第一行\n第二行\t(前面有个 Tab)")
    println("他说:\"仓颉真有意思!\"")
    println("Windows 路径要写双反斜杠:C:\\Users\\wangpeng")
    println("\u{4ED3}\u{9889}")    // 4ED3=仓,9889=颉
    return 0
}

运行结果:

第一行
第二行  (前面有个 Tab)
他说:"仓颉真有意思!"
Windows 路径要写双反斜杠:C:\Users\wangpeng
仓颉

3.2 Raw 字符串:反斜杠就是反斜杠

Windows 文件路径里全是 \,用普通字符串每个都要写成 \\,正则表达式更惨。仓颉提供 raw 字符串:在双引号两侧各加一个 #,即 #"..."#,里面的内容原样保留——反斜杠不转义、${} 不插值:

package helloCangjie

main(): Int64 {
    let path = #"C:\Users\wangpeng\Desktop\main.cj"#
    println(path)

    println(#"${name} 会原样显示,\n 也不会换行"#)
    return 0
}

运行结果:

C:\Users\wangpeng\Desktop\main.cj
${name} 会原样显示,\n 也不会换行

写 Windows 路径、正则、带特殊符号的文本时,优先想到 #"..."#

3.3 多行字符串:三个引号写一段

需要保留换行的大段文字(SQL、模板、诗),用三个双引号 """ 包裹,中间可以直接换行,也同样支持 ${} 插值:

package helloCangjie

main(): Int64 {
    let who = "李白"
    let poem = """
${who}·静夜思
床前明月光,
疑是地上霜。
"""
    println("------")
    print(poem)
    println("------")
    return 0
}

运行结果:

------
李白·静夜思
床前明月光,
疑是地上霜。

------

⚠️ 注意一个实测出来的细节:多行字符串原样保留一切字符,包括每行开头的空格缩进。所以示例里文字故意顶格写(不跟着代码缩进),否则输出里会带上前面的一串空格;结尾换行也会保留("疑是地上霜。"后面那个空行就是这么来的)。


四、字节与字符:UTF-8 的两个"反直觉"

仓颉字符串内部按 UTF-8 编码存储。UTF-8 是一种变长编码:

  • 英文、数字、常用符号:1 个字节存一个字符;
  • 汉字:3 个字节存一个字符;
  • 个别 emoji 甚至要 4 个字节。

这带来两个初学者必踩的坑。

4.1 坑一:size 量的是字节数,不是字数

package helloCangjie

main(): Int64 {
    let en = "abc"
    let cn = "仓颉语言"
    println("${en} 的 size = ${en.size}")
    println("${cn} 的 size = ${cn.size}")
    println("${cn} 的字数 = ${cn.toRuneArray().size}")
    return 0
}

运行结果:

abc 的 size = 3
仓颉语言 的 size = 12
仓颉语言 的字数 = 4

"仓颉语言" 只有 4 个字,size 却是 12(4 × 3 字节)。想得到"人眼看到的字数",先调用 toRuneArray() 转成字符数组再取 size

4.2 坑二:for-in 遍历字符串得到的是字节

更意外的是,直接 for-in 一个字符串,循环变量不是字符,而是一个个字节(UInt8,数字)

package helloCangjie

main(): Int64 {
    let cn = "仓颉语言"
    print("直接 for-in:")
    for (b in cn) {
        print("${b} ")
    }
    println()

    print("调用 runes():")
    for (ch in cn.runes()) {
        print("${ch} ")
    }
    println()
    return 0
}

运行结果:

直接 for-in:228 187 147 233 162 137 232 175 173 232 168 128
调用 runes():仓 颉 语 言

前三个数字 228 187 147 正是"仓"字 UTF-8 编码的三个字节(十六进制 E4 BB 93)。想逐个人们认识的字符遍历,调用字符串的 runes() 方法

4.3 Rune:单个字符的类型

仓颉用 Rune 类型表示一个 Unicode 字符,字面量写法是 r'字符'(小写 r 加单引号)。它配合 std.unicode 包还能判断字符种类:

package helloCangjie

import std.unicode.*

main(): Int64 {
    let a = r'A'
    let five = r'5'
    let zhong = r'中'
    println("${a} 是字母吗:${a.isLetter()}")
    println("${five} 是数字吗:${five.isNumber()}")
    println("${zhong} 是字母吗:${zhong.isLetter()}")
    return 0
}

运行结果:

A 是字母吗:true
5 是数字吗:true
中 是字母吗:true

(汉字在 Unicode 分类里属于字母,所以 r'中'.isLetter()trueisLetter()isNumber() 等是 std.unicode 包给 Rune 提供的扩展,记得 import。)

把本节串起来:

需求写法说明
字节长度s.size英文 1 字节,汉字 3 字节
字数s.toRuneArray().size一个 Rune 对应一个人眼字符
逐字节遍历for (b in s)得到 UInt8
逐字符遍历for (ch in s.runes())得到 Rune
取第 i 个字符s.toRuneArray()[i]安全,不受变长编码影响

五、切片:从字符串里取出一段

字符串支持第 5 课学过的区间下标,切一刀取出子串

package helloCangjie

main(): Int64 {
    let s = "HelloCangjie"
    println(s[0..5])      // 左闭右开:下标 0~4
    println(s[5..=10])    // 左闭右闭:下标 5~10
    return 0
}

运行结果:

Hello
Cangji

注意:切片下标同样是字节下标,从 0 开始。纯英文文本每个字符 1 字节,下标和"第几个字母"完全对得上,放心切。

但切中文时必须守住 3 字节边界——每个汉字正好占 3 个字节,按 3 的倍数切才安全:

package helloCangjie

main(): Int64 {
    let cn = "仓颉语言"
    println(cn[0..3])     // 0~2 字节,正好是"仓"
    println(cn[0..=5])    // 0~5 字节,正好是"仓颉"
    return 0
}

运行结果:

仓
仓颉

⚠️ 如果下标切到一个汉字的中间(比如对 "仓颉"[0..1]),程序能编译通过,但运行时会抛出异常:

An exception has occurred:
IllegalArgumentException: Invalid utf8 byte sequence.

所以处理含中文的文本,最稳妥的办法是先转字符数组再操作,最后还能用 String(字符数组) 拼回字符串:

package helloCangjie

main(): Int64 {
    let cn = "仓颉语言"
    let runes = cn.toRuneArray()
    println("第 1 个字:${runes[0]}")
    println("第 4 个字:${runes[3]}")

    // 取出"颉语"两个字,再组回字符串
    let part = String(runes[1..3])
    println("取出的部分:${part}")
    return 0
}

运行结果:

第 1 个字:仓
第 4 个字:言
取出的部分:颉语

runes[1..3] 是数组切片,第 7 课学数组时还会再见;这里先记住"字符数组可以放心按下标语义操作"。)


六、常用字符串方法全家桶

标准库给 String 准备了一批高频方法,先跑一段总览,再逐个解释:

package helloCangjie

import std.unicode.*

main(): Int64 {
    let s = "Hello,Cangjie"

    // ① 判断类:包含 / 开头 / 结尾 / 计数
    println("包含 Cang:${s.contains("Cang")}")
    println("以 Hello 开头:${s.startsWith("Hello")}")
    println("以 jie 结尾:${s.endsWith("jie")}")
    println("字母 l 出现次数:${s.count("l")}")

    // ② 查找位置:找不到返回 None(第 9 课讲 Option)
    println("第一个 l 的位置:${s.indexOf("l")}")
    println("最后一个 l 的位置:${s.lastIndexOf("l")}")
    println("xyz 的位置:${s.indexOf("xyz")}")

    // ③ 切分与连接
    let fruits = "apple,banana,orange".split(",")
    println("切出 ${fruits.size} 段,第二段是 ${fruits[1]}")
    println(String.join(fruits, delimiter: " | "))

    // ④ 替换
    println(s.replace("Cangjie", "仓颉"))

    // ⑤ 英文大小写转换(只影响 ASCII 字母)
    println("cangjie".toAsciiUpper())
    println("CANGJIE".toAsciiLower())

    // ⑥ 去首尾空白(trim 系列是 std.unicode 的扩展)
    let padded = "  hello cangjie  "
    println("[${padded.trim()}]")
    return 0
}

运行结果:

包含 Cang:true
以 Hello 开头:true
以 jie 结尾:true
字母 l 出现次数:2
第一个 l 的位置:Some(2)
最后一个 l 的位置:Some(3)
xyz 的位置:None
切出 3 段,第二段是 banana
apple | banana | orange
Hello,仓颉
CANGJIE
cangjie
[hello cangjie]

逐个解释:

  • 判断三件套contains(是否包含子串)、startsWith / endsWith(前缀后缀),返回 Bool,最适合放在 if 条件里;
  • count("l"):数子串出现了几次(这里 l 在 Hello 里出现 2 次);
  • indexOf / lastIndexOf:返回子串第一次/最后一次出现的字节下标。结果长得有点怪:找到是 Some(2),找不到是 None——它是第 9 课要学的 Option 可选值,现阶段只要记住"判断有没有用 contains,要位置才用 indexOf,看到 None 就是没找到";
  • split(","):按分隔符切成字符串数组(Array<String>,第 7 课细讲);String.join(数组, delimiter: " | ") 反过来用指定分隔符拼回一句——注意 join 是 String 的静态方法,分隔符是命名参数 delimiter:
  • replace(旧, 新):把所有旧子串替换成新的,返回新字符串;
  • toAsciiUpper() / toAsciiLower():只转换英文字母(名字带 Ascii 就是提醒你它不管汉字);
  • trim():去掉首尾的空格、Tab、换行等空白,处理用户输入的利器;只想去一头用 trimStart() / trimEnd()。这三个是 std.unicode 包的扩展函数,必须 import std.unicode.*,否则编译器会报 'trim' is not a member of struct 'String'

七、StringBuilder:循环拼接的正确姿势

因为 String 不可变,下面这种循环里用 += 拼字符串的写法,每拼一次都会造一个全新字符串、把旧内容整体复制一遍,数据量大时很浪费:

package helloCangjie

main(): Int64 {
    // 能跑,但循环次数很多时效率低(每次 += 都在复制旧内容)
    var s = ""
    for (i in 1..=5) {
        s += "${i}"
    }
    println("朴素拼接:${s}")
    return 0
}

运行结果:

朴素拼接:12345

更好的工具是 StringBuilder(字符串构建器,在核心包 std.core 里,无需 import):它内部维护一块可增长的缓冲区,append 不断往里追加,最后 toString() 一次性取出:

package helloCangjie

main(): Int64 {
    let sb = StringBuilder()
    for (i in 1..=5) {
        sb.append(i)
        if (i < 5) {
            sb.append(", ")    // 数字之间加分隔符,最后一个不加分号
        }
    }
    let result = sb.toString()
    println(result)
    return 0
}

运行结果:

1, 2, 3, 4, 5

经验法则:偶尔拼一两句,用插值或 +;在循环里成百上千次追加,用 StringBuilder。 append 不挑类型——字符串、数字、Rune 都能直接塞进去,它会自动转成文本。


八、CIDE 实操:英文句子分析器(综合实战)

综合本课知识:让用户输入一句英文,程序自动完成去空白、统计长度/字数、大小写转换、关键词判断、切词编号、查找替换等一整套分析。

8.1 编写程序

继续使用 helloCangjie 项目,把 src/main.cj 替换为:

package helloCangjie

import std.env.*
import std.unicode.*

main(): Int64 {
    print("请输入一句英文:")
    let raw = getStdIn().readln().getOrThrow()
    let sentence = raw.trim()

    println("------ 句子分析报告 ------")
    println("去掉首尾空白后:[${sentence}]")
    println("字节长度:${sentence.size}")
    println("字符个数:${sentence.toRuneArray().size}")
    println("全大写:${sentence.toAsciiUpper()}")

    // 不区分大小写判断是否包含 cangjie:先统一转小写再 contains
    if (sentence.toAsciiLower().contains("cangjie")) {
        println("关键词检查:这句话里提到了 cangjie ✅")
    } else {
        println("关键词检查:没有提到 cangjie")
    }

    // 按空格切词,逐个编号并统计每个词的字节长度
    let words = sentence.split(" ")
    println("单词数:${words.size}")
    for ((index, word) in words.enumerate()) {
        println("  第 ${index + 1} 个词:${word}(${word.size} 个字节)")
    }

    // 查找、连接与替换
    println("第一个字母 o 的位置:${sentence.indexOf("o")}")
    println("下划线连接:${String.join(words, delimiter: "_")}")
    println("字母 o 替换成 0:${sentence.replace("o", "0")}")
    return 0
}

几个设计要点:

  • trim() 给输入"洗澡":用户输入时手抖多敲的首尾空格不参与分析,rawsentence 分开保存看得最清楚;
  • 大小写不敏感的判断技巧:先 toAsciiLower() 整体转小写,再 contains("cangjie"),这样 CangjieCANGJIE 都能命中;
  • enumerate():遍历数组时同时拿到"下标 + 元素",编号输出时不用自己维护计数器(第 7 课还会用);
  • indexOf 只用于展示位置:真正判断有没有出现用的是上面的 contains

8.2 运行与验证

Ctrl + R 运行,输入 I love Cangjie (故意在首尾多敲几个空格):

请输入一句英文:  I love Cangjie  
------ 句子分析报告 ------
去掉首尾空白后:[I love Cangjie]
字节长度:14
字符个数:14
全大写:I LOVE CANGJIE
关键词检查:这句话里提到了 cangjie ✅
单词数:3
  第 1 个词:I(1 个字节)
  第 2 个词:love(4 个字节)
  第 3 个词:Cangjie(7 个字节)
第一个字母 o 的位置:Some(3)
下划线连接:I_love_Cangjie
字母 o 替换成 0:I l0ve Cangjie

可以自己再换几句试试:

  • 输入全中文的句子,观察"字节长度"和"字符个数"的差距(一个汉字 3 字节);
  • 输入不带任何空格的 hello,单词数应为 1;
  • 输入不含字母 o 的句子,最后一行位置会显示 None,替换行原文不变。

📸 配图建议:Result 面板完整显示句子分析报告的运行截图,能看到 enumerate 编号列表和 Some(3)。

8.3 用调试器观察字符串的"不可变"

字符串方法都返回新串、不改原串,这个特性在调试器里一目了然:

  1. let words = sentence.split(" ") 一行打断点;
  2. Shift + F9 启动调试,控制台输入 I love Cangjie 后回车;
  3. 断住后在 Variables 面板对比 raw(带空格)和 sentence(trim 后的新串)——raw 里的空格仍然还在,证明 trim() 没有修改原值;
  4. 单步(F8)越过 split,展开 words 数组,能看到切出来的 3 个字符串元素和它们的下标;
  5. 再单步观察 toAsciiLower()replace() 的结果:每一步都产生了新字符串,而 sentence 从头到尾没变。

📸 配图建议:断点命中时 Variables 面板中 raw 带空格、sentence 不带空格、words 含 3 个元素的截图。

调试结束点停止按钮。


九、常见问题 FAQ

Q1:为什么 "仓颉语言".size 是 12 而不是 4?
size 返回的是 UTF-8 字节长度,汉字一个字占 3 个字节。想要字数,用 s.toRuneArray().size

Q2:for (c in "仓颉") 为什么打印出 228、187 这种数字?
直接 for-in 字符串遍历的是字节(UInt8),228 187 147 正是"仓"字的三个 UTF-8 字节。想逐字符遍历用 for (ch in s.runes()),或 s.toRuneArray()

Q3:切字符串报 IllegalArgumentException: Invalid utf8 byte sequence 是怎么回事?
切片下标是字节下标,切中文时把一个汉字(3 字节)从中间切断了,产生了不合法的 UTF-8 数据。处理中文请先 toRuneArray() 转成字符数组再按字符下标操作,需要字符串时用 String(数组) 拼回。

Q4:调用 trim() 编译报错"not a member of struct ‘String’"?
trim() / trimStart() / trimEnd()std.unicode 包提供的扩展函数,文件开头加 import std.unicode.* 即可。containssplit 等则是 String 自带的,不用 import。

Q5:Windows 路径里的反斜杠一定要写两遍吗?
普通字符串里 \\ 才表示一个反斜杠;更省心的办法是用 raw 字符串 #"C:\Users\name\a.cj"#,里面所有字符原样保留,连 ${} 都不会被插值。

Q6:indexOf 返回的 Some(3)None 是什么?能直接当数字用吗?
它是 Option 可选值(第 9 课详解):找到时 Some(字节下标),找不到时 None。入门阶段只要知道"看到 None 就是没找到";只想判断"有没有",直接用返回 Bool 的 contains 更方便。

Q7:循环里用 += 拼字符串不行吗?
能跑,但 String 不可变,每次 += 都会复制整个旧字符串,循环次数多了很慢。少量拼接用插值;循环里大量追加请用 StringBuilderappend + toString

Q8:怎么把数字变成字符串、字符串变成数字?
数字转字符串:插值 "${n}"n.toString();字符串转数字:Int64.parse(text)(需 import std.convert.*),文本不是合法数字时会抛出异常,第 10 课错误处理会讲怎么优雅地接住它。


十、课后练习

  1. 让用户输入自己的名字(可能是中文),输出一句问候,并分别打印名字的字节长度字符个数。提示:sizetoRuneArray().size 对比着看;中文名"王鹏"应是 6 个字节、2 个字。
  2. 给定字符串 let s = "Cangjie is a modern language",输出:单词个数(split(" "))、字母 a 出现次数(count("a"))、是否以 Cangjie 开头、整句的全大写形式。
  3. "=" * 30 打印一条 30 个等号的分隔线;再把 "2026-09-15""-" 切开,输出"年:2026,月:09,日:15"。
  4. StringBuilder 在循环中拼出 1, 2, 3, ..., 10(要求最后一个数字后面没有多余逗号),对比直接用 += 的写法,思考如果循环到 10000 次差别在哪。
  5. 打开 8.1 的程序 Shift + F9 调试,在 split 一行打断点,输入 I love Cangjie,在 Variables 面板确认 raw 带空格而 sentence 不带;单步观察 words 数组的 3 个元素,以及 replace("o", "0") 执行后 sentence 本身有没有变化(答案应该是没有)。

下节预告

这节课我们学会了处理"一段文本",但程序里经常要处理的是一排数据:一个班 50 个同学的成绩、购物车里的多件商品。第 7 课学习 数组 Array 与区间 Range——把同类型的数据整齐地装进一个容器,按下标存取、整体遍历、切片,还会正式认识这节课反复出现的 split(" ") 到底切出了什么。我们下节课见!


系列说明:本系列基于 Windows 平台 + CIDE + 仓颉 SDK(1.1.3)编写,所有代码均已实际编译运行通过。如遇 SDK 版本差异导致的细节出入,以你本地版本为准,欢迎评论区交流。


� 遇到问题?扫码联系作者

跟着课程练习时,如果在 SDK 安装、环境变量配置、编译报错或调试上卡住,欢迎扫码加作者企业微信直接咨询(请备注"仓颉课程"):

扫码加企业微信联系 CIDE 作者

离线环境下图片可能加载不出来,也可以在 CIDE 菜单 Help ▸ 联系作者 / Contact 中查看同一张二维码(应用内置兜底图,无需联网)。


�📥 工具下载

本系列全程使用的仓颉 IDE —— CIDE(免费开源、社区版):

Logo

一站式 AI 云服务平台

更多推荐