- 示例工程
- 教程
【免费下载链接】仓颉编程基础及应用_陈波_何睿_重庆大学
《仓颉编程基础及应用》,清华大学出版社,2025年9月第1版: 1. 随书源代码; 2. PPT; 3.在线扩展阅读资料。
将一个数值对象转换成指定样式的字符串(规定宽度、对齐、精度、进制、符号前缀等)是控制台输出与数据展示中高频出现的需求。本文基于《仓颉编程基础及应用》随书源码仓库中的扩展阅读文档,系统讲解仓颉std.convert包为Float32、Float64、Int32、Int64、UInt32、UInt64等类型扩展提供的format成员函数,完整拆解fmt格式串的[flags][width][.precision][specifier]四段式语法,并给出仓库中可直接编译运行的 9 个配套示例工程,帮助读者掌握仓颉中宽度补齐、左右对齐、零填充、进制转换与科学计数法等格式化实战技能。
1. 格式化概念与 format 成员函数
将一个对象转换成对应的字符串对象的过程称之为格式化(format)。在仓颉中,std.convert包为Float32、Float64、Int32、Int64、UInt32、UInt64等类型扩展实现了format成员函数。在导入std.convert包后,再执行这些对象的format成员函数,即可将对象“转换”成对应的字符串表达形式。
上述format成员函数的签名为format(fmt: String): String,其fmt参数是一个字符串类型的参数,用于指定转换格式。理解这个函数有两点需要注意:
- 它是扩展成员函数:
format并不是这些数值类型自带的成员,导入std.convert之后,Int32、Float64等对象才“拥有”该成员函数,这体现了仓颉通过包导入引入扩展能力的语言机制; - 它不修改原对象:
pi.format(x)只是根据pi的值以及格式串x的要求生成并返回一个新的字符串对象,原数值对象在函数执行前后类型和值都保持不变。
2. 简单格式化示例
下述示例(对应仓库工程 BookSourceCode/CH2/StrFormat)将浮点数对象pi按指定格式转换成字符串并打印至屏幕:
package StrFormat import std.convert //导入std标准库下的format包 main(): Int64 { let pi:Float64 = 3.141592653589793238462643383279 let s1 = pi.format(".4"); let s2 = pi.format("+20.10") println(s1); print(s2) //s1, s2均为String类型 return 0 }上述代码的执行结果为:
3.1416 +3.1415926536逐行解析:
- 第 2 行:导入
std标准模块下的convert(格式化)包。程序第 6 行所使用的格式化函数是由该包定义的; - 第 5 行:定义圆周率不可变变量
pi,为尽可能提高存储精度,这里使用了Float64类型; - 第 6 行:在导入了
std.convert之后,pi作为Float64类型的对象,便拥有了成员函数format; - 第 7 行:将格式化结果字符串
s1和s2通过println和print函数打印至屏幕。
结合执行结果观察:
pi.format(".4")将pi格式化,生成了将pi保留 4 位小数的字符串"3.1416"。format函数的参数".4"为一个字符串字面量,它表明转换格式为“保留 4 位小数”。不难看出,3.1415926… 在格式化保留 4 位小数的过程中被四舍五入,变成了 3.1416;pi.format("+20.10")将pi格式化为显示正负号(+)、总宽度 20 个字符、保留 10 位小数、右对齐的字符串,不足部分使用空格补齐(即执行结果第 2 行中+3.1415926536左侧的若干空格)。
3. 格式化参数 fmt 的语法格式
根据仓颉文档,format(fmt: String): String函数的fmt参数用于指定格式化参数,这些参数用于规定转换结果的宽度、对齐方式、精度等信息。格式化参数fmt的语法格式为:
[flags][width][.precision][specifier]其中,方括号表示这些字段为可选,即格式化参数并不需要完整包含上述 4 个字段。四个字段的位置是固定的:标志位在前、宽度次之、精度(以.引导)再次之、进制/记数 specifier 在最后。后文分别对四类字段逐一展开。
4. flags 标志位
flags字段可以包含"-"、"+"、"#"、"0"四个字符中的 1 个或多个。
4.1 "-":左对齐
"-"适用于Int、UInt、Float等类型,表示左对齐。对应示例工程 BookSourceCode/CH2/Alignment:
package Alignment import std.convert main(): Int64 { var c:Int32 = -17 let s1 = c.format("-20") //20个字符,左对齐 println(s1) let s2 = c.format("20") //20个字符,默认右对齐 print(s2) return 0 }执行结果为:
-17 -17解析:
- 第 6 行:格式化参数
"-20"中的"-"属于flags字段,表示转换结果应为左对齐;"20"则属于width字段,表示结果字符串应包含 20 个字符,不足部分用空格补齐(因此第一行的-17后补了 17 个空格); - 第 9 行:格式化参数未要求左对齐,默认右对齐。如执行结果第 2 行所见,
format成员函数通过在左侧补充空格的方式满足 20 的宽度要求。
4.2 "+":正值输出加号
"+"适用于Int、UInt、Float,表示对正数输出+号。对应示例工程 BookSourceCode/CH2/Plus:
package Plus import std.convert main(): Int64 { var v1:Float32 = 7.1287 let s1 = v1.format("+") //给正值使用+,结果中会出现+号 println(s1) var v2:Float32 = -7.1287 let s2 = v2.format("+") //给负值使用+ print(s2) return 0 }执行结果为:
+7.128700 -7.128700可见正数结果被加上+号前缀;如执行结果第 2 行所见,当给负值使用"+"时,于转换结果不构成影响(负号-本就存在)。
4.3 "#":为转换结果添加进制符号
"#"为转换结果添加进制符号。具体地,为二进制结果补充0b或者0B,为 16 进制结果补充0x或者0X,为 8 进制结果补充0o或者0O。当输出结果为 10 进制时,不起作用。该符号预期与specifier中的进制符号x、b等联合使用。对应示例工程 BookSourceCode/CH2/Sharp:
package Sharp import std.convert main(): Int64 { var v = 125 println(v.format("#x")) println(v.format("x")) //x为specifier,意为16进制 println(v.format("#B")) println(v.format("B")) //B为specifier,意为2进制 //未指定进制,即为10进制,#号不起作用 print(v.format("#")) return 0 }执行结果为:
0x7d //x导致了7d, #号附加了0x 7d //没有#号,就没有0x 0B1111101 //B导致2进制结果,#号附加了0B 1111101 //没有#号,就没有0B 125 //对于10进制,#号不起作用4.4 "0":空位补零
"0"适用于Int、UInt和Float,用于在空位补0。对应示例工程 BookSourceCode/CH2/ZeroLeading:
package ZeroLeading import std.convert main(): Int64 { var v = 72.6386654 println(v.format("020")) //20个字符,不足前端补0 print(v.format("20")) //20个字符,不足前端补空格 return 0 }执行结果为:
0000000000072.638665 72.638665可以看出,宽度不足的补位默认使用空格,加上"0"标志后则改为补0,常用于生成固定位宽的时间戳、编号等展示。
5. width 宽度
v.format("20")中的20即为宽度。宽度应为正整数,适用于Int、UInt、Float等类型。宽度前有"-"表示左对齐,否则右对齐。对应示例工程 BookSourceCode/CH2/Width:
package Width import std.convert main(): Int64 { var v = 123456 println(v.format("20")) //自身占6个字符,前方补了14个空格 print(v.format("+20")) //连同+号占7个字符,前方补了13个空格 return 0 }执行结果为:
123456 +123456两点值得注意:
- 宽度指的是整个结果字符串的总字符数,而非数值本身占用的位数;
- 当同时使用
"+"标志时,符号也计入总宽度——"+123456"连同+号占 7 个字符,故前方只补了 13 个空格。
6. precision 精度
精度常用于指定浮点数小数点后的数字位数,如果不指定,则默认输出 6 位小数(第 2 节示例中Float32输出7.128700即为默认 6 位小数的体现)。对应示例工程 BookSourceCode/CH2/Precision:
package Precision import std.convert main(): Int64 { var v:Float64 = 12345.678987654321 println(v.format(".3")) //3位小数,四舍五入 println(v.format(".5")) //5位小数,四舍五入 print(v.format(".0")) //0位小数,四舍五入 return 0 }执行结果为:
12345.679 12345.67899 12346可以看到,精度截断时按四舍五入处理:.3使12345.6789…进位为12345.679;.0表示不保留小数,结果直接进位为整数12346。
7. specifier 进制与记数方式
7.1 b、B、o、O、x、X:指定进制(Int 与 UInt)
b、B、o、O、x、X用于指定进制,适用于Int和UInt类型:b为小写 2 进制、B为大写 2 进制;o为小写 8 进制、O为大写 8 进制;x为小写 16 进制、X为大写 16 进制;未指定时默认 10 进制。如前所述,上述进制符号可与flags中的"#"号配合使用。对应示例工程 BookSourceCode/CH2/Base:
package Base import std.convert main(): Int64 { var v = 4571 println(v.format("b")) println(v.format("B")) println(v.format("o")) println(v.format("O")) println(v.format("x")) print(v.format("X")) return 0 }执行结果为:
1000111011011 1000111011011 10733 10733 11db 11DB其中大小写 specifier 的差异主要体现在 16 进制的数字字母上(x输出11db,X输出11DB);2 进制与 8 进制本身只含数字,大小写结果相同。
7.2 e、E、g、G:科学计数法与自适应记数(Float)
e、E、g、G适用于Float类型:e表示小写的科学计数法,E表示大写的科学计数法;g或G源于 general(常规),表示让仓颉在科学计数法和普通 10 进制计数法中自动选择较为恰当的表达方式。对应示例工程 BookSourceCode/CH2/Scientific:
package Scientific import std.convert main(): Int64 { var a = 1234.5678987654321 println(a.format("e")) println(a.format(".3E")) println(a.format("g")) //自适应:常规10进制 var b = 228989289.1234234 print(b.format(".2G")) //自适应:科学计数法 return 0 }执行结果为:
1.234568e+03 //e 1.235E+03 //E 1234.57 //g 2.3E+08 //.2G从结果可以看出g/G的“自适应”行为:当数值较适中时(1234.5678…)选择常规 10 进制记数并截断为1234.57,当数值量级较大时(228989289.1234…)则自动切换为科学计数法2.3E+08,避免了普通记数方式下过长的数字串。
8. 格式化参数速查表
将全文内容汇总为速查表,便于日常编码时对照使用:
| 字段 | 位置 | 可选取值 | 适用类型 | 作用 |
|---|---|---|---|---|
flags | 最前 | -、+、#、0(可组合) | -/+/0适用 Int、UInt、Float;#配合进制 specifier | -左对齐;+正值加号;#添加0x/0b/0o等进制前缀;0空位补零 |
width | flags 之后 | 正整数 | Int、UInt、Float | 结果总宽度,不足时补空格(或按0标志补零);无-时默认右对齐 |
.precision | width 之后 | 以.引导的非负整数 | Float | 小数点后位数,默认 6 位,超出四舍五入 |
specifier | 最后 | b/B、o/O、x/X;e/E、g/G | 前者用于 Int、UInt;后者用于 Float | 指定进制或科学计数法/自适应记数方式;缺省为 10 进制 |
四个字段均为可选,可自由组合,例如第 2 节中的"+20.10"即为flags(+) + width(20) + .precision(10)的组合。
9. 随书源码工程的验证方式
文中所有示例均来自《仓颉编程基础及应用》随书源码目录 BookSourceCode/CH2,每个示例是独立的 cjpm 工程(含 cjpm.toml 与src/main.cj)。从工程配置 BookSourceCode/CH2/StrFormat/cjpm.toml 看,output-type为executable、cjc-version为0.57.3;仓库 README.md 说明源码整体按照仓颉 LTS 1.0.0 标准编写。因此适用前提是:本地安装兼容的仓颉工具链(cjc/cjpm)后,在任一示例工程目录下(如BookSourceCode/CH2/StrFormat)使用 cjpm 构建并运行即可复现本文各节的执行结果。
与format主题相关但属于不同技术面的扩展阅读,可参考同目录下的 使用 format-hex 以 16 进制格式查看文件内容(该文档讨论的是 Windows PowerShell 的format-hex命令,与本文的std.convert格式化函数并非同一技术),以及 仓颉位运算相关示例——理解了format的进制输出后,位运算结果用format("b")、format("x")展示会十分直观。
10. 小结
std.convert包通过扩展机制为整数与浮点类型提供format(fmt: String): String成员函数,将数值对象按指定样式转换为String,且不改变原对象;- 格式串语法为
[flags][width][.precision][specifier],四段均为可选:flags(-左对齐、+正值加号、#进制前缀、0补零)控制标志,width控制总宽度与补齐,.precision控制小数位数,specifier控制进制(b/B/o/O/x/X)或浮点记数方式(e/E/g/G); - 随书源码 BookSourceCode/CH2 下 StrFormat、Alignment、Plus、Sharp、ZeroLeading、Width、Precision、Base、Scientific 共 9 个工程与本文示例一一对应,可直接编译运行验证各格式化参数的实际效果。
- 示例工程
- 教程
【免费下载链接】仓颉编程基础及应用_陈波_何睿_重庆大学
《仓颉编程基础及应用》,清华大学出版社,2025年9月第1版: 1. 随书源代码; 2. PPT; 3.在线扩展阅读资料。
相关推荐
仓颉编程基础及应用入门教程2:初学者必会的10个数据类型与字符串格式化技巧
仓颉编程基础及应用入门教程2:初学者必会的10个数据类型与字符串格式化技巧 《仓颉编程基础及应用》入门教程2面向初学者和普通用户,聚焦仓颉编程中最常用的数据类型
示例工程教程DLSS Swapper 完整指南:免费给游戏换 DLSS、FSR、XeSS 版本还能一键还原
DLSS Swapper 完整指南:免费给游戏换 DLSS、FSR、XeSS 版本还能一键还原 DLSS Swapper 是一款免费开源的 Windows 工具
桌面应用大麦自动抢票脚本:把选座下单交给配置驱动
大麦自动抢票脚本:把选座下单交给配置驱动 开票瞬间手动点击往往慢半拍,页面先弹出缺货登记,票就没了。ticket purchase 把选城市、挑票价、勾观演人、
GUI 自动化RPA
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考