琉离铟落的小窝琉离铟落的小窝
← 返回文章列表
2026-06-25
#Cangjie#入门教程

区间类型

仓颉的基本数据类型——区间类型

2.8.1 什么是区间?

区间(Range)用来表示一个有固定步长的数字序列。简单说,就是"从哪开始、到哪结束、一次跳几步"。

💡TIP

你可以把区间想象成爬楼梯——你知道从第几级台阶开始、在第几级停下、一次跨几级。比如"从第 0 级开始,到第 10 级结束,一次跨 1 级",就是区间 0..=10 : 1

最常见的就是整数区间,例如 1 到 5 的整数序列:

Cangjie
let r = 1..=5 : 1   // 包含 1, 2, 3, 4, 5

2.8.2 区间的三个要素

每个区间都有三个核心参数:

参数 名称 含义 示例
start 起始值 序列从哪里开始 0
end 终止值 序列到哪里结束 10
step 步长 每两个元素之间差多少 1(每次+1)、-2(每次-2)
IMPORTANT

step 固定是 Int64 类型,且 不能等于 0。如果步长为 0,程序会报错。


2.8.3 用构造函数创建区间

Range<T> 是仓颉的泛型区间类型。构造函数的完整参数如下:

Cangjie
Range<T>(start: T, end: T, step: Int64, hasStart: Bool, hasEnd: Bool, isClosed: Bool)

后面三个 Bool 参数的含义:

参数 true false
hasStart 包含开始值 不包含开始值
hasEnd 包含结束值 不包含结束值
isClosed 左闭右闭 左闭右开

最常用的组合是 hasStart = true, hasEnd = true,即"既有起始又有终止":

Cangjie
let r1 = Range<Int64>(0, 10, 1, true, true, true)   // 闭区间:0 到 10(包含 10)
                                                     // 结果:0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

let r2 = Range<Int64>(0, 10, 1, true, true, false)  // 开区间:0 到 10(不包含 10)
                                                     // 结果:0, 1, 2, 3, 4, 5, 6, 7, 8, 9

let r3 = Range<Int64>(10, 0, -2, true, true, false)  // 从 10 开始,步长为 -2,到 0(不包含 0)
                                                      // 结果:10, 8, 6, 4, 2                                            
ℹ️NOTE

构造函数参数多、限制也多,日常编码中几乎不用,推荐使用下面介绍的区间字面量,更简洁直观。

IMPORTANT

hasStarthasEndfalse 时,在 for-in无效(效果等同二者均为 true);在与数组下标配合使用时,对应参数失效,改用数组的 0size - 1 替代。

Cangjie
main() {
    // hasEnd = false,在 for-in 中等同 true,范围为 1..=4
    let r4 = Range<Int64>(1, 4, 1, true, false, true)
    println(r4)  // 输出:1 2 3 4

    // 在数组切片中,hasEnd = false 使用 arr.size - 1 作为 end(即 6) 区间搭配数组使用案例请看上一章节
    let arr = [1, 2, 3, 4, 5, 6, 7]
    println(arr[r4])  // 输出:[2, 3, 4, 5, 6, 7]
}

2.8.4 用字面量创建区间(推荐)

仓颉提供了两种简洁的区间写法:

左闭右开区间 `start..end : step`

格式:start..end : step
含义:从 start 开始,到 end 之前(不包含 end)为止。

口诀:.. 看到终点就刹车,不到终点 🛑
Cangjie
let r1 = 0..10 : 1   // 结果:0, 1, 2, 3, 4, 5, 6, 7, 8, 9
                      // 注意:没有 10!

左闭右闭区间 `start..=end : step`

格式:start..=end : step
含义:从 start 开始,到 end 为止(包含 end)。

口诀:..= 一路到终点,刚好赶上 🎯
Cangjie
let n = 10
let r2 = 0..=n : 1    // 结果:0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
                      // 注意:包含 10!

对比一下

字面量 包含起始 包含终止 示例 结果
0..10 : 1 ✅ 包含 0 ❌ 不包含 10 0,1,2,3,4,5,6,7,8,9 共 10 个
0..=10 : 1 ✅ 包含 0 ✅ 包含 10 0,1,2,3,4,5,6,7,8,9,10 共 11 个

步长为负数的情况

步长也可以是负数,这样序列就是从大到小递减:

Cangjie
let r3 = 10..0 : -2     // 从 10 开始,每次减 2,到 0(不包含 0)
                         // 结果:10, 8, 6, 4, 2

let r4 = 10..=0 : -2    // 从 10 开始,每次减 2,到 0(包含 0)
                         // 结果:10, 8, 6, 4, 2, 0
💡TIP

步长为负数时,起始值要大于终止值,这样才有意义。如果 10..0 : 1(步长为正但你从大往小跑),那就是空区间了。


2.8.5 默认步长

步长 step 可以省略,省略时默认等于 1

Cangjie
let r5 = 0..10         // 等价于 0..10 : 1
                        // 结果:0, 1, 2, 3, 4, 5, 6, 7, 8, 9

但是步长不能为 0:

Cangjie
let r6 = 0..10 : 0     // ❌ 报错:step cannot be 0(步长不能为 0)

2.8.6 空区间

有些情况下,区间里一个元素都没有,这就是空区间。什么时候会出现空区间?

