当前位置: 首页 > news >正文

仓颉编程语言青少年基础教程:输入输出

仓颉编程语言青少年基础教程:输入输出

仓颉编程语言v1.0.0的输入输出由标准库的core 包(std.core)和env 包(std.env)提供。标准库的convert包(std.convert),提供了类型转换和格式化功能。

什么是“输入 / 输出”?

• 输入(Input):程序从键盘、鼠标、文件或网络读取数据。

• 输出(Output):程序把结果展示到屏幕、文件或网络。

env 包中print()、println()和readln()介绍

print()、println()和readln(),这些函数属于标准库的env 包

基本输入输出功能由标准库核心包std.core提供,该包无需显式导入,默认即可使用。其输入输出能力围绕 “控制台输出” 和 “控制台输入”。

【core 包是标准库的核心包,提供了适用仓颉语言编程最基本的一些 API 能力。

提供了内置类型(有符号整型、无符号整型、浮点型等)、常用函数(print、println、eprint 等)、常用接口(ToString、Hashable、Equatable、Collection 等)、常用类和结构体(Array、String、Range 等)、常用异常类(Error、Exception 以及它们的一些细分子类)。

core 包不需要显式导入,默认导入。写不写import std.core.*  都可以。显式写 import std.core.* 不会报错,但多余。

仓颉编程语言标准库(std)是安装仓颉 SDK 时默认自带的库。标准库预先定义了一组函数、类、结构体等,旨在提供常用的功能和工具,以便开发者能够更快速、更高效地编写程序。

标准库包含了若干包(package),而包是编译的最小单元。包可以定义子包,从而构成树形结构。

没有父包的包称为 root(根)包,root 包及其子包(包括子包的子包)构成的整棵树称为模块(module)。】

控制台输出print()和println()函数

仓颉编程语言的print()和println()输出是程序最基础的功能,其中println()会自动追加换行符。

  •  print:仅将数据的 “字符串表达” 输出到控制台,输出后光标停留在当前行末尾,后续输出会紧跟当前内容。

  •  println:在将数据 “字符串表达”输出到控制台后,自动追加一个换行符(\n),光标跳转至下一行开头。

例如:

main() {    println("这是println输出,自动换行")print("这是print输出,不自动换行。")print("这也是print输出。")
}

编译运行截图:

控制台输入:readln () 函数

控制台输入功能由readln()函数单独实现,用于接收用户从控制台输入的文本内容,直到遇到换行或EOF结束。

示例:(读一行)

源码如下:

import std.convert.* //使用Parse()函数用到main() {// 示例1:获取用户输入并直接输出print("请输入你的名字:");  // 提示用户输入let name = readln();          // 接收用户输入的名字(字符串类型)println("你好,${name}!");  // 输出问候语,如输入“Bob”,则输出“你好,Bob!”// 示例2:获取输入并转换为其他类型(需结合类型转换API)print("请输入你的年龄:");let ageStr = readln();                // 先获取输入的字符串let age = Int32.parse(ageStr);        // Parse()函数,将字符串转为 Int32println("你的年龄是:${age}");  // 输出转换后的年龄
}

编译运行截图:

插值字符串

在仓颉编程语言中,输出语句中的 ${} 用于在字符串中内嵌表达式并进行格式化输出。语法:

${expression}

示例源码:

main() {// 1.基本变量插值let name = "仓颉"let version = "1.0"println("欢迎使用 ${name} ${version}")println("-------")// 2.表达式插值let a = 7let b = 3println("a + b = ${a + b}")println("-------")// 3.函数调用结果    func max(a: Int64, b: Int64): Int64 { if (a > b) {a} else {b}}let m = max(5, 9)println("较大值:${m}")println("-------")// 4.多行字符串中的插值let lang = "仓颉"let lines = """${lang}语言版本 1.0"""println(lines)println("-------")//5.转义与嵌套大括号let left = "{"let right = "}"println("转义示例:${left}内容${right}")
}

运行输出:

欢迎使用 仓颉 1.0
-------     
a + b = 10  
-------     
较大值:9   
-------     
    仓颉语言
    版本 1.0

-------
转义示例:{内容}

 

env 包的标准输入、标准输出介绍

标准库的env 包(std. env)提供当前进程的相关信息与功能、包括环境变量、命令行参数、标准流、退出程序。也提供标准输入、标准输出、标准错误进行交互的方法。

getStdIn().readln() 从标准输入中读取字符串。

getStdIn().read() 从标准输入中读取一个字符。

getStdOut().write() 从标准输出中输出字符串,不自动换行。

getStdOut().writeln() 从标准输出中输出字符串,并自动换行。

【错误流通常也支持类似write()/writeln()的方法(用于输出错误信息)。

getStdErr()  获取当前进程标准错误流。

