仓颉基础大揭秘:数据类型的奇妙世界

1 概述

1.1 背景介绍

仓颉编程语言作为一款面向全场景应用开发的现代编程语言,通过现代语言特性的集成、全方位的编译优化和运行时实现、以及开箱即用的 IDE工具链支持,为开发者打造友好开发体验和卓越程序性能。

案例结合代码体验,让大家更直观的了解仓颉语言中的基础数据类型。

1.2 适用对象

  • 个人开发者
  • 高校学生

1.3 案例时间

本案例总时长预计50分钟。

1.4 案例流程

11a0c75e6fc2b97a6b805317f20ea48c.png

说明:

① 进入华为开发者空间,登录云主机;
② 使用CodeArts IDE for Cangjie编程和运行仓颉代码。

1.5 资源总览

资源名称规格单价(元)时长(分钟)
开发者空间 - 云主机鲲鹏通用计算增强型 kc2 | 4vCPUs | 8G | Ubuntu免费50

最新案例动态,请查阅 仓颉基础大揭秘:数据类型的奇妙世界 。小伙伴快来领取华为开发者空间,进入云主机桌面版实操吧!

2 运行测试环境准备

2.1 开发者空间配置

面向广大开发者群体,华为开发者空间提供一个随时访问的“开发桌面云主机”、丰富的“预配置工具集合”和灵活使用的“场景化资源池”,开发者开箱即用,快速体验华为根技术和资源。

领取云主机后可以直接进入华为开发者空间工作台界面,点击进入桌面连接云主机。没有领取在开发者空间根据指引领取配置云主机即可,云主机配置参考1.5资源总览。

2427bdcdb98bfd50840ca130685be10a.PNG

552fc96c3b58a06e294e4a760ae719e3.PNG

2.2 创建仓颉程序

点击桌面CodeArts IDE for Cangjie,打开编辑器,点击新建工程,保持默认配置,点击创建。

产物类型说明:

  • executable,可执行文件;
  • static,静态库,是一组预先编译好的目标文件的集合;
  • dynamic,动态库,是一种在程序运行时才被加载到内存中的库文件,多个程序共享一个动态库副本,而不是像静态库那样每个程序都包含一份完整的副本。

28acbca9146a8a6aacbfdd4f6ac3791b.png

2.3 运行仓颉工程

创建完成后,打开src/main.cj,参考下面代码简单修改后,点击编辑器右上角运行按钮直接运行,终端窗口可以看到打印内容。

package demo
// 第一个仓颉程序
main(): Int64 {
    println("hello world")
    println("你好,仓颉!")
    return 0
}

(* 注意:后续替换main.cj文件代码时,package demo保留,demo为实际创建的项目名称)