口诀:步长方向与大小方向不一致时,就是空的。

Cangjie
// 以下都是空区间(不包含任何元素):

let r7 = 10..0 : 1      // 步长是 +1,但 start=10 > end=0,越走越远
let r8 = 0..10 : -1     // 步长是 -1,但 start=0 < end=10,也越走越远
let r9 = 10..=0 : 1     // 闭区间也一样,方向不对就是空
let r10 = 0..=10 : -1   // 同上,方向反了

空区间的判定规则

区间形式 空区间条件
start..end : step(左闭右开) step > 0start >= end
start..end : step(左闭右开) step < 0start <= end
start..=end : step(左闭右闭) step > 0start > end
start..=end : step(左闭右闭) step < 0start < end
ℹ️NOTE

注意左闭右开和左闭右闭的细微区别:

  • 左闭右开 start..endstart >= end 就空(步长为正时)
  • 左闭右闭 start..=endstart > end 才空(步长为正时),因为 start = end 时至少有一个元素

2.8.7 区间的实际用途

区间最常见的用途是配合 数组切片for 循环

配合数组切片

Cangjie
let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
let slice = arr[0..5]       // 取下标 0 到 4,结果是 [0, 1, 2, 3, 4]
🚨CAUTION

arr[n..]arr[..n] 这类省略起始或结束的切片写法仅限数组等下标访问类型使用,不可用于 for-in 语句。其中 arr[n..] 等价于 arr[n..arr.size]arr[..n] 等价于 arr[0..n]

配合 for 循环

Cangjie
main() {
    for (i in 1..=5) {      // i 依次取 1, 2, 3, 4, 5
        println("第 ${i} 次循环")
    }
}

运行结果:

Bash
第 1 次循环
第 2 次循环
第 3 次循环
第 4 次循环
第 5 次循环
💡TIP

利用区间做循环,比手动写起始和结束条件要清晰得多!


2.8.8 小结

概念 要点
区间的作用 表示一个有固定步长的序列
三个要素 start(起始)、end(终止)、step(步长)
左闭右开 start..end : step,不包含 end
左闭右闭 start..=end : step,包含 end
默认步长 省略 step 时默认为 1
步长不能为 0 否则报错
空区间 步长方向和大小方向不一致时出现

2.8.9 动手试一试 ✏️

  1. 用区间字面量表示 "从 2 到 20 的所有偶数"。
  2. 用区间字面量表示 "从 100 到 0 的所有 10 的倍数"(包含 0)。
  3. 下面的区间分别包含哪些数字?
    • 5..15 : 3
    • 5..=15 : 3
    • 20..10 : -5
    • 20..=10 : -5
  4. 以下哪个区间是空的?为什么?
    • 0..100 : -1
    • 100..0 : -1
    • 5..=5 : 1
点击查看答案

第 1 题:

Cangjie
let even = 2..=20 : 2   // 2, 4, 6, 8, 10, 12, 14, 16, 18, 20

第 2 题:

Cangjie
let tens = 100..=0 : -10   // 100, 90, 80, 70, 60, 50, 40, 30, 20, 10, 0

第 3 题:

区间 包含的数字
5..15 : 3 5, 8, 11, 14(不包含 15)
5..=15 : 3 5, 8, 11, 14(包含 15 但 15 不在序列里,因为 5+3×3=14,下一个是 17 > 15)
20..10 : -5 20, 15, 10(不包含 10?注意左闭右开,不包含 10,所以是 20, 15)
20..=10 : -5 20, 15, 10(包含 10)
ℹ️NOTE

5..=15 : 3 虽然标记为"包含 15",但实际序列是 5, 8, 11, 14。这是否包含 15 看的是"是否在 end 处停止"——14 之后下一个是 17,已经超过 15 了,所以 15 并不在序列中。当 start + k×step 恰好等于 end 时,闭区间才会包含它(如 0..=10 : 1 包含 10)。

第 4 题:

  • 0..100 : -1空区间。步长为负(-1),但起始 0 < 终止 100,方向相反。
  • 100..0 : -1非空。步长为负(-1),起始 100 > 终止 0,方向一致。结果:100, 99, 98, ..., 2, 1(不含 0)。
  • 5..=5 : 1非空。左闭右闭且 start = end,包含一个元素 5。

2.8.10 常见问题

Q1:`0..10` 和 `0..=10` 有什么区别?

0..10 是左闭右开,包含 0 但不包含 10,结果是 0,1,2,...,9(共 10 个)。
0..=10 是左闭右闭,包含 0 和 10,结果是 0,1,2,...,10(共 11 个)。

Q2:step 可以是小数吗?

不可以。step 的类型固定为 Int64,只能是整数。如果你想表示小数的等差数列,需要用其他方式实现。

Q3:空区间有什么实际用途吗?

空区间通常不是有意创建的,而是边界情况。在循环或数组切片中,如果区间是空的,就不会执行任何操作,避免了程序崩溃。例如 arr[5..3] 会返回空数组而不是报错。

Q4:区间和数组有什么区别?

区间描述的是一个规则序列(从哪开始、到哪结束、步长多少),它本身不存储所有元素的值,而是按需计算。而数组是真实存着所有元素的集合。区间更像是一个"生成规则",数组才是"存储容器"。