getStdIn()           获取当前进程标准输入流。

getStdOut()  获取当前进程标准输出流。

补充说明

• 标准输入(stdin):键盘 → 程序
• 标准输出(stdout):程序 → 屏幕
• 标准错误(stderr):程序 → 屏幕(专门报错)

标准输入,接收外部输入数据的默认来源,通常是键盘(用户通过键盘输入内容)。

标准输出,输出正常结果的默认目的地,通常是控制台(终端窗口),用户可以直接看到输出内容。

标准错误,输出错误信息的专用数据流,通常也是控制台(和 标准输出 看起来一样),但逻辑上是独立的流,输出错误、警告、诊断信息。

本包提供多平台统一操控能力,目前支持 Linux 平台,macOS 平台,Windows 平台与 HarmonyOS 平台。】

下面给出示例。

字符串级读(读一行)

方式1:使用readln()

readln()能从标准输入中读取字符串,示例见前面。

import 语句导入其它包中的声明或定义】

方式2:使用getStdIn().readln()  ,功能类似std.core的readln()

需要使用 import —— import std.env.*

源码如下:

字符串级读(读一行)

方式1:使用readln()

readln()能从标准输入中读取字符串,示例见前面。

import 语句导入其它包中的声明或定义】

方式2:使用getStdIn().readln()  ,功能类似std.core的readln()

需要使用 import —— import std.env.*

源码如下:

import std.env.*main() {getStdOut().write("请输入:")          // 可换 print("请输入:")var line = getStdIn().readln()     // 读取字符串var r = line.getOrThrow()           // 拆包getStdOut().writeln("你输入的是:${r}")  // 可换 println("你输入的是:${line}")
}

说明:其中两行

    var line = getStdIn().readln()     // 读取字符串

    var r = line.getOrThrow()           // 拆包

可写为一行

var line = getStdIn().readln().getOrThrow()  //读取字符串, 并拆包

编译运行截图:

字符级读

可以用getStdIn().read()读取一个字符。示例源码如下:

import std.env.*main() {  print("请输入字符:")   let c = getStdIn().read().getOrThrow()  // 读取一个字符,并拆包println("你输入的字符是: ${c}")getStdOut().writeln("你输入的字符是: ${c}")
}

编译运行

请输入字符:中国
你输入的字符是: 中
你输入的字符是: 中

字节级别(二进制场景)读

示例源码如下

import std.env.*main() {let buf: Array<UInt8> = [0, 0, 0, 0]  // 创建一个长度为4的UInt8数组(可容纳4个字节)print("请输入:") let n = getStdIn().read(buf) // 从标准输入读取字节,存入bufprintln("读到 ${n} 字节:${buf[..n]}") //输出字节值// 遍历打印读取到的字节值for (i in 0..n) {print("${buf[i]} ")}
}

编译运行

请输入:中华人民共和国
读到 4 字节:[228, 184, 173, 229]
228 184 173 229

说明:

1.缓冲区大小

buf 只有 4 个 UInt8,所以 getStdIn().read(buf) 最多读 4 个字节。

2.汉字 UTF-8 长度

“中”的 UTF-8 编码:E4 B8 AD → 3 字节

“华”的 UTF-8 编码:E5 8D 8E → 3 字节

3.字节只能装下 E4 B8 AD E5,于是你看到数组里恰好是

[0xE4, 0xB8, 0xAD, 0xE5] → 十进制 [228, 184, 173, 229]

4.后续字节仍在输入缓冲区

剩下的 8D 8E ... 还留在系统输入队列中;下次再读就能拿到。

convert包的常用功能介绍

标准库的convert包(std.convert)提供了强大的类型转换和格式化功能

  •  类型转换:支持将字符串解析为特定类型,也支持将其他类型转换为字符串。如其中Parsable<T>接口提供常规转换parse和tryParse函数。

  •  格式化输出:格式化format函数功能,可将数据类型转换为指定格式的字符串(如控制宽度、对齐方式、进制、小数精度等)。

类型转换

parse函数和tryParse函数的区别

  •  parse 转换失败 直接抛异常,程序会当场崩溃(IllegalArgumentException)。

  •  tryParse 转换失败 不抛异常,而是返回一个 Option(选项) 包裹的结果:

        – 成功 → Some(值)

        – 失败 → None

示例 1:使用parse函数常规转换,可以使用try-catch处理已知可能异常的情况:

import std.convert.*main() {// 1. Bool转换let boolVal = Bool.parse("true");println("Bool转换结果:${boolVal}"); // 输出:true// 2. Int32转换(带负号)let intVal = Int32.parse("-456");println("Int32转换结果:${intVal}"); // 输出:-456// 3. Float64转换(科学计数法)let floatVal = Float64.parse("3.14e2");println("Float64转换结果:${floatVal}"); // 输出:314.0// 以下代码会抛IllegalArgumentException(演示异常场景)// let invalidInt = Int32.parse("123a"); // 含非数字字符// let overflowInt = Int8.parse("128"); // 超出Int8范围(127)
}

