浙江传媒学院 · 仓颉面向对象程序设计 · 基于 CangStream 框架构建
浙江传媒学院 · 仓颉面向对象程序设计 · 基于 CangStream 框架构建
struct 关键字定义结构体,两个 let 字段 x/y,自定义 init 构造,按值输出坐标。
package demo
struct Point {
let x: Int64
let y: Int64
public init(a:Int64,b:Int64) {
x=a
y=b
}
}
main(): Int64 {
var a=Point(5,10)
println(" 点p的坐标为:(${a.x},${a.y})")
return 0
}
在 struct Point 中添加 distance 成员函数,调用 sqrt 计算两点欧氏距离。
package demo
import std.math.*
struct Point {
let x: Int64
let y: Int64
init(x: Int64, y: Int64) {
this.x = x
this.y = y
}
func distance(topoint: Point):Float64 {
let dx=Float64(x - topoint.x)
let dy=Float64( y - topoint.y)
return Float64(sqrt(dx*dx+dy*dy)) // 计算两点间的距离
}
}
main(): Int64 {
var a =Point(10,20)
var b =Point(100,200)
let dis=Int64(a.distance(b))
println(" 点a的坐标是:(${a.x},${a.y})")
println(" 点b的坐标是:(${b.x},${b.y})")
println(" ab两点之间的距离是:${dis}")
return 0
}
static var 成员配合 static init 块实现实例计数器,每次构造自动递增。
package demo
import std.math.*
struct Point {
var x: Int64
var y: Int64
static var n:Int64
static init(){
n=0
}
init(x: Int64, y: Int64) {
this.x = x
this.y = y
n++
}
func distance(topoint: Point):Float64 {
let dx=Float64(x - topoint.x)
let dy=Float64( y - topoint.y)
return Float64(sqrt(dx*dx+dy*dy)) // 计算两点间的欧几里得距离
}
}
main(): Int64 {
var a =Point(10,20)
println(" 第${Point.n}个点的坐标是:(${a.x},${a.y})")
var b =Point(100,200)
println(" 第${Point.n}个点的坐标是:(${b.x},${b.y})")
let dis=Int64(a.distance(b))
println(" 两点之间的距离是:${dis}")
return 0
}
定义 getArea/typeName 成员函数,展示结构体方法的基本定义与调用方式。
package demo
struct Rectangle {
let width: Int64 = 10
let height: Int64 = 20
static let n: Int64 =1
public func getarea() {
return this.width * this.height
}
public static func typeName(): String {
return "矩形"
}
}
main(): Int64 {
var a =Rectangle()
println("这个${Rectangle.typeName()}的面积是:${a.getarea()}")
return 0
}
演示 public 与 internal 访问修饰符在跨包访问时的差异(说明性代码,含两个 package 声明,不可单独运行)。
package demo
struct Rectangle {
public let width: Int64 = 10
let height: Int64 = 20
public func getarea() {
return this.width * this.height
}
public static func typeName(): String {
return "矩形"
}
}
package demo2
import demo.*
main(): Int64 {
var a =Rectangle()
println("这个${Rectangle.typeName()}的面积是:${a.getarea()}")
return 0
}
let 字段只读:用局部变量模拟计数逻辑,演示不可变字段的约束与绕过方式。
package demo
struct Rectangle {
let width: Int64
let height: Int64
static var n: Int64=0
init(x: Int64, y: Int64) {
this.width = x
this.height = y
}
public func getarea() {
return this.width * this.height
}
public static func typeName(): String {
let n=n+1
return " 矩形${n}"
}
}
main(): Int64 {
var a =Rectangle(10,20)
println("${Rectangle.typeName()}的长是:${a.width}")
println("${Rectangle.typeName()}的宽是:${a.height}")
println("${Rectangle.typeName()}的面积是:${a.getarea()}")
return 0
}
var 字段可变:直接通过实例访问 width/height 字段并修改其值。
package demo
struct Rectangle {
var width: Int64
var height: Int64
static var n: Int64=0
init(x: Int64, y: Int64) {
this.width = x
this.height = y
}
public func getarea() {
return this.width * this.height
}
public static func typeName(): String {
n=n+1
return " 矩形${n}"
}
}
main(): Int64 {
var a =Rectangle(10,20)
println("${Rectangle.typeName()}的面积是:${a.getarea()}")
a.width=20
a.height=30
println("${Rectangle.typeName()}的面积是:${a.getarea()}")
return 0
}
struct 是值类型:赋值后修改副本不影响原始实例,展示值语义的复制行为。
package demo
struct Rectangle {
var width: Int64
var height: Int64
static var n: Int64=0
init(x: Int64, y: Int64) {
this.width = x
this.height = y
}
public func getarea() {
return this.width * this.height
}
public static func typeName(): String {
n=n+1
return " 矩形${n}"
}
}
main(): Int64 {
var a =Rectangle(10,20)
println("${Rectangle.typeName()}的面积是:${a.getarea()}")
var b=a
b.width=20
b.height=30
println("${Rectangle.typeName()}的面积是:${a.getarea()}")
return 0
}
只有声明为 mut 的函数才能修改 struct 实例的 var 字段,普通成员函数不可写。
package demo
struct Rectangle {
var width: Int64
var height: Int64
var n: Int64=0
init(x: Int64, y: Int64) {
this.width = x
this.height = y
}
public func getarea() {
return this.width * this.height
}
public mut func typeName(): String {
n=n+1
return " 矩形${n}"
}
}
main(): Int64 {
var a =Rectangle(10,20)
println("${a.typeName()}的面积是:${a.getarea()}")
return 0
}
Up/Down/Left/Right 四个带 UInt64 参数的构造器,match 解构后输出对应方向描述。
package demo
enum Direction {
Up(UInt64)|Down(UInt64)|Left(UInt64)|Right(UInt64)
}
main() {
let dir1=Direction.Up(100)
let dir2=Direction.Down(80)
let dir3=Direction.Left(200)
let dir4=Direction.Right(300)
printDirection(dir1)
printDirection(dir2)
printDirection(dir3)
printDirection(dir4)
}
func printDirection(dir:Direction) {
match (dir) {
case Up(a) => println("向上移动:${a}个像素")
case Down(b) => println("向下移动:${b}个像素")
case Left(c) => println("向左移动:${c}个像素")
case Right(d) => println("向右移动:${d}个像素")
}
}
Add/Sub 构造器以 Direction 自身为参数,实现像素移动的递归组合表达。
package demo
enum Direction {
| Up(UInt64)
| Add(Direction, UInt64)
| Sub(Direction, UInt64)
}
func printDirection(dir: Direction) {
match (dir) {
case Direction.Up(a) => println("向上移动: " + a.toString() + " 个像素")
case Direction.Add(_, b) => println("在此基础上向上移动: " + b.toString() + " 个像素")
case Direction.Sub(_, c) => println("在此基础上向下移动: " + c.toString() + " 个像素")
}
}
main(): Int64 {
let dir1 = Direction.Up(100)
let dir2 = Direction.Add(dir1, 80)
let dir3 = Direction.Sub(dir2, 20)
printDirection(dir1)
printDirection(dir2)
printDirection(dir3)
return 0
}
自定义 Option
package demo
enum Option<T> {
|Some(T)
|None
}
main() {
let someValue1: Option<Int64> = Some(100)// 代表有一个值 100
printOption(someValue1)
}
func printOption(opt: Option<Int>) {
match (opt) {
case Some(value) => println("这个值是: ${value}")
case None => println("没有值")
}
}
查找函数返回 Option
package demo
enum Option<T> {
|Some(T)
|None
}
main() {
let someValue1: Option<String> = Some("向前移动50个像素")
let someValue2: Option<String> = None
printOption(someValue1)
printOption(someValue2)
}
func printOption(opt: Option<String>) {
match (opt) {
case Some(value) => println(value)
case None => println("位置没有变化")
}
}
case 0 | 10 | 20 => 多值合并为一个分支,按笔画数对汉字结构进行分类。
package demo
func get(sort: Int64) {
match(sort) {
case 0 | 10 | 20 | 30 => "横"
case 88 | 99 | 90 | 91 | 92 => "竖"
case 130 | 135 => "撇"
case 280 | 285 => "捺"
case _ => "不能判定"
} }
main() {
let result = get(90)
println("这个笔画是${result}.")
}
Rune 字面量 r'横' 作为模式,匹配笔画名称并返回对应的笔画编号。
package demo
func translate(n: Rune) {
match (n) {
case "横" => 1
case "竖" => 2
case "撇" => 3
case "捺" => 4
case _ => -1
} }
main() {
println(translate(r"撇") )
}
用 b'0'~b'9' 的 Byte 常量模式匹配字符,将 ASCII 字符转换为对应数字值。
package demo
func translate(n: Byte): Int64 {
match (n) {
case 49 => return 1 // '1'
case 50 => return 2 // '2'
case 51 => return 3 // '3'
case 52 => return 4 // '4'
case _ => return -1
}
}
main(): Int64 {
println(translate(50)) // 传入 ASCII 50,即 '2'
println(UInt32(50)) // 输出 50
return 0
}
case n => 作为兜底分支捕获所有未匹配整数,绑定到变量 n 并直接输出其值。
package demo
func get(s: Int64) {
match(s) {
case 1 => "壹"
case 0 => "零"
case n => "x 不是零和壹,而是 x = ${n}"
}
}
main() {
let x= get(4)
println("${x}")
}
case _ => 通配符匹配 Direction 中未逐一列举的分支,不绑定变量,统一处理。
package demo
enum Direction {
Up|Down|Left|Right
}
main() {
let x =Up
let y = match (x) {
case Left => "向左走"
case Right => "向右走"
case _ => "不确定"
}
println(y)
}
case ("王", snum) => 解构 (String, Int64) 二元组,同时匹配字符与绑定笔画数。
package demo
main() {
let tv = ("王", 4)
let s = match (tv) {
case ("主", snum) => "主由${snum}个笔画组成"
case ("王", snum) => "王由${snum}个笔画组成"
case (_, _) => "没法确定"
}
println(s)
}
Year(n) / Month(n) 构造器解构,提取内部值分别计算年与月的换算关系。
package demo
enum TimeUnit {
| Year(UInt64)
| Month(UInt64)
}
main() {
let x = Year(2)
let s = match (x) {
case Year(n) => "${n}年是${n * 12}个月" // Matched.
case Month(n) => "${n}个月不一定是${n*30}天"
}
println(s)
}
Command 构造器内嵌 TimeUnit,展示多层 enum 嵌套解构的写法。
package demo
enum TimeUnit {
| Year(UInt64)
| Month(UInt64)
}
enum Command {
| SetTimeUnit(TimeUnit)
| GetTimeUnit
| Quit
}
main() {
let command = (SetTimeUnit(Year(2022)), SetTimeUnit(Year(2024)))
match (command) {
case(SetTimeUnit(Year(year)), _)=> println("设定年份是${year}")
case(_,SetTimeUnit(Month(month)))=>println("设定月份是${month}")
case _ => ()
}
}
constPat 函数演示可反驳模式(refutable pattern):并非所有值都能匹配成功。
package demo
// 定义常量模式匹配函数
func constPat(x: Int64) {
let result = match (x) {
case 1 => "one"
case 2 => "two"
case _ => "_"
}
println(result)
}
main() {
// 调用常量模式匹配函数
constPat(1) // 输出 "one"
constPat(2) // 输出 "two"
constPat(3) // 输出 "_"
}
let Some(x) = ... 直接在 let 绑定中解构 Option,无需显式 match 语句。
package demo
// 定义 Option 枚举类型
enum Option<T> {
| Some(T)
| None
}
// 定义匹配 Option 的函数
func matchOption(opt: Option<Int64>) {
let result = match (opt) {
case Some(x) => "Some value: ${x}"
case None => "No value"
}
println(result)
}
main() {
// 创建一个 Option 枚举实例 Some
let optionSome =Option<Int64>.Some(42)
matchOption(optionSome) // 输出 "Some value: 42"
// 创建一个 Option 枚举实例 None
let optionNone =Option<Int64>.None
matchOption(optionNone) // 输出 "No value"
}
match 用作语句而非表达式,按 Direction 方向依次执行各分支并输出移动步数。
package demo
func moveto(x: Int64) {
match (x) {
case 0 =>let m1 ="未移动"
println(m1)
case 1 =>let m2 ="向前移动1步"
println(m2)
case 2 =>let m3 ="向前移动2步"
println(m3)
case 3 =>let m4 ="向前移动3步"
println(m4) // Matched
case _ => println("移动步数超出范围")
}
}
main() {
let steps = 3
moveto(steps)
}
Direction.Up(n) 分支追加 where n > 10 条件,满足守卫才匹配,否则落入下一分支。
package demo
enum Direction {
Up(UInt64) |Down(UInt64) |Left(UInt64) |Right(UInt64)
}
func moveto(x:Direction) {
match (x) {
case Direction.Up(x) where x<100 =>let m1 ="向上移动${x}"
println(m1)
case Direction.Down(x)=>let m2 ="向下移动1步"
println(m2)
case Direction.Left(x) =>let m3 ="向左移动2步"
println(m3)
case Direction.Right(x) =>let m4 ="向右移动3步"
println(m4) // Matched
case _ => println("步数超出范围")
}
}
main() {
let steps=Direction.Up(110)
moveto(steps)
}
省略 match 后的被匹配表达式,各分支直接写布尔条件,可读性优于多层 if-else。
package demo
main() {
let x = -1
match {
case x > 0 => print("x > 0")
case x < 0 => print("x < 0")
case _ => print("x = 0")
}
}
match 作为表达式,按整数范围返回不同分类描述字符串,赋值给变量后输出。
package demo
func processNumber(num: Int64): String {
let result = match(num) {
case 1 => "One"
case 2 => "Two"
case _ => "Other"
}
return result
}
main(): Int64 {
let num = 1
println(processNumber(num))
return 0
}
checkValue 函数内 match 返回 String,函数签名声明返回类型,统一在外层输出。
package demo
func checkValue(x: Int64): String {
let result =match (x) {
case 0 => "x = 0"
case 1 => "x = 1"
case _ => "x != 0 and x != 1"
}
return result
}
main() {
let x = 2
let s = checkValue(x) // 调用 checkValue 函数
println(s) // 输出 "x != 0 and x != 1"
}
各 case 分支直接调用 println,match 整体返回 Unit,无需外层收集返回值。
package demo
func checkValue(num: Int64) {
match(num) {
case 1 => println("One")
case 2 => println("Two")
case _ => println("Other")
}
}
main() {
checkValue(2) // 输出 "Two"
}
对 Direction 的 Up/Down/Left/Right 四个构造器逐一匹配,输出各方向行走描述。
package demo
enum Direction {
Up(UInt64) |Down(UInt64) |Left(UInt64) |Right(UInt64)
}
func moveto(x:Direction) {
match (x) {
case Direction.Up(x) =>let m1 ="向上移动${x}"
println(m1)
case Direction.Down(x)=>let m2 ="向下移动${x}步"
println(m2)
case Direction.Left(x) =>let m3 ="向左移动${x}步"
println(m3)
case Direction.Right(x) =>let m4 ="向右前移动${x}步"
println(m4) // Matched
case _ => println("移动步数超出范围")
}
}
main() {
let steps1=Direction.Right(100)
let steps2=Direction.Down(100)
let steps3=Direction.Left(100)
let steps4=Direction.Up(100)
moveto(steps1)
moveto(steps2)
moveto(steps3)
moveto(steps4)
}
if let Some(dir) = getCommand() { ... } 解构成功时机器人前进,展示 if-let 的标准写法。
package demo
main() {
let result = Option<Int64>.Some(100)
if (let Some(value) <- result) {
println("控制成功,机器人向前走了${value}步")
}
else {
println("控制失败")
}
}
getCommand() 返回 None 时走 else 分支,输出操作失败提示,演示 if-let 的 else 处理。
package demo
main() {
let result = Option<Int64>.None
if (let Some(value) <- result) {
println("操作成功,返回值为:${value}")
} else {
println("操作失败")
}
}
while let Some(msg) = receive() { ... } 每轮取出消息处理,返回 None 时自动退出循环。
package demo
import std.random.*
func recv(): Option<UInt8> {
let number = Random().nextUInt8()
if (number < 128) {
return Some(number)
}
return None
}
main() {
// 模拟循环接收通信数据,如果失败就结束循环
while (let Some(data) <- recv()) {
println(data)
}
println("接收失败!")
}
for (key, val) in list { ... } 在 for 头部直接解构 (String, Int64) 元组,逐项输出。
package demo
func processTuple(x: Int64, y: Int64) {
println("x = ${x}")
println("y = ${y}")
}
func processTupleSum() {
for ((i, j) in [(1, 2), (3, 4), (5, 6)]) {
println("Sum = ${i + j}")
}
}
main() {
let x = 100
let y = 200
processTuple(x, y) // 调用函数处理 tuple 值
processTupleSum() // 调用函数计算和
}
for Some(x) in optList { ... } 在循环头部直接解构 Some,自动跳过 None 元素。
package demo
enum RedColor {
Red(Int64)
}
main() {
let Red(red) = Red(0) // 定义一个枚举实例并解构赋值
println("red = ${red}")
for (Red(r) in [Red(10), Red(20), Red(30)]) {
println("r = ${r}") // 使用 for-in 循环解构枚举类型并打印
}
}
8 方向 enum Direction(Up/Down/Left/Right/UpLeft/UpRight/DownLeft/DownRight)配合 match 实现全方位移动控制。
package demo
enum Direction {
Up(UInt64) | Down(UInt64) | Left(UInt64) | Right(UInt64) |
UpLeft(UInt64) | UpRight(UInt64) | DownLeft(UInt64) | DownRight(UInt64)
}
main() {
let steps = Direction.Up(10)
match(steps) {
case Direction.Up(x) => println("向上移动${x}步")
case Direction.Down(x) => println("向下移动${x}步")
case Direction.Left(x) => println("向左移动${x}步")
case Direction.Right(x) => println("向右移动${x}步")
case Direction.UpLeft(x) => println("向左上方移动${x}步")
case Direction.UpRight(x) => println("向右上方移动${x}步")
case Direction.DownLeft(x) => println("向左下方移动${x}步")
case Direction.DownRight(x) => println("向右下方移动${x}步")
case _ => println("未知方向")
}
}
定义 5 个 struct Point,依次计算相邻两点距离并累加,输出五点连线的总路径长度。
package demo
import std.math.*
struct Point {
var x: Int64
var y: Int64
static var n: Int64 = 0 // 静态变量 n 初始化为 0
init(x: Int64, y: Int64) {
this.x = x
this.y = y
Point.n++ // 更新静态变量 n
}
func distance(topoint: Point): Float64 {
let dx = Float64(x - topoint.x)
let dy = Float64(y - topoint.y)
return Float64(sqrt(dx * dx + dy * dy))//计算两点间的欧几里得距离
}
}
main(): Int64 {
// 创建5个点
var points = [
Point(0, 0),
Point(1, 1),
Point(2, 3),
Point(4, 5),
Point(7, 8)
]
// 计算连线的总长
var totalDistance: Float64 = 0.0
for (i in 0..(points.size - 1)) {
totalDistance += points[i].distance(points[i + 1])
}
println("五个点之间的连线总长是:${totalDistance}")
return 0
}
Point + Direction + moveTo 组合:按指令序列移动坐标点,输出行走轨迹的文字描述。
package demo
import std.math.*
// 定义结构体 Point 表示坐标
struct Point {
var x: Int64
var y: Int64
init(x: Int64, y: Int64) {
this.x = x
this.y = y
}
}
// 定义方向的枚举
enum Direction {
Up(Int64) | Down(Int64) | Left(Int64) | Right(Int64) |
UpLeft(Int64) | UpRight(Int64) | DownLeft(Int64) | DownRight(Int64)
}
// 定义函数来打印方向和步数
func printDirection(dir: Direction) {
match (dir) {
case Up(a) => println("向上移动: ${a}个像素")
case Down(b) => println("向下移动: ${b}个像素")
case Left(c) => println("向左移动: ${c}个像素")
case Right(d) => println("向右移动: ${d}个像素")
case UpLeft(e) => println("向左上方移动: ${e}个像素")
case UpRight(f) => println("向右上方移动: ${f}个像素")
case DownLeft(g) => println("向左下方移动: ${g}个像素")
case DownRight(h) => println("向右下方移动: ${h}个像素")
}
}
// 计算从起点到终点的移动方案,计算每一步的距离
func moveTo(start: Point, end: Point):Float64 {
var totalDistance: Float64 = 0.0 // 记录总的移动距离
var currentPoint = start
// 向右上方移动:x > 0,y > 0
while (currentPoint.x < end.x && currentPoint.y < end.y) {
printDirection(Direction.UpRight(1)) // 每步1个像素
currentPoint.x += 1
currentPoint.y += 1
totalDistance += Float64(sqrt(1.0 + 1.0)) // 每步的距离:sqrt(1^2 + 1^2) = sqrt(2)
}
// 向右移动:x > 0,y = 0
while (currentPoint.x < end.x) {
printDirection(Direction.Right(1))
currentPoint.x += 1
totalDistance += 1.0 // 每步的距离是1像素
}
// 向上移动:x = 0,y > 0
while (currentPoint.y < end.y) {
printDirection(Direction.Up(1))
currentPoint.y += 1
totalDistance += 1.0 // 每步的距离是1像素
}
return totalDistance
}
// 主程序
main() {
let start = Point(0, 0) // 起点
let end = Point(0, 10) // 终点
println("已经规划好从 (${start.x}, ${start.y})点出发到(${end.x}, ${end.y}) 点的路径:")
println("请从 (${start.x}, ${start.y})点出发:")
let totalDist = moveTo(start, end)
println("到达 (${end.x}, ${end.y}) 终点")
println("从 (${start.x}, ${start.y}) 到 (${end.x}, ${end.y}) 的总距离是:${totalDist}像素")
}
enum Radical 表示汉字部件,enum Character 组合部件,match 统计笔画数并输出结构说明。
// 定义汉字部件的枚举类型
package demo
enum Radical {
氵 | 工| 山| 青 | 阝 | 心 | 人 | 日
}
// 定义组合部件与汉字
enum Character {
清(Radical, Radical) // 氵青
|江(Radical, Radical) // 氵 工
|阳(Radical, Radical) // 阳
}
func printRadical(radical: Radical) {
let leftorright:String= match (radical) {
case 氵=> "氵"
case 青=> "青"
case 阝=> "阳"
case _ => "Null"
}
return leftorright
}
// 打印汉字的函数
func printCharacter(char: Character) {
let hanzi:String= match (char) {
case 清(Radical.氵, Radical.青) => "清"
case 江(Radical.氵, Radical.工) => "江"
case 阳(Radical.阝, Radical.日) => "阳"
case _ => "Null"
}
return hanzi
}
// 主程序
main() {
// 定义部件组合
let left=Radical.氵
let right=Radical.青
let qing = Character. 清(Radical.氵, Radical.青)
println("${printRadical(left)}+${printRadical(right)}=${printCharacter(qing)}")
}
对 Array
package demo
func bubbleSort(array: Array<Int64>): Array<Int64> {
for (i in 0..array.size - 1) {
for (j in 1..array.size - i ) {
if(array[j - 1] > array[j]) {
var temp = array[j - 1]
array[j - 1] = array[j]
array[j] = temp
}
}
}
return array
}
main(): Int64 {
let array = [82,-64,0,-13,-12,-7,-12,-9,-3,-7,1,-6,4,-7,7,-10,7,-11,6,-64,0,-13,-12,-13,13,-13,13,-64,0,-4,-12,13,-12,13,-12,-64,0,10,-12,10,-12,-64,0,10,-12,10,11,9,12,3,12,3,12,-64,0,-2,-6,-2,7,-2,7,-64,0,-2,-5,-2,-5,5,-5,5,4,5,4,-64,0,-1,4,4,4,4,4,-64,-64]
let sortedArray = bubbleSort(array)
println(sortedArray.toString())
return 0
}