云计算百科
云计算领域专业知识百科平台

【仓颉语言入门 · 第6课】

【仓颉语言入门 · 第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~20 struct/class、构造与属性、接口、枚举与 match 模式匹配、泛型、扩展
五、工程化与标准库 21~25 cjpm 包管理与多文件、文件 IO、JSON 处理、网络编程、单元测试
六、并发编程 26~28 线程、Channel 通道与同步原语、并发实战
七、项目实战 29~30 命令行小工具、GeoJSON 数据处理实战
  • 环境搭建与第一个仓颉程序
  • 变量与常量:let / var 与基本数据类型
  • 运算符与标准输入输出
  • 分支结构:if 与 match 表达式
  • 循环结构:while / for / Range
  • 字符串详解与字符串插值(本文)
  • 数组 Array 与区间 Range
  • 集合框架:ArrayList、HashMap、HashSet
  • 可空类型 ? 与 Option
  • 错误处理:异常机制与 Result
  • 函数定义、参数与返回值
  • Lambda 与高阶函数
  • 闭包、作用域与函数类型
  • 迭代器 Iterator 与 Sequence
  • 结构体 struct 与类 class
  • 构造函数、属性与方法
  • 接口 interface 与实现
  • 枚举 enum、代数数据类型与 match 模式匹配
  • 泛型编程
  • 扩展、类型别名与可见性控制
  • cjpm 包管理与多文件项目组织
  • 文件与目录 IO
  • JSON 处理(结合 stdx 扩展库)
  • 网络编程入门
  • 单元测试
  • 并发基础:线程的创建与等待
  • Channel 通道与同步原语
  • 并发实战:多线程任务处理
  • 实战一:带文件持久化的命令行小工具
  • 实战二: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} 都是它。记住三个要点:

  • 花括号不能省:是 ${name} 不是 $name;
  • 花括号里是完整表达式:变量、四则运算、方法调用、比较运算都可以;
  • 自动转字符串:数字、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() 是 true。isLetter()、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() 给输入"洗澡":用户输入时手抖多敲的首尾空格不参与分析,raw 和 sentence 分开保存看得最清楚;
    • 大小写不敏感的判断技巧:先 toAsciiLower() 整体转小写,再 contains("cangjie"),这样 Cangjie、CANGJIE 都能命中;
    • 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 用调试器观察字符串的"不可变"

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

  • 在 let words = sentence.split(" ") 一行打断点;
  • Shift + F9 启动调试,控制台输入 I love Cangjie 后回车;
  • 断住后在 Variables 面板对比 raw(带空格)和 sentence(trim 后的新串)——raw 里的空格仍然还在,证明 trim() 没有修改原值;
  • 单步(F8)越过 split,展开 words 数组,能看到切出来的 3 个字符串元素和它们的下标;
  • 再单步观察 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.* 即可。contains、split 等则是 String 自带的,不用 import。

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

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

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

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


    十、课后练习

  • 让用户输入自己的名字(可能是中文),输出一句问候,并分别打印名字的字节长度和字符个数。提示:size 与 toRuneArray().size 对比着看;中文名"王鹏"应是 6 个字节、2 个字。
  • 给定字符串 let s = "Cangjie is a modern language",输出:单词个数(split(" "))、字母 a 出现次数(count("a"))、是否以 Cangjie 开头、整句的全大写形式。
  • 用 "=" * 30 打印一条 30 个等号的分隔线;再把 "2026-09-15" 按 "-" 切开,输出"年:2026,月:09,日:15"。
  • 用 StringBuilder 在循环中拼出 1, 2, 3, …, 10(要求最后一个数字后面没有多余逗号),对比直接用 += 的写法,思考如果循环到 10000 次差别在哪。
  • 打开 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(免费开源、社区版):

    • GitCode 仓库 / 安装包下载:https://gitcode.com/wp_upala/cide
    • 打开页面后进入 发行版(Releases),下载 CIDE-<版本>-x64-Setup.exe 安装即可
    • 仓颉 SDK 请前往仓颉编程语言官网下载:https://cangjie-lang.cn
    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 【仓颉语言入门 · 第6课】
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!