示例 2:使用tryParse函数,需通过 “模式匹配” 或 “判空” 处理结果,适合不确定输入是否合法的场景:

import std.convert.*;main(){/* 例 1:Int32 失败 */let maybeInt = Int32.tryParse("abc")match (maybeInt) {case Some(v) => println("Int32 成功:${v}")case None    => println("Int32 失败:不是整数")}/* 例 2:UInt8 成功 */let maybeUint = UInt8.tryParse("255")match (maybeUint) {case Some(u) => println("UInt8 成功:${u}")case None    => println("UInt8 失败")}/* 例 3:Rune 失败(长度≠1)*/let maybeRune = Rune.tryParse("AB")if (maybeRune.isNone()) {println("Rune 失败:长度不为 1")}
}

示例3,输入一个数,判断它的奇偶性:

import std.convert.*
main() {print("请输入一个整数:")var str: String  = readln()var n =  Int64.parse(str)// 判断奇偶if (n % 2 == 0) {println("${n} 是偶数")} else {println("${n} 是奇数")}
}

或写为:

import std.env.*
import std.convert.*
main() {getStdOut().write("请输入一个整数:")          // 可换 print("请输入一个整数:")var str: String  = getStdIn().readln().getOrThrow()  //读取字符串, 并拆包var n =  Int64.parse(str)// 判断奇偶if (n % 2 == 0) {println("${n} 是偶数")} else {println("${n} 是奇数")}
}

format函数格式化功能

尽管 format函数 支持 “实例.点语法” 这种类似方法的调用方式,但核心依据官方接口的 static func 声明,以及 “语法糖不改变本质” 的原则,其规范名称仍是 “函数”(更具体地说,是 “静态函数”)。

基本调用格式

value.format(format_spec)

其中:

  •  value:要格式化的值(任何实现了Formattable接口的类型)

  •  format_spec:格式说明符字符串,遵循特定语法:[flags][width][.precision][specifier]

format_spec(格式说明符)部分的说明:

1. flags(标志位)

用于控制对齐方式、符号显示、进制前缀等,支持 4 种标志:

标志

适用类型

功能说明

-

Int、UInt、Rune、Float

左对齐,空位补在右侧(默认右对齐)。

+

Int、UInt、Float

正数强制显示+号,负数仍显示-号。

#

Int、UInt(进制转换时)

为进制格式添加前缀:二进制(0b/0B)、八进制(0o/0O)、十六进制(0x/0X)。

0

Int、UInt、Float

空位用0填充(而非默认空格)。

示例

import std.convert.*main() {var num: Int32 = 20;// 左对齐(宽度10)print("\"${num.format("-10")}\"\n");  // 输出:"20        "// 强制显示正号(宽度10,右对齐)print("\"${num.format("+10")}\"\n");  // 输出:"       +20"// 十六进制加前缀(宽度10)print("\"${num.format("#10x")}\"\n"); // 输出:"       0x14"// 0填充(宽度10)print("\"${num.format("010")}\"\n");  // 输出:"0000000020"
}

2. width(宽度)

指定输出字符串的最小宽度(正整数),若实际内容长度小于宽度,则用空格(或0,若指定0标志)填充;如果实际值宽度大于指定宽度,不会截断:

  •  无符号:默认右对齐,空位补在左侧。

  •  带-:左对齐,空位补在右侧。

  •  若内容长度超过宽度,不截断,按实际长度输出。

  •  符号(+/-)和进制前缀(如0x)会占用宽度计数。

示例:

import std.convert.*main() {var num: Int32 = 20;// 宽度1(小于实际长度2,不截断)println("\"${num.format("1")}\"");  // 输出:"20"// 宽度4,带正号(+占用1个字符位)println("\"${num.format("+4")}\""); // 输出:" +20"
}

3. precision(精度)

以.开头的正整数,对整数和浮点数的影响不同,对于浮点数:指定小数位数;对于整数:指定最小数字位数(不足时用前导零填充):

类型

功能说明

浮点数

控制小数点后有效数字的位数:
- 不足则补位(不一定补 0);
- 超过则四舍五入;
- 未指定时默认保留 6 位小数。

整数

控制最小位数:
- 不足则在前面补0;
- 超过则无效果。

示例:

import std.convert.*main() {var f: Float64 = -1234.123456;// 浮点数:精度4(保留4位小数)println("\"${f.format(".4")}\"");  // 输出:"-1234.1235"// 浮点数:精度20(保留20位小数)println("\"${f.format(".20")}\"");  // 输出:"-1234.12345600000003287278"
}