(* 仓颉注释语法:// 符号之后写单行注释,也可以在一对 /* 和 */ 符号之间写多行注释)

d1e16b48f5f9620fafe9fc59ae62a367.png

到这里,我们第一个仓颉程序就运行成功啦!后面案例中的示例代码都可以放到main.cj文件中进行执行,接下来我们继续探索仓颉语言。

3 仓颉中的基础数据类型

3.1 整数类型

整数类型分为:有符号整数类型和无符号整数类型。

有符号整数类型包括 Int8、Int16、Int32、Int64 和 IntNative,分别用于表示编码长度为 8-bit、16-bit、32-bit、64-bit 和平台相关大小的有符号整数值的类型。

无符号整数类型包括 UInt8、UInt16、UInt32、UInt64 和 UIntNative,分别用于表示编码长度为 8-bit、16-bit、32-bit、64-bit 和平台相关大小的无符号整数值的类型。

编码长度为 N 的有符号整数类型,其表示范围为:7e2b7f4d83653aa56083f7f1ef0e144c.png

编码长度为 N 的无符号整数类型,其表示范围为:8bc12a8f3d614234383159dc5d670ae6.png
 
举例说明:

Int8:编码长度为8的有符号整数类型,范围为:57ed23d8ad03c1abee01a203c00a7be5.png

UInt16:编码长度为16的无符号整数类型,范围为:730bfaff2bdcec13b5efa4ddb776d932.png

3.1.1 整数类型字面量

整数类型字面量有 4 种进制表示形式:

  • 二进制:使用 0b 或 0B 前缀
  • 八进制:使用0o(小写字母o)或0O(大写字母O)前缀
  • 十进制:没有前缀
  • 十六进制:使用 0x 或 0X 前缀

备注:在各进制表示中,可以使用下划线 _ 充当分隔符的作用,方便识别数值的位数,如 0b0001_1000。

对于整数类型字面量,如果它的值超出了上下文要求的整数类型的表示范围,编译器将会报错。

具体代码操作如下:

Step1:复制以下代码,替换main.cj文件中的main函数。

main():Int64 {
     // Error, 128 out of the range of Int8
    let x: Int8 = 128     
    // Error, 256 out of the range of UInt8 
    let y: UInt8 = 256       
    // Error, 0x8000_0000 out of the range of Int32  
    let z: Int32 = 0x8000_0000 
    return 0
}

Step2:代码复制完成后,编译器直接提示报错。

5de7230f1462a0f3a2eed8ac5270c7d8.PNG

在使用整数类型字面量时,可以通过加入后缀来明确整数字面量的类型,后缀与类型的对应为:

后缀类型后缀类型
i8Int8u8UInt8
i16Int16u16UInt16
i32Int32u32UInt32
i64Int64u64UInt64

加入了后缀的整数字面量可以像下面的方式来使用,具体代码操作如下:

Step1:复制以下代码,替换main.cj文件中的main函数。

main():Int64 {
    // x is 100 with type Int8
    var x = 100i8      
    println("x的值为:${x}")
    // y is 16 with type UInt64
    var y = 0x10u64    
    println("y的值为:${y}")
    // z is 282 with type Int32
    var z = 0o432i32   
    println("z的值为:${z}") 
    return 0
}

Step2:点击编辑器右上角运行按钮直接运行,终端窗口可以看到打印内容。

3f6e39e8476ea8070f16d65d32c3389d.PNG

3.1.2 字符字节字面量

仓颉编程语言支持字符字节字面量,以方便使用 ASCII 码表示 UInt8 类型的值。字符字节字面量由字符 b、一对标识首尾的单引号、以及一个 ASCII 字符组成,具体代码操作如下:

Step1:复制以下代码,替换main.cj文件中的main函数。

main():Int64 {
    // a is 120 with type UInt8
    var a = b'x' 
    println("a的值为:${a}") 
    // b is 10 with type UInt8
    var b = b'\n' 
    println("b的值为:${b}") 
    // c is 120 with type UInt8
    var c = b'\u{78}' 
    println("c的值为:${c}") 
    return 0
}

Step2:点击编辑器右上角运行按钮直接运行,终端窗口可以看到打印内容。

535a13f2ee6ecb274792d3b91bc9c5ee.PNG

3.1.3 整数类型支持的操作

整数类型默认支持的操作符包括:算术操作符、位操作符、关系操作符、自增和自减操作符、赋值操作符、复合赋值操作符。

算术操作符:

一元负号(-)、加法(+)、减法(-)、乘法(*)、除法(/)、取模(%)、幂运算(**)。具体代码操作如下:

Step1:复制以下代码,替换main.cj文件中的main函数。

main():Int64 {
    // 负号
    let p0 = -10
    println("负号:p0=${p0}")
    // 加法
    let p1 = 10 + 5
    println("加法运算:p1=${p1}")
    // 减法
    let p2 = 10 - 5
    println("减法运算:p2=${p2}")
    // 乘法
    let p3 = 10 * 5
    println("乘法运算:p3=${p3}")
    // 除法
    let p4 = 10 / 5
    println("除法运算:p4=${p4}")
    // 取模
    let p5 = 10 % 5
    println("取模运算:p5=${p5}")
    // 幂运算
    let p6 = 10 ** 2
    println("幂运算:p6=${p6}")
    return 0
}

Step2:点击编辑器右上角运行按钮直接运行,终端窗口可以看到打印内容。

21e58a12eb8620c93981fa5d502055d3.PNG

位操作符:

按位求反(!)、左移(<<)、右移(>>)、按位与(&)、按位异或(^)、按位或(|)。注意,按位与、按位异或和按位或操作符要求左右操作数是相同的整数类型。

具体代码操作如下:

Step1:复制以下代码,替换main.cj文件中的main函数。

main():Int64 {
    let p3 = 3
    let p2 =2
    // 取反!
    let b = true
    println("取反操作:b=${!b}")
    // 左移(<<)
    let p4 = p3 << 1
    println("左移:p4 = ${p4}")
    //右移(>>)
    let p5 = p3 >> 1
    println("右移:p5 = ${p5}")
    //按位与(&)
    println("按位与: ${p3 & p2}")
    //按位异或(^)
    println("按位异或: ${p3 ^ p2}")
    //按位或(|)
    println("按位或: ${p3 | p2}")
    return 0
}

Step2:点击编辑器右上角运行按钮直接运行,终端窗口可以看到打印内容。

be04a892d09bdd36e11bc4302bfeb3a8.PNG

关系运算符:

小于(<)、大于(>)、小于等于(<=)、大于等于(>=)、相等(==)、不等(!=)。

具体代码操作如下:

Step1:复制以下代码,替换main.cj文件中的main函数。

main():Int64 {
    let p1 = 1
    let p2 = 2
    println("p1小于p2:${p1 < p2}")
    println("p1大于p2:${p1 > p2}")
    println("p1小于等于p2:${p1 <= p2}")
    println("p1大于等于p2:${p1 >= p2}")
    println("p1相等于p2:${p1 == p2}")
    println("p1不等于p2:${p1 != p2}")
    return 0
}

Step2:点击编辑器右上角运行按钮直接运行,终端窗口可以看到打印内容。

26f0211f4b55fa030bb9612dc3019292.PNG

赋值操作符和自增和自减操作符:

赋值操作符即 =,自增和自减操作符包括:自增(++)和自减(--)。

具体代码操作如下:

Step1:复制以下代码,替换main.cj文件中的main函数。

main():Int64 {
    var a = 10
    //赋值
    a = 11
    println("变量a重新赋值:${a}")
    //自增(++)
    a++
    println("变量a自增后的值为:${a}")
    //自减(--)
    a--
    println("变量a自减后的值为:${a}")
    return 0
}

Step2:点击编辑器右上角运行按钮直接运行,终端窗口可以看到打印内容。

9f2389dc546e737c819b47be4a20b6a1.PNG

复合赋值操作符:

+=、-=、*=、/=、%=、**=、<<=、>>=、&=、^=、|=。

具体代码操作如下:

Step1:复制以下代码,替换main.cj文件中的main函数。

main():Int64 {
    var a = 10
    a+=2
    println("a的值为10,a+=2的值为:${a}")
    a-=1
    println("a的值为12,a-=1的值为:${a}")
    a*=2
    println("a的值为11,a*=2的值为:${a}")
    a/=2
    println("a的值为22,a/=2的值为:${a}")
    a%=2
    println("a的值为11,a%=2的值为:${a}")
    a**=2
    println("a的值为1,a**=2的值为:${a}")
    a<<=2
    println("a的值为1,a<<=2的值为:${a}")
    a>>=2
    println("a的值为4,a>>=2的值为:${a}")
    a&=2
    println("a的值为1,a&=2的值为:${a}")
    a^=2
    println("a的值为0,a^=2的值为:${a}")
    a|=2
    println("a的值为2,a|=2的值为:${a}")
    return 0
}

Step2:点击编辑器右上角运行按钮直接运行,终端窗口可以看到打印内容。

125eb23b4e3a0044750b74bd3494af95.PNG

3.2 浮点类型

浮点类型包括 Float16、 Float32 和 Float64,分别用于表示编码长度为16-bit、32-bit 和 64-bit 的浮点数。

Float64 的精度约为小数点后 15 位,Float32 的精度约为小数点后6位,Float16 的精度约为小数点后 3 位。

3.2.1 浮点类型的字面量

浮点类型字面量有两种进制表示形式:十进制、十六进制。

在十进制表示中,一个浮点字面量至少要包含一个整数部分或一个小数部分,没有小数部分时必须包含指数部分(以 e 或 E 为前缀,底数为 10)。

在十六进制表示中,一个浮点字面量除了至少要包含一个整数部分或小数部分(以 0x 或 0X 为前缀),同时必须包含指数部分(以 p 或 P 为前缀,底数为 2)。

下面的例子展示了浮点字面量的使用,具体代码操作如下:

Step1:复制以下代码,替换main.cj文件中的main函数。

main():Int64 {
    let a: Float32 = 3.14
    println("a的值为:${a}")
    let b: Float32 = 2e3
    println("b的值为:${b}")
    let c: Float32 = 2.4e-1
    println("c的值为:${c}")
    let d: Float64 = .123e2
    println("d的值为:${d}")
    let e: Float64 = 0x1.1p0
    println("e的值为:${e}")
    let f: Float64 = 0x1p2
    println("f的值为:${f}")
    let g: Float64 = 0x.2p4
    println("g的值为:${g}")
    return 0
}

Step2:点击编辑器右上角运行按钮直接运行,终端窗口可以看到打印内容。

355f9e5f8e0250f743a13ec37f97632d.PNG

在使用十进制浮点数字面量时,可以通过加入后缀来明确浮点数字面量的类型,后缀与类型的对应为:

后缀为f16—>对应的类型为Float16;

后缀为f32—>对应的类型为Float32;

后缀为f64—>对应的类型为Float64;

具体代码操作如下:

Step1:复制以下代码,替换main.cj文件中的main函数。

 main():Int64 {
    let a = 3.14f32   
    println("a的值为:${a}")
    let b = 2e3f32    
    println("b的值为:${b}")
    let c = 2.4e-1f64 
    println("c的值为:${c}")
    let d = .123e2f64 
    println("d的值为:${d}")
    return 0
}

Step2:点击编辑器右上角运行按钮直接运行,终端窗口可以看到打印内容。

a95fcc9b8a75122c0ab28459edf7ddde.PNG

3.2.2 浮点类型支持的操作

浮点类型默认支持的操作符包括:算术操作符、关系操作符、赋值操作符、复合赋值操作符。浮点类型不支持自增和自减操作符。

具体请参考3.1.3 整数类型支持的操作。

3.3 布尔类型

布尔类型使用Bool表示,用来表示逻辑中的真和假。

布尔类型的字面量:

布尔类型只有两个字面量:true和false。具体代码操作如下:

Step1:复制以下代码,替换main.cj文件中的main函数。

 main():Int64 {
    let a: Bool = true
    println("布尔类型a的值为:${a}")
    let b: Bool = false 
    println("布尔类型b的值为:${b}")
    return 0
}

Step2:点击编辑器右上角运行按钮直接运行,终端窗口可以看到打印内容。

245b25bec971d46bbdd312408bd2710b.PNG

布尔类型支持的操作:

布尔类型支持的操作符包括:逻辑操作符(逻辑非 !,逻辑与 &&,逻辑或 ||)、部分关系操作符(== 和 !=)、赋值操作符、部分复合赋值操作符(&&= 和 ||=)。

3.4 字符类型

字符类型使用Rune表示,可以表示 Unicode 字符集中的所有字符。

字符类型字面量:

字符类型字面量有三种形式:单个字符、转义字符和通用字符。一个 Rune 字面量由字符 r 开头,后跟一个由一对单引号或双引号包含的字符。

单个字符字面量由字符 r 开头,后跟由一对单引号或双引号包含的单个字符。

转义字符是指在一个字符序列中对后面的字符进行另一种解释的字符。转义字符使用转义符号 \ 开头,后面加需要转义的字符。

通用字符以 \u 开头,后面加上定义在一对花括号中的 1~8 个十六进制数,即可表示对应的 Unicode 值代表的字符。

具体代码操作如下:

Step1:复制以下代码,替换main.cj文件中的main函数。

 main():Int64 {
    // 单个字符
    let a: Rune = r'a'
    println("单个字符a的值为:${a}")
    let b: Rune = r"b"
    println("单个字符b的值为:${b}")
    println()
    // 转义字符
    let c: Rune = r'\\'
    println("转义字符c的值为:${c}")
    let d: Rune = r'\n'
    println("转义字符d的值为:${d}")
    let e: Rune = r'\t'
    println("转义字符e的值为:${e}")
    println()   
    // 通用字符
    let f: Rune = r'\u{4f60}'
    print("${f}")
    let g: Rune = r'\u{597d}'
    print("${g}")
    return 0
}

Step2:点击编辑器右上角运行按钮直接运行,终端窗口可以看到打印内容。

b4c224aed8ead418464ca726bdef04db.PNG

字符类型支持的操作:

字符类型仅支持关系操作符:小于(<)、大于(>)、小于等于(<=)、大于等于(>=)、相等(==)、不等(!=)。比较的是字符的 Unicode 值。

3.5 字符串类型

字符串类型使用String表示,用于表达文本数据,由一串 Unicode 字符组合而成。

3.5.1 字符串字面量

字符串字面量分为三类:单行字符串字面量,多行字符串字面量,多行原始字符串字面量。

单行字符串字面量的内容定义在一对单引号或一对双引号之内,引号中的内容可以是任意数量的(除了用于定义字符串字面量的非转义的引号和单独出现的 \ 之外的)任意字符。单行字符串字面量只能写在同一行,不能跨越多行。

多行字符串字面量开头结尾需各存在三个双引号(“”")或三个单引号(‘’')。字面量的内容从开头的三个引号换行后的第一行开始,到遇到的第一个非转义的三个引号为止,之间的内容可以是任意数量的(除单独出现的 \ 之外的)任意字符。不同于单行字符串字面量,多行字符串字面量可以跨越多行。

多行原始字符串字面量以一个或多个井号(#)和一个单引号(')或双引号(")开头,后跟任意数量的合法字符,直到出现与字符串开头相同的引号和与字符串开头相同数量的井号为止。

具体代码操作如下:

Step1:复制以下代码,替换main.cj文件中的main函数。

main():Int64 {
    // 单行字符串字面量
    let s1: String = ""
    let s2 = 'Hello Cangjie Lang'
    let s3 = "\"Hello Cangjie Lang\""
    let s4 = 'Hello Cangjie Lang\n'
    println("单行字符串s1的值为:${s1}")
    println("单行字符串s2的值为:${s2}")
    println("单行字符串s3的值为:${s3}")
    println("单行字符串s4的值为:${s4}")

    // 多行字符串字面量
    let s5: String = """
    你好,
    仓颉
    """
    let s6 = '''
    Hello,
    Cangjie Lang'''
    println("多行字符串s5的值为:${s5}")
    println("多行字符串s6的值为:${s6}")

    // 多行原始字符串
    let s7: String = #""#
    let s8 = ##'\n'##
    let s9 = ###"
    Hello,
    Cangjie
    Lang"###
    println("多行原始字符串s7的值为:${s7}")
    println("多行原始字符串s8的值为:${s8}")
    println("多行原始字符串s9的值为:${s9}")
    return 0
}

Step2:点击编辑器右上角运行按钮直接运行,终端窗口可以看到打印内容。

ab3ab61ac40c22dfeff7bd6869e6110b.PNG

终端窗口打印的完整内容:

developer@developer:~/IDEProjects/demo$ cjpm run
单行字符串s1的值为:
单行字符串s2的值为:Hello Cangjie Lang
单行字符串s3的值为:"Hello Cangjie Lang"
单行字符串s4的值为:Hello Cangjie Lang

多行字符串s5的值为:    你好,
    仓颉
    
多行字符串s6的值为:    Hello,
    Cangjie Lang
多行原始字符串s7的值为:
多行原始字符串s8的值为:\n
多行原始字符串s9的值为:
    Hello,
    Cangjie
    Lang

cjpm run finished
3.5.2 插值字符串

插值字符串是一种包含一个或多个插值表达式的字符串字面量,通过将表达式插入到字符串中,可以有效避免字符串拼接的问题。

虽然直到现在才介绍它,但其实它早已经出现在之前的示例代码中,因为经常在 println 函数中输出非字符串类型的变量值,例如 println(“${x}”)。

插值表达式必须用花括号 {} 包起来,并在 {} 之前加上 $ 前缀。{} 中可以包含一个或者多个声明或表达式。

具体代码操作如下:

Step1:复制以下代码,替换main.cj文件中的main函数。

 main():Int64 {
    // 插字符串
    let fruit = "苹果"
    let count = 10
    let price = 500
    let s = "我买了${count ** 2}个${fruit},花费了${price}元钱"
    println(s)
    return 0
}

Step2:点击编辑器右上角运行按钮直接运行,终端窗口可以看到打印内容。

7b5866b92fe56df4660360e263785923.PNG

3.5.3 字符串类型支持的操作

字符串类型支持使用关系操作符进行比较,支持使用 + 进行拼接。下面的例子展示了字符串类型的判等、拼接、拆分和替换:

具体代码操如下:

Step1:复制以下代码,替换main.cj文件中的main函数。

main():Int64 {
    let s1 = "abc"
    var s2 = "ABC"
    // 字符串比较
    let r1 = s1 == s2
    println("The result of 'abc' == 'ABC' is: ${r1}")
    // 字符串拼接
    let r2 = s1 + s2
    println("The result of 'abc' + 'ABC' is: ${r2}")
    // 拆分
    let s5 =  r2.split("A")
    println(s5.toString())
    // 替换
    let s6=  r2.replace("ABC", "EFG")
    println(s6)
    return 0
}

Step2:点击编辑器右上角运行按钮直接运行,终端窗口可以看到打印内容。

51ef8a921dc8095ec8315a8c7ce31060.PNG

3.6 元组类型

元组(Tuple)可以将多个不同的类型组合在一起,成为一个新的类型。元组类型使用 (T1, T2, …, TN) 表示,其中 T1 到 TN 可以是任意类型,不同类型间使用逗号(,)连接。

注意:

  • 元组至少是二元。

    (Int64, Float64) 表示一个二元组类型,(Int64, Float64, String) 表示一个三元组类型。

  • 元组的长度是固定的,即一旦定义了一个元组类型的实例,它的长度不能再被更改。

  • 元组类型是不可变类型,即一旦定义了一个元组类型的实例,它的内容不能再被更新。

3.6.1 元组类型的字面量

元组类型的字面量使用 (e1, e2, …, eN) 表示,其中e1到eN是表达式,多个表达式之间使用逗号分隔。

元组支持通过t[index]的方式访问某个具体位置的元素,其中t是一个元组,index是下标,并且index只能是从0开始且小于元组元素个数的整数类型字面量,否则,编译报错。

具体代码操作如下:

Step1:复制以下代码,替换main.cj文件中的main函数。

 main():Int64 {
    // 定义元组
    let t: (Float64, String) = (3.14, "PI")
    // 取元组的第一个元素
    var a = t[0]
    println("元组t的第一个元素为:${a}")
    // 取元组的第二个元素
    var b = t[1]
    println("元组t的第二个元素为:${b}")
    return 0
}

Step2:点击编辑器右上角运行按钮直接运行,终端窗口可以看到打印内容。

fc47d6bd3bcaed8492b6a376bf1e18d5.PNG

3.6.2 元组类型的类型参数

可以为元组类型标记显式的类型参数名,下面例子中的name和price就是 类型参数名。

对于一个元组类型,只允许统一写类型参数名,或者统一不写类型参数名,不允许交替存在,并且参数名本身不能作为变量使用或用于访问元组中元素。

具体代码操作如下:

Step1:复制以下代码,替换main.cj文件中的代码。(保留package)

 // name 和 price 就是 类型参数名
func getFruitPrice (): (name: String, price: Int64) {
    return ("banana", 10)
}

main():Int64 {

    // 报错,统一写类型参数名,或者统一不写类型参数名,不允许交替存在
    //let a: (name: String, Int64) = ("banana", 5) 

    // 报错,参数名本身不能作为变量使用或用于访问元组中元素
    //b.name 

    // ok
    let b: (name: String, price: Int64) = getFruitPrice()
    // 取元组的第一个元素
    var x = b[0]
    println("元组b的第一个元素为:${x}")
    // 取元组的第二个元素
    var y = b[1]
    println("元组b的第二个元素为:${y}")
    return 0
}

Step2:点击编辑器右上角运行按钮直接运行,终端窗口可以看到打印内容。

eb80cad77fc6fa40f49ba52b2db28205.PNG

3.7 数组类型

可以使用Array类型来构造单一元素类型,有序序列的数据。

仓颉使用Array<T>来表示Array类型。T表示Array的元素类型,T可以是任意类型。

3.7.1 访问Array成员

当需要对Array的所有元素进行访问时,可以使用for-in循环遍历Array的所有元素。

Array是按元素插入顺序排列的,因此对Array遍历的顺序总是恒定的。

当需要知道某个Array包含的元素个数时,可以使用size属性获得对应信息。

具体代码操作如下:

Step1:复制以下代码,替换main.cj文件中的main函数。

 main():Int64 {
    // 定义数组
    let languages: Array<String> = ["Python","Cangjie","Java","ArkTS","C++"]
    // 遍历数组中的元素
    for(language in languages){
        println("数组的元素是:${language}")
    }
    if (languages.size != 0) {
        // 数组的长度size
         println("The size of languages is ${languages.size}")
    }
    return 0
}

Step2:点击编辑器右上角运行按钮直接运行,终端窗口可以看到打印内容。

3427a15c27848c212dc778f0dd380f14.PNG

3.7.2 修改Array

Array是一种长度不变的Collection类型,因此Array没有提供添加和删除元素的成员函数。

但是Array允许对其中的元素进行修改,同样使用下标语法。

对Array 素的修改会影响到该实例的所有引用。

具体代码操作如下:

Step1:复制以下代码,替换main.cj文件中的main函数。

 main():Int64 {

    let arr: Array<Int64> = [0, 1, 2, 3, 4, 5]
    // 通过下标,修改数组的第一个元素
    arr[0] = 3
    println("The first element is ${arr[0]}")

    // Array 元素的修改会影响到该实例的所有引用
    let new_array = arr
    new_array[1] = 9
    println("new_array: ${new_array.toString()}")
    println("arr: ${arr.toString()}")
    return 0
}

Step2:点击编辑器右上角运行按钮直接运行,终端窗口可以看到打印内容。
0421.png

3.8 其它类型

包括区间类型、Unit类型、Nothing类型。

3.8.1 区间类型

区间类型用于表示拥有固定步长的序列,区间类型是一个泛型,使用Range<T>表示。

区间类型定义:

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

start:起始值

end:终止值

step:前后两个元素之间的差值(步长),步长不能等于0

具体代码操作如下:

Step1:复制以下代码,替换main.cj文件中的main函数。

main():Int64 {
    let r1 = Range<Int64>(0, 10, 1, true, true, true) 
    print("r1包含的元素有:")
    for(key in r1.iterator()){
          print("${key}"+" ")
    }

    println()

    let r2 = Range<Int64>(0, 10, 1, false, false, false) 
    print("r2包含的元素有:")
    for(key in r2.iterator()){
          print("${key}"+" ")
    }
    return 0
}

Step2:点击编辑器右上角运行按钮直接运行,终端窗口可以看到打印内容。

dfe911a6c7b0cb567bbcc26cafbec890.PNG

区间类型字面量:

区间字面量有两种形式:“左闭右开”区间和“左闭右闭”区间。

  • 左闭右开区间的格式是 start…end : step,它表示一个从start开始,以step为步长,到 end(不包含 end)为止的区间;
  • 左闭右闭区间的格式是 start…=end : step,它表示一个从start开始,以step为步长,到 end(包含 end)为止的区间。

具体代码操作如下:

Step1:复制以下代码,替换main.cj文件中的main函数。

 main():Int64 {
    let n = 12
    let r1 = 6..n : 1   
    print("r1包含的元素有:")
    for(key in r1.iterator()){
          print("${key}"+" ")
    }
    println()
    let r2 = 6..=n : 1   
    print("r2包含的元素有:")
    for(key in r2.iterator()){
          print("${key}"+" ")
    }

    return 0
}

Step2:点击编辑器右上角运行按钮直接运行,终端窗口可以看到打印内容。

f010f83cfcdf66ce3675320b1f43a263.PNG

3.8.2 Unit 类型

对于那些只关心副作用而不关心值的表达式,它们的类型是Unit。例如,print 函数、赋值表达式、复合赋值表达式、自增和自减表达式、循环表达式,它们的类型都是Unit。

Unit类型只有一个值,也是它的字面量:()。除了赋值、判等和判不等外,Unit类型不支持其他操作。

3.8.3 Nothing类型

Nothing是一种特殊的类型,它不包含任何值,并且Nothing类型是所有类型的子类型。

break、continue、return 和 throw 表达式的类型是 Nothing,程序执行到这些表达式时,它们之后的代码将不会被执行。return 只能在函数体中使用,break、continue只能在循环体中使用,具体代码操作如下:

Step1:复制以下代码,替换main.cj文件中的main函数。

main():Int64 {
    while (true) {
        func f() {
            // break 只能在循环体中使用
            break 
        }
        let g = { =>
            // continue 只能在循环体中使用
            continue 
        }
    }
    return 0
}

Step2:代码复制完成后,编译器直接提示报错。

8b41abe0c658c03bc18bcd4fdc99693f.PNG

至此,《仓颉基础大揭秘:数据类型的奇妙世界》案例内容已全部完成。

如果想了解更多仓颉编程语言知识可以访问:https://cangjie-lang.cn/

相关推荐

鸿蒙案例上新啦 | 购物、听歌、健身:15个模板带你一键激活社交娱乐

页面层级如何组织、跨页共享状态如何同步、列表与详情及个人中心如何形成稳定闭环。鸿蒙开发实践中心将这些高频消费与互动场景沉淀为可参考的标准模板,提供从业务架构到界面实现的快捷实践入口。更多实战案例欢迎前往鸿蒙开发实践中心案例中心查看并开启云端体验。

华为云官方博客 338

鸿蒙案例上新啦 | 出门打车、到家上课:25个模板带你一屏打通日常生活

如何合理拆分页面组件、如何建立单一可信的状态源、如何让用户在每一步操作中都获得明确反馈。鸿蒙开发实践中心以标准化的应用与元服务模板为入口,将清晰的业务架构与可复用的代码结构直观呈现。不妨立即挑选一个感兴趣的方向进入云端环境,从页面布局、组件封装、状态管理到路由组织,亲手跑通你的鸿蒙实战项目。

华为云官方博客 325

LakeAgent:DWS数据仓库的第二大脑,告别 “翻译式运维”,迈入智能自治时代

和普通 SQL 改写工具不同,LakeAgent 自动做多方案代价对比,主动规避负优化陷阱:补充分区键过滤实现剪枝,扫描分区由 37 收敛至 1,执行代价从 758.28 降至 113.74;未来的数据仓库,将不止能算、能存,更能看懂自己、诊断自己、理解自己。长久以来,数仓的智能都依附于人:信号需要人解读,瓶颈需要人研判,经验困在个体里,无法随底座永续生长。CPU 高、CPU 告警、CPU 诊断、CPU 使用率过高、CPU 满。语法、错误码、计费、性能调优、最佳实践、故障处置等全场景内容。

华为云官方博客 555

如何使用RDS Supabase后端BaaS能力:文件存储(File Storage)

• product-images(公开桶,允许公共读取):策略名称"Public read for product-images",允许SELECT,目标角色anon,策略定义bucket_id = 'product-images'。上传/删除需另配INSERT/DELETE策略,详见SQL。• product-specs(私有桶,仅认证用户访问自己的文件夹):建议拆为上传、读取、删除三条策略,策略定义均为 bucket_id = 'product-specs' 且仅限本人文件夹(详见下文 SQL)。

华为云官方博客 476

如何使用RDS Supabase后端BaaS能力:实时订阅与推送(Realtime)

Realtime 把数据库的每次变更同步到客户端:表里增、删、改一行,订阅者无需刷新页面或主动请求即可秒级收到。三大能力各司其职:• Postgres Changes — 监听表的 INSERT/UPDATE/DELETE,变化即通知• Broadcast — 客户端之间直接互发,适合瞬时通知、协同编辑• Presence — 跟踪频道里“谁在线”典型场景有实时数据展示(订单、库存、监控指标即时刷新)、即时通讯(消息收发、在线名单、“对方正在输入”)、协同编辑与实时通知。

华为云官方博客 464

AI Agent如何通过MCP连接到华为云RDS Supabase应用平台

Schema元数据列出所有可访问的表(按schema分组)。Schema元数据列出表的列及元数据(类型/默认值/约束)。Schema元数据列出所有约束(PK/FK/UNIQUE/CHECK/EXCLUDE)。可按schema/表/类型过滤。Schema元数据列出所有外键关系。可按schema/表过滤。Schema元数据列出所有索引及定义和大小。可按schema/表过滤。Schema元数据列出已应用的数据库迁移记录。Schema元数据列出已安装的PostgreSQL扩展。

华为云官方博客 473

华为大数据Flink让每一 CU 算力,跑出开源 5.74 倍的性能

1. 开源Apache Flink 已成为业界流计算事实标准,但在极端重负载场景下存在性能瓶颈。2. 华为大数据Flink通过多项自研深度优化,在执行计划、算子执行、状态存储三个层面构建协同的优化体系。3. Nexmark Benchmark 测试结果:整体性能提升 5.74 倍,极端重负载场景性能领先最高 18.3 倍。4. 100% 兼容 Apache Flink 1.20,业务代码零改造,无缝迁移。

华为云官方博客 380

LakeAgent实战 | 业务分析篇从一句提问到业务分析

本文以“订单金额变化”分析为例,展示LakeAgent如何通过自然语言提问,结合DataArtsStudio的数据资产与专业技能,帮助业务人员快速定位数据、生成SQL、追踪血缘、生成报告。从问题出发,逐步实现数据发现、变化洞察、原因追溯与团队协作,最终形成可复用的分析流程与企业规则,显著提升数据分析效率与一致性。

华为云官方博客 389

华为云RDS Supabase AI应用已开放公测 :30分钟搭建AI应用后端

认证、存储、实时推送、数据库API——4个后端模块,传统开发需要数周。今天,你只需要30分钟。AI创业公司的全栈开发工程师。上周老板说"下周要上线的AI对话应用,后端你来搞"——认证鉴权、数据库接口、文件存储、实时推送,每一个模块都需要数周搭建,而市场不会等你。小张打开华为云RDS Supabase,30分钟搭好认证、数据库API、对象存储,剩下的时间全用来打磨AI交互体验。基于开源Supabase+华为云RDS PostgreSQL全托管能力,为开发者提供。

华为云官方博客 396

如何使用RDS Supabase后端BaaS能力:数据库函数(Database Function)

上一篇介绍了 Database Data API——建表即自动生成增删改查接口,解决单表读写,但聚合统计、跨表事务、字段自动维护等逻辑已超出其能力边界。本篇推进到数据库函数(Database Function):把业务逻辑封装进数据库,前端通过 .rpc() 调用,由触发器自动响应数据变更。上一篇中,小张基于 Data API 完成了产品目录的建表与基础读写。但新需求随之而来:按分类统计产品数与价格区间、上架新品同时写产品表与定价表、产品修改后自动刷新更新时间。

华为云官方博客 464

如何使用RDS Supabase后端BaaS能力:创表即生成API(Database Data API)

认证、存储、实时推送、数据库API——4个后端模块,传统开发要数周。本系列逐个拆解,首篇聚焦数据库API(Database Data API):建表即得 API,无需手写后端。小张,AI创业公司的全栈工程师。老板让他做个产品目录页,展示产品与价格、支持上下架。传统做法要搭后端、写接口、配权限,工期少说1-2周;而在华为云RDS Supabase,建两张表、应用 SDK 直连,几分钟增删改查全跑通。

华为云官方博客 478

从一句话到一个能出去的链接,AI开发者空间做了什么

自行搭建的 Agent、正在使用的开源项目、团队既有的工具,都可以接入,可以通过AI创建或者手动搭建环境;华为云 AI开发者空间——面向开发者的云端一站式开发平台,做的就是把这段路接上:环境免安装,浏览器打开即为完整的 Linux 运行环境,预置的 AI 智能体开箱即用。第一个任务建议选能出结果的:做一个游戏、生成一个页面、创建一台实例,从需求走到可访问的链接,一次就能看清这个环境在做什么。沙箱是一个完整的 Linux 环境,依赖、服务、端口都是真实的,不是模拟。环境释放后,权限随之失效。

华为云官方博客 425

华为云码道配置自定义大模型,四种方式完整实操

案例介绍。

华为云官方博客 624

图数据库:实现穿透式监管的数据基座

穿透式监管标志着国企监管从“管企业”向“管资本”转型过程中的关键一跃。而图数据库正是这一跃的技术支点。从股权穿透到资金链穿透,从供应链穿透到数据穿透,华为GES图数据库正在将“穿透式监管”从理念变为可落地、可操作的实践。无论是天眼查式的全量链路查询,还是某集团财经的税务规则判断,抑或是芯片供应链式的部件风险分析,乃至通过Palantir构建决策知识图谱,其底层逻辑都是一致的——用图的力量,穿透一切形式的“隔离层”,直抵风险本质与责任核心。

华为云官方博客 664

《公共云三十问》正式收官,奔赴企业AI百场景新征程

今年6月底,公共云产业联盟重点推出《公共云三十问》专栏,以每周三问的节奏,连载十周,解读《先进公共云》白皮书,分享国计民生系列案例,旨在凝聚共识、推动落地实践。同时,专栏分析公共云在产业升级、民生福祉、科技创新、全球发展等方面的作用,梳理中国特色公共云发展路径:以普惠云拓展用云广度,以智算云提升用云深度,以自主云夯实用云厚度,以全球云打开用云跨度。这十问从专属云、行业云切入,深入政务、金融、交通、电力、钢铁、化工、油气、制造等国计民生场景,回答公共云“怎么用”。

华为云官方博客 473

开发者小技巧|IAM配置,让码道代码智能体连续30天免登录

案例介绍。

华为云官方博客 645

码道深度对接CodeArts,让需求自动落地为代码

案例介绍。

华为云官方博客 720

【公共云三十问 之三十】拥抱AI,企业如何建设面向智能体的专属云?

企业可分阶段建设覆盖开发、运行、运营及安全的一体化智能体平台——从构建一站式、高低码协同的智能体开发平台,到打造高性能、极致弹性的运行时环境,再到搭建AgentOps驱动的持续运营与运维体系,同时构建端到端、多层次的全链路安全防护体系。在数据湖建设方面,遵循“存量复用、平滑演进、AI导向、分步迭代”原则,分三阶段推进——打造AI多模数据湖核心能力、完成存算分离与统一元数据管理、实现闭环赋能全面支撑智能体规模化落地,在保护既有投资的前提下将传统数据平台转型为AI数据专属供给平台。

华为云官方博客 823

【公共云三十问 之二十九】国计民生之制造:制造云如何重塑数智时代的新质生产力?

平台打通软件交付的完整路径,覆盖需求管理、代码托管、代码检查、编译构建、制品仓库、部署、测试等关键环节,支持大模型能力融入研发全流程,实现从需求到交付的端到端管理。通过构建“研发一朵云”,方案打破地域与组织壁垒,实现跨团队协同开发,有效缩短软件交付周期,助力工业制造企业从“传统研发”走向“敏捷研发”,加速数智化转型进程。当制造云真正成为数据流通的平台、AI创新的底座,公共云的社会价值将从基础设施层向生产场景层持续延伸,为新型工业化建设和制造强国战略注入源源不断的动力,重塑数智时代的中国制造新质生产力。

华为云官方博客 789

告别重复手工迁仓,码道MCP+Skill实现仓库批量迁移

案例介绍。

华为云官方博客 790

【公共云三十问 之二十八】国计民生之油气:智算云如何叩响数智时代的“地心蓝金”?

西南油气田以“向地球深部要资源”为战略方向,联合以华为云Stack为代表的公共云服务商共同打造统一算力底座,建设西南区域数据湖与通用技术平台,构建“勘探开发工程技术、天然气生产过程管控、天然气产运储销”等三个一体化协同应用场景,支撑油气勘探、开发生产、管输储运等全业务链的数智化转型。当智算云真正成为数据流通的平台、AI创新的底座,油气田得以将算力效能、数据价值与智能技术深度融入勘探开发全链条,将“看不见的算力”转化为“摸得着的储量”,以智能化手段持续降低勘探风险、缩短发现周期、提高采收效率,确保生产安全。

华为云官方博客 613

【公共云三十问 之二十七】国计民生之化工:数智云如何重塑传统化工新范式?

在架构方面,方案构建云边协同的统一体系,涵盖AI协同、数据协同与运营协同三大维度——总部集中训练大模型,边缘节点负责推理执行,云边持续迭代,实现“边用边学”的智能闭环,模型平均精度提升20%以上。此外,方案提供一站式企业级工业物联网平台、数据湖与数据治理平台,覆盖工业数据分析“采、存、算、管、用”全流程,打通生产现场与管理系统间的数据壁垒,有效消除数据孤岛。层面,方案充分发挥软硬协同优势,实现计算、存储、网络与云平台的深度协同,训练线性度超95%,为大模型训练推理提供强劲算力支撑。▲化工“数智”新模式。

华为云官方博客 663

【公共云三十问 之二十六】国计民生之钢铁:数智云如何淬炼中国钢铁新力量?

同时,构建云边端协同的统一架构,支撑集团总部与各生产基地两级协同发展——总部集中训练大模型,边缘节点负责推理执行,云边持续迭代,实现训推一体化的资源调度与高效协同,为钢铁行业的数智化转型构建了坚实的算力底座。层面,方案构建覆盖“工业数采→边缘IT/OT融合→统一数据湖→数据治理平台→数据应用”全链路的一站式数据治理与流通平台,打通生产现场与管理系统间的数据壁垒,让数据“采得到、流得动、用得好”,加速数据价值从生产现场向经营决策层流动释放。湘潭钢铁集团的钢铁数智云,是钢铁工业智能云建设的标杆案例。

华为云官方博客 526

LakeWatch——MRS 智能运维Agent

从资源池、队列、作业等多个维度,对集群CPU与内存资源进行精细化分析与对比,直观呈现不同时间段的空闲、满载等使用状态,识别资源浪费,指导治理优化,为扩缩容决策提供数据支撑。对HDFS存储进行多维度深度分析(目录、用户、用户组等),涵盖使用量、增量、文件大小分布及数据热度等指标,帮助快速识别增长较快的目录、长期未访问的文件,统计目录文件数量与小文件占比,评估HDFS总存储量与扩缩容需求,为存储治理与资源规划提供全面数据支撑。Agent主动巡检,识别异常趋势并提前预警,让运维从"事后处理"转向"事前预防"。

华为云官方博客 515

华为云专题文档发布:丰富的AI案例、选型指导和概念解读

发布 “云服务选型”、“云计算概念”专题,提供云服务选型指导,助您选择匹配业务的云服务,解读云计算相关概念,开启云上学习之路。开发者工具和文档专区上线,提供从学习、实践到反馈的全链路支持。帮助中心新增100余篇AI案例。

华为云官方博客 286

一个人,也能用AI做点“星东西”

华为云星耀创想者大赛-2026华为云OPC创意大赛等你来~

华为云官方博客 290

从需求到可执行工作项:MCP+Skill 让智能体规划真正落地

回顾整个体验,以前让智能体帮我拆需求,它是洋洋洒洒给我列了一大篇 Markdown,看着挺像那么回事,但最后还是得我一条条往 CodeArts Req 里搬,搬完再手动挂父子关系、排日期,拆需求五分钟,搬运两小时。现在好了,MCP 给智能体接上了"手",Skill 给它装上了"项目经理的脑子",一句话下去,34 个工作项连带排期、层级关系全给我建好了,甘特图一拉,齐刷刷都在两周内,节省了多少工作量啊,美滋滋。本次实操在码道代码智能体基础上,构建了一套"需求→可执行工作项"的自动化规划方案。

华为云官方博客 576

华为云码道「码力续航计划」更新!

✅上新GLM‑5.3‑Flash,高速响应,代码生成、工程解析、Agent调试高效输出。新增GLM‑5.3‑Flash福利模型,每日解锁1000万免费Tokens。● 本次活动共发放总量价值100万元Tokens,发完即止!把耗算力的编码重活,交给华为云码道代码智能体🚀🚀。● 每日额度准时刷新,当日清零、次日满血重置。✅复杂算法、大项目解析、批量代码生成随便跑。✅不用抠额度、不用算消耗,放开调试大胆迭代。✅无需额外操作,登录即送,直接切换模型使用。● 把算力交给码道,让撸码不再内耗👏🏻。

华为云官方博客 685

【公共云三十问 之二十四】国计民生之交通:交通云如何铺就数智通衢新坦途?

交通行业作为支撑实体经济的关键基础设施,涵盖公路、铁路、机场、港口、地铁等众多子领域,其中,公路网络作为综合交通运输体系的基础骨架,承担着全国超过70%的客货运量,其数字化、智能化转型的需求尤为迫切。方面,提供Agent开发框架、知识库管理、RAG工程、意图识别、静态应用编排及模型评测等能力,支持客户将行业知识、业务流程与AI能力深度融合,快速构建面向收费稽核、路网调度、应急处置等场景的智能应用。开发并实现落地应用,全面覆盖建设、管理、养护、运营、服务、安全、办公七大业务领域。

华为云官方博客 461

【公共云三十问 之二十五】国计民生之电力:电力云如何点亮数智电力新引擎?

方案构建了覆盖数据获取、质量评估到标准化处理的全链路能力。基于公共云服务商智算底座及气象大模型,通过时空图神经网络重新建模产流机制,中国华电建成超50TB多源融合数据集,突破时空建模与机理融合等五大关键技术,短期径流预测精度较传统机理模型提升5个百分点以上,实现15天中期径流预测精度超85%,推理效率达秒级。基于气象大模型的基础架构与预训练能力,客户可直接在大模型之上开展增量训练与微调,充分利用场站所在区域的高精度历史数据(如3公里、1公里分辨率),针对不同场站和区域的地形地貌与气候特征进行模型调优。

华为云官方博客 381
上一篇: 本地MacOS环境连接管理开发者空间 - 云开发环境
下一篇: 基于开发者空间OpenGauss数据库列存引擎的分析与使用
华为云开发者联盟
华为云开发者联盟 企业官方账号 企业官方账号
博客等级 码龄10年 72万+粉丝 5985原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值