- 文档
- 编程语言
【免费下载链接】cangjie_docs
仓颉编程语言开发者文档。
字符串是仓颉编程语言(Cangjie)中表达文本数据的核心内置类型String。本篇技术指南围绕字符串类型的字面量书写规则、插值表达式机制以及判等、拼接、包含、拆分等常用操作展开,结合文档示例与源码佐证,帮助读者在仓颉程序中正确书写字符串并高效完成文本处理。读完本文,你将掌握单行/多行/多行原始三类字符串字面量的语法边界、${}插值求值规则,以及字符串与Byte、Rune类型之间的隐式强制转换等实战要点。
字符串类型概述
字符串类型使用String表示,用于表达文本数据,由一串 Unicode 字符组合而成。仓颉语言在标识符、字符字面量等语法层面均遵循 Unicode 标准(标识符章节说明仓颉使用 Unicode 标准 15.0.0),因此String天然支持中文、emoji 等多语言字符的存储与处理。值得注意的是,String本身并不在关键字表中,它是标准库中内置的公开类型,可直接用于变量声明,例如let s: String = ""。
字符串字面量
字符串字面量分为三类:单行字符串字面量、多行字符串字面量和多行原始字符串字面量。三类字面量在定界符、转义规则与跨行能力上各不相同,需要根据文本内容按需选用。
单行字符串字面量
单行字符串字面量的内容定义在一对单引号('...')或一对双引号("...")之内。引号中的内容可以是任意数量的任意字符,但有以下限制:
- 不能包含用于定义字符串字面量的非转义引号(即与定界符相同的引号必须转义);
- 不能包含单独出现的
\(反斜杠必须配合转义序列使用,如\n、\"、\\); - 单行字符串字面量只能写在同一行,不能跨越多行。
以下示例展示了空字符串、单引号定界、双引号转义以及含转义换行符的写法:
let s1: String = "" let s2 = 'Hello Cangjie Lang' let s3 = "\"Hello Cangjie Lang\"" let s4 = 'Hello Cangjie Lang\n'其中s3通过\"在双引号定界的字符串中输出一对字面引号;s4中的\n是转义后的换行符。
多行字符串字面量
多行字符串字面量的开头和结尾各需存在三个双引号(""")或三个单引号(''')。字面量的内容从开头的三个引号换行后的第一行开始,到遇到的第一个非转义的三个引号为止。与单行字符串字面量不同,多行字符串字面量可以跨越多行,适合书写较长的文本块。
let s1: String = """ """ let s2 = ''' Hello, Cangjie Lang'''需要注意,多行字符串字面量内容中同样不允许出现单独出现的\;其内容可以包含任意数量的其他字符(包括与定界符不同的引号、换行和缩进)。
多行原始字符串字面量
多行原始字符串字面量以一个或多个井号(#)加上一个单引号(')或双引号(")开头,后跟任意数量的合法字符,直到出现与字符串开头相同的引号、且相同数量的井号为止。如果当前文件结束之前仍未遇到匹配的引号和相同个数的井号,编译器将报错。
多行原始字符串字面量可以跨越多行,其与多行字符串字面量的核心区别在于:转义规则不适用于原始字符串字面量,字面量中的内容会维持原样。也就是说,转义字符不会被转义——例如下例s2中的\n不是换行符,而是由\和n两个字符组成的字符串\n:
let s1: String = #""# let s2 = ##'#'\n'## // 输出结果为:#'\n let s3 = ###" Hello, Cangjie Lang"### // 该变量当中的换行、缩进等也会被保留井号数量的设计使得原始字符串可以安全地内嵌引号和井号。例如s2使用两个井号定界,其内容#'\n中既包含了单引号又包含了\,无需任何转义;s3使用三个井号定界,其内容中的换行与缩进被原样保留。如果需要表达更复杂的文本(如多级引号嵌套),只需增加井号数量即可。
字符串字面量到 Byte / Rune 的隐式强制转换
对于形如left = right的赋值操作,仓颉提供两种针对字符串字面量的隐式强制转换:
- 如果左操作数的类型是
Byte(内置类型UInt8的别名,相关内容可参见整数类型),且右操作数是一个表示 ASCII 字符的字符串字面量,那么右操作数的字符串会被强制转换为Byte类型后再赋值; - 如果左操作数的类型是
Rune(仓颉的字符类型,可表示 Unicode 字符集中的所有字符,参见字符类型),且右操作数是一个单字符的字符串字面量,那么右操作数的字符串会被强制转换为Rune类型后再赋值。
main() { var b: Byte = "0" print(b) b = "1" print(b) var r: Rune = "0" print(r) r = "1" print(r) }编译并执行上述代码,输出结果为:
484901输出中的48、49分别是字符'0'与'1'的 ASCII 码(十进制),0、1是Rune变量r打印出的字符本身。这一机制让开发者可以用字符串字面量的形式便捷地初始化字节与字符类型变量。
插值字符串
插值字符串是一种包含一个或多个插值表达式的字符串字面量。通过将表达式嵌入到字符串中,可以有效避免繁琐的字符串拼接。插值字符串经常出现在println函数中,用于输出非字符串类型的变量值,例如println("${x}")。
插值表达式必须用花括号{}包起来,并在{}之前加上$前缀。{}中可以包含一个或者多个声明或表达式。当插值字符串求值时,每个插值表达式所在位置会被{}中的最后一项的值替换,整个插值字符串求值后仍然是一个字符串。
下面的示例演示了插值表达式中的算术运算、变量引用以及含声明块的复杂表达式:
main() { let fruit = "apples" let count = 10 let s = "There are ${count * count} ${fruit}" println(s) let r = 2.4 let area = "The area of a circle with radius ${r} is ${let PI = 3.141592;PI * r * r}" println(area) }编译并执行上述代码,输出结果为:
There are 100 apples The area of a circle with radius 2.400000 is 18.095570可以看到:${count * count}先完成表达式求值(10 * 10)再嵌入字符串;${let PI = 3.141592;PI * r * r}在插值块内部声明了局部常量PI并计算圆面积,最终{}中最后一项(乘法表达式)的值被替换进字符串。需要特别说明的是,插值字符串不适用于多行原始字符串字面量——原始字符串中的内容维持原样,${...}不会被求值。
字符串类型支持的操作
字符串类型支持使用关系操作符进行比较(如==、!=),支持使用+进行拼接。下面的例子展示了字符串类型的判等和拼接:
main() { 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}") }编译并执行上述代码,输出结果为:
The result of 'abc' == 'ABC' is: false The result of 'abc' + 'ABC' is: abcABC由于字符串比较区分大小写,"abc" == "ABC"的结果为false;而+将两个字符串按序拼接得到"abcABC"。在操作符优先级表中,+、-的优先级为 6(左结合),==、!=的优先级为 10,因此在混合书写s1 + s2 == "abcABC"这类表达式时,拼接运算会先于判等执行;同时基本操作符章节也明确指出"加法操作符也可用于字符串的拼接"。
字符串还支持其他常见操作,例如包含判断、拆分、替换等。下面给出部分常见操作示例:
main() { var s1 = "abc" var s2 = "ABCabc" var s3 = "abcyyabcqqabcbc" let r1 = s2.contains(s1) // 判断s2中是否包含字符串s1 println(r1) // true let r2 = s3.split(s1) // 对原字符串 s3 按照字符串 s1 作为分隔符分割 println(r2[1]) // yy s1 = s2 println(s1) // ABCabc }运行结果依次为:contains返回true("ABCabc"包含子串"abc");split以"abc"为分隔符将"abcyyabcqqabcbc"拆分为字符串数组,索引 1 处的元素是"yy";s1重新赋值为s2后打印出"ABCabc"。split返回的是可索引访问的字符串数组(r2[1]),开发者可通过下标按位置取回各分段。
源码与文档中的更多实践佐证
字符串比较在编译器插桩中的体现
在编译选项附录中,--sanitizer-coverage-trace-memcmp选项会在String、Array等类型的比较函数前插入回调,其插桩清单直接印证了字符串内置 API 的组成:String==、String.startsWith、String.endsWith、String.indexOf、String.replace、String.contains。也就是说,字符串类型除判等与拼接外,还内置了startsWith、endsWith、indexOf、replace等常用文本处理能力,配合上文的contains、split,足以覆盖日常的检索与替换场景。
通过扩展为字符串添加自定义方法
字符串类型支持仓颉的扩展机制。在--export-for-test编译选项的示例中,可以看到extend String { ... }的用法,开发者可以为String增加自定义方法(如示例中的invertSlashes),从而在字符串类型之上封装领域相关的文本逻辑。
字符串与 I/O 流的互转
在I/O 流概述中,字符串与字节数据之间的转换通过String.fromUtf8(buf)与"Hello World".toArray()完成:前者将 UTF-8 字节数组解码为字符串,后者将字符串编码为字节数组。结合本章内容可知,仓颉字符串在底层以 Unicode 字符序列表达文本,而其与外部数据交互(文件、网络、内存缓冲)时则以 UTF-8 字节流为载体,二者通过fromUtf8/toArray相互转换。
总结
仓颉编程语言的String类型提供了一套完整而严谨的文本表达机制:三类字符串字面量分别覆盖单行短文本、跨行长文本与"所见即所得"的原始文本场景;Byte/Rune的隐式强制转换打通了字符串与字节、字符类型之间的边界;${}插值表达式让动态文本的构造免于繁琐拼接;==、+、contains、split等操作则覆盖了判等、拼接、检索与拆分等核心文本处理需求。掌握这些规则,即可在仓颉项目中正确书写并高效处理各种文本数据。
- 文档
- 编程语言
【免费下载链接】cangjie_docs
仓颉编程语言开发者文档。
相关推荐
Carbon 语言字面量表达式详解:值驱动类型、iN/uN/fN 类型字面量与字符语义
Carbon 语言字面量表达式详解:值驱动类型、iN/uN/fN 类型字面量与字符语义 本文围绕 docs/design/expressions/literal
编程语言编译器标准库仓颉编程语言字符类型(Rune)详解:字面量、转义与类型转换实战
仓颉编程语言字符类型(Rune)详解:字面量、转义与类型转换实战 字符是文本处理的基本单元。在仓颉(Cangjie)编程语言中,字符类型使用 Rune 表示,能
文档编程语言仓颉编程语言 String 字符串完全指南:字面量、插值、切片与 Rune 转换
仓颉编程语言 String 字符串完全指南:字面量、插值、切片与 Rune 转换 String 是仓颉(Cangjie)语言中用于表达文本数据的核心结构体类型,
文档知识库教程OpenHarmony
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考