4. specifier(格式符)

指定数据的输出格式(如进制、科学计数法等),不同类型支持的格式符不同:

格式符

适用类型

功能说明

b/B

Int、UInt

二进制格式输出(b小写,B大写,仅影响进制前缀,如0b/0B)。

o/O

Int、UInt

八进制格式输出(o对应0o前缀,O对应0O前缀)。

x/X

Int、UInt

十六进制格式输出(x对应0x前缀,X对应0x前缀,字母部分x小写、X大写)。

e/E

Float

科学计数法输出(e对应小写e,E对应大写E)。

g/G

Float

自动选择精简格式(十进制或科学计数法,优先更短的表示)。

示例:

import std.convert.*main() {// 整数进制转换var num: Int32 = 20;println("二进制: ${num.format("b")}");    // 输出:"10100"println("八进制: ${num.format("o")}");    // 输出:"24"println("十六进制: ${num.format("x")}");  // 输出:"14"println("带前缀十六进制: ${num.format("#X")}");  // 输出:"0X14"// 浮点数格式var f: Float32 = 1234.1;var largeF: Float32 = 123412341234.1;println("科学计数法: ${f.format("20.2e")}");  // 输出:"            1.23e+03"println("精简格式: ${largeF.format("20G")}");  // 输出:"         1.23412E+11"
}

最后,给出一个format函数综合示例:

import std.convert.*main() {// 整数格式化示例let num = 12345// 基本格式化println(num.format(""))          // 默认格式: "12345"println(num.format("10"))      // 宽度10,右对齐: "     12345"println(num.format("-10"))     // 宽度10,左对齐: "12345     "println(num.format("010"))     // 宽度10,零填充: "0000012345"println(num.format("+10"))     // 显示正号: "    +12345"// 进制格式化println(num.format("b"))       // 二进制: "11000000111001"println(num.format("o"))       // 八进制: "30071"println(num.format("x"))       // 十六进制(小写x): "3039"println(num.format("X"))       // 十六进制(大写X): "3039"println(num.format("#x"))      // 带前缀十六进制: "0x3039"// 浮点数格式化示例let pi = 3.1415926535// 小数精度控制println(pi.format(""))           // 默认: "3.141593"println(pi.format(".2"))       // 2位小数: "3.14"println(pi.format(".5"))       // 5位小数: "3.14159"// 科学计数法println(pi.format(".3e"))      // 科学计数法,3位小数: "3.142e+00"println(pi.format(".3E"))      // 科学计数法(大写),3位小数: "3.142E+00"// 通用格式println(pi.format(".3g"))      // 通用格式,3位有效数字: "3.14"// 组合使用println(pi.format("-10.2e"))   // 左对齐,宽度10,科学计数法: "3.14e+00  "     
}

http://www.xdnf.cn/news/1382581.html

相关文章:

  • 模拟实现Linux中的进度条
  • [Mysql数据库] 知识点总结5
  • 天津医科大学肿瘤医院冷热源群控系统调试完成:以 “精准控温 + 高效节能” 守护医疗核心场景
  • 实战演练(一):从零构建一个功能完备的Todo List应用
  • Spring事务管理机制深度解析:从JDBC基础到Spring高级实现
  • 力扣(LeetCode) ——965. 单值二叉树(C语言)
  • C#写的一键自动测灯带的应用 AI帮写的。
  • [灵动微电子 MM32BIN560CN MM32SPIN0280]读懂电机MCU之串口DMA
  • list 手动实现 1
  • 学习日志40 python
  • 微服务即时通信系统(十三)--- 项目部署
  • 【后端】微服务后端鉴权方案
  • 虚函数指针和虚函数表的创建时机和存放位置
  • 【Linux知识】Linux 设置账号密码永不过期
  • 完整代码注释:实现 Qt 的 TCP 客户端,实现和服务器通信
  • 【LINUX网络】TCP原理
  • WEEX唯客上线C2C交易平台:打造安全便捷的用户交易体验
  • 现在购买PCIe 5.0 SSD是否是最好的时机?
  • 前端实现Linux查询平台:打造高效运维工作流
  • [光学原理与应用-320]:光学产品不同阶段使用的工具软件、对应的输出文件
  • 华为S5720S重置密码
  • c语言动态数组扩容
  • MCU平台化实践方案
  • STL库——list(类函数学习)
  • 财务数据报销画像技术实现:从数据采集到智能决策的全流程解析
  • 【AI自动化】VSCode+Playwright+codegen+nodejs自动化脚本生成
  • 当new一块内存时,操作系统做了哪些事情
  • 软考 系统架构设计师系列知识点之杂项集萃(134)
  • leetcode算法刷题的第二十天
  • 鸿蒙OS与Rust整合开发流程