• 36期怎么提交才会有成绩呢?
    按照要求实现了接口,但都是0分。
  • [问题求助] 35期提交作品出现这个是为什么哇
     35期提交作品出现这个是为什么哇 
  • 求哪路大神帮帮忙吧
    运行模拟器就报这个错误
  • [区域初赛赛题问题] 请问初赛证书怎么获取?
    您好,请问2025年华为软挑初赛证书怎么获取?
  • [知识分享] 开发者技术支持 - 从系统相册选择照片后,怎么获取照片的位置信息
    一、 关键技术难点总结1.1 问题说明从相册选择图片后,获取不到照片的位置信息。1.2 原因分析图片的经纬度信息存储在EXIF里,对应的key是:GPS_LONGITUDE和GPS_LATITUDE。图片工具当前主要提供图片EXIF信息的读取与编辑能力。EXIF(Exchangeable image file format)是专门为数码相机的照片设定的文件格式,可以记录数码照片的属性信息和拍摄数据。当前仅支持JPEG格式图片。1.3 解决思路在图库等应用中,需要查看或修改数码照片的EXIF信息。由于摄像机的手动镜头的参数无法自动写入到EXIF信息中或者因为相机断电等原因经常会导致拍摄时间出错,这时候就需要手动修改错误的EXIF数据,即可使用本功能。1.4 解决方案1、鸿蒙中图片怎么读取exif信息获取图片信息,需要先将图库图片拷贝到沙箱路径中。当需要调用图片信息时,使用PhotoViewPicker选择指定的图片资源,文件选择成功后,返回PhotoSelectResult结果集。将图库图片复制到沙箱中的参考代码如下:async photoPick() {try {let PhotoSelectOptions = new photoAccessHelper.PhotoSelectOptions();PhotoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;PhotoSelectOptions.maxSelectNumber = 5;let photoPicker = new photoAccessHelper.PhotoViewPicker();photoPicker.select(PhotoSelectOptions).then(async (PhotoSelectResult: photoAccessHelper.PhotoSelectResult) => {console.info('PhotoViewPicker.select successfully, PhotoSelectResult uri: ’ +JSON.stringify(PhotoSelectResult));let file1 = fs.openSync(PhotoSelectResult.photoUris[0])fs.copyFileSync(file1.fd, data/storage/el2/base/haps/entry/files/${file1.name})let file2 = fs.openSync(data/storage/el2/base/haps/entry/files/${file1.name}, fs.OpenMode.READ_WRITE)console.log(file fd ==> ${file2.fd} | file path ==> ${file2.path})this.filePath = file2.path}).catch((err: BusinessError) => {console.error('PhotoViewPicker.select failed with err: ’ + JSON.stringify(err));});} catch (error) {let err: BusinessError = error as BusinessError;console.error('PhotoViewPicker failed with err: ’ + JSON.stringify(err));}}2、将图片拷贝到沙箱路径中后,使用ImageSource对图片进行解码,再通过getImageInfo获取图片信息或getImageProperty获取指定的图片属性值。注意:getImageProperty仅支持JPEG、PNG和HEIF12+(不同硬件设备支持情况不同)文件,且需要包含exif信息,获取的属性值必须是图片属性中存在的,不存在的话则会返回ImagePropertyOptions中的设定值defaultValue。参考代码如下:private async getImageCoordinates() {console.log(‘输出:filePath’,this.filePath)let imageSource = image.createImageSource(this.filePath);const keys = [image.PropertyKey.GPS_LATITUDE,image.PropertyKey.GPS_LONGITUDE,image.PropertyKey.GPS_LATITUDE_REF,image.PropertyKey.GPS_LONGITUDE_REF]imageSource.getImageProperties(keys).then((data) => {console.info('批量获取图片中的指定属性键的值success: ',JSON.stringify(data));// 提取GPS数据const latitudeDms = data[image.PropertyKey.GPS_LATITUDE] as string;const longitudeDms = data[image.PropertyKey.GPS_LONGITUDE] as string;const latitudeRef = data[image.PropertyKey.GPS_LATITUDE_REF] as string;const longitudeRef = data[image.PropertyKey.GPS_LONGITUDE_REF] as string; // 转换为十进制 const latitude = this.dmsToDecimal(latitudeDms, latitudeRef); const longitude = this.dmsToDecimal(longitudeDms, longitudeRef); // 输出结果 console.log('原始GPS数据:'); console.log('纬度:', latitudeDms, latitudeRef); console.log('经度:', longitudeDms, longitudeRef); console.log('转换后的十进制坐标:'); console.log('纬度:', latitude); console.log('经度:', longitude); console.log('坐标格式:', `${latitude}, ${longitude}`); }).catch((err: BusinessError) => { console.error('批量获取图片中的指定属性键的值error: ', JSON.stringify(err)); }); // 获取指定序号的图片信息 let imageInfo = imageSource.getImageInfoSync(0); console.log('获取指定序号的图片信息', JSON.stringify(imageInfo)) if (imageInfo == undefined) { console.error('Failed to obtain the image information.'); } else { console.info('Succeeded in obtaining the image information.', JSON.stringify(imageInfo)); }}// 将度分秒格式的GPS坐标转换为十进制格式dmsToDecimal(dms: string, ref: string): number {// 去除空格并按逗号分割const parts = dms.replace(/\s+/g, ‘’).split(‘,’);if (parts.length !== 3) return NaN;// 解析度、分、秒const deg = parseFloat(parts[0]);const min = parseFloat(parts[1]);const sec = parseFloat(parts[2]);// 计算十进制值let decimal = deg + min / 60 + sec / 3600;// 根据参考方向调整正负if (ref === ‘S’ || ref === ‘W’) {decimal = -decimal;}return decimal;}3、参考链接:获取图片经纬度信息:https://developer.huawei.com/consumer/cn/forum/topic/0208180370773931585?fid=0109140870620153026,https://developer.huawei.com/consumer/cn/forum/topic/0202178283677576203
  • [知识分享] 开发者技术支持-短视频列表如何实现连续播放
    1.问题说明:播放视频时无法自动连播,声音会重复2.原因分析:没有监听播放结束状态和释放视频资源3.解决思路:(1) Swiper 滑动切换机制(2) 视频播放器生命周期管理(3) 自动播放下一条视频机制4.解决方案:整体架构设计短视频连续播放功能主要通过以下核心组件协同实现:ShortVideoPage:页面主体,负责视频列表管理、滑动切换控制和全局状态协调ShortVideoView:单个视频播放组件,独立管理自己的播放器实例和播放状态Swiper:垂直滑动组件,实现视频间的流畅切换体验核心实现机制详解(1) Swiper 滑动切换机制  Swiper(this.swiperController) { LazyForEach(this.lazyVideoListData, (item: ChannelItemBean, index: number) => { ShortVideoView({ // ... 参数传递 }) })}.vertical(true) // 垂直滑动模式,模拟抖音式浏览体验.index(this.curIndex) // 当前播放视频索引,用于定位当前播放项.onChange((index: number) => { this.onSwiperItemChange(index) // 滑动切换时的回调处理,包括数据更新和统计上报})(2) 视频播放器生命周期管理每个 ShortVideoView 组件采用独立的播放器生命周期管理策略:  // ShortVideoView.ets@Link @Watch('createOrFinish') selectedVideoUrl: string; // 当前选中播放的视频URL// 基于选中状态精确控制播放器的创建和销毁createOrFinish(): void { if (this.videoUrl == this.selectedVideoUrl) { this.init(); // 初始化并开始播放当前视频 } else { this.getStop(); this.release(); // 停止并释放非当前播放的视频资源 }}3) 自动播放下一条视频机制通过事件发射器机制实现自动播放下一条视频:  // 在 ShortVideoView.ets 中,播放完成时发送事件case 'completed': emitter.emit(EventConst.SHORT_VIDEO_SHOW_NEXT) // 发送播放完成事件通知 this.removeRecentVideo() // 移除已播放完成的视频进度记录 this.callbackComplete?.(); this.showLoading = false break;// 在 ShortVideoPage.ets 中监听事件并处理自动播放private onEmitter() { // 注册监听播放完成事件,实现续播下一条视频 emitter.on(EventConst.SHORT_VIDEO_SHOW_NEXT, () => { this.onAutoNext() })}private onAutoNext() { Logger.info(TAG, `onAutoNext`) this.swiperController.showNext() // 自动滑动到下一个视频项 this.atype = 'auto' // 标记为自动播放类型 this.ptype = 'order' // 标记为顺序播放模式}完整播放流程初始化播放:进入页面时,根据当前索引初始化第一个视频播放器,加载并播放视频内容滑动切换:用户上下滑动时,Swiper 的 onChange 回调更新当前索引,并触发相应业务逻辑播放器精细化管理:新显示的视频组件通过 @Watch 监听 selectedVideoUrl 变化调用 createOrFinish 方法决定是否初始化播放器实例隐藏的视频组件会自动停止播放并释放系统资源,避免资源浪费自动连续播放:当前视频播放完成后,通过事件机制通知页面自动切换到下一个视频,实现无缝续播体验关键优化技术点资源智能管理:通过 @Watch 和 createOrFinish 方法精确控制播放器的创建和释放,确保同时只有一个视频在播放,大大节省系统资源懒加载机制:使用 LazyForEach 实现视频列表的按需加载,提升页面初始化性能全局状态共享:通过 @Provide/@Consume 实现播放状态、控制器显示等全局状态的实时同步事件驱动架构:利用 emitter 实现组件间解耦通信,提高系统可维护性播放进度续播:通过 RECENT_VIDEOS 存储播放进度,支持用户中断后继续观看性能监控统计:完善的日志记录和播放数据统计,便于问题排查和用户体验优化这种精心设计的架构确保了在垂直滑动浏览短视频时能够提供流畅的连续播放体验,同时通过精细化的资源管理避免了系统性能问题。
  • 鸿蒙开发har模块内部怎么进行页面路由跳转
    router.pushUrl({ url:url }) this.getUIContext().getRouter().pushNamedRoute({ name:"qrCode" })//都不管用
  • [技术交流] 使用SQLite的ORM框架时对于boolean型数据的处理
    数据库相关文章:https://developer.huawei.com/consumer/cn/blog/topic/03191259102976177对于数据库中的数据类型处理时布尔值,如果直接给表格定义如:db.execDML(‘ALTER TABLE tb_user ADD COLUMN is_student boolean’)@TableField({name:“is_student”,type:FieldType.BOOLEAN})这样定义是没有值的我们需要定义成为db.execDML(‘ALTER TABLE tb_user ADD COLUMN is_student integer’);@TableField({name:“is_student”,type:FieldType.NUMBER})使用和取值都不会影响,因为ORM 框架会自动转换
  • [交流吐槽] 开发者技术支持-TextInput 渲染后如何控制不自动聚焦
    一、关键技术难点总结关键技术难点总结,说明问题,痛点总结,技术总结,效果总结。0.1 问题说明在鸿蒙应用开发中,使用 TextInput 组件进行页面渲染后,该组件会自动获取焦点,弹出输入法键盘。这一默认行为在部分场景下不符合用户预期,例如表单页面初始加载时无需立即输入、列表中包含 TextInput 项时滚动触发不必要聚焦等,影响用户操作体验。0.2 原因分析组件默认属性配置:TextInput 组件在鸿蒙 ArkUI 框架中存在默认的焦点获取机制,当组件渲染完成后,系统会自动将焦点分配给该组件,触发输入法弹出。缺乏直接控制 API:框架未提供专门用于禁用 TextInput 自动聚焦的属性或方法,开发者无法通过简单配置直接关闭该行为。页面渲染时序影响:在页面布局复杂或组件动态加载场景中,组件渲染完成的时序与焦点分配逻辑存在关联,手动干预焦点的时机难以精准控制,易出现聚焦逻辑失效的情况。0.3 解决思路利用焦点管理 API:通过鸿蒙框架提供的焦点管理相关接口,在 TextInput 组件渲染完成后主动移除其焦点状态。动态控制焦点属性:结合组件的生命周期函数,在组件加载完成后动态设置焦点相关属性,覆盖默认的自动聚焦行为。布局层级优化:通过调整组件在页面布局中的层级或父容器属性,减少系统默认焦点分配机制对 TextInput 组件的影响。0.4 解决方案基于焦点管理 API 的控制方法借助鸿蒙 ArkUI 提供的FocusScope和focusControl模块,实现对 TextInput 焦点的手动控制。在组件渲染完成后,通过focusControl.clearFocus()方法清除焦点,阻止自动聚焦。      import { FocusScope, focusControl } from '@ohos.arkui.focus';import { onPageShow } from '@ohos.arkui.page';@Entry@Componentstruct TextInputPage { private textInputController: TextInputController = new TextInputController(); onPageShow() { // 页面显示后清除焦点 focusControl.clearFocus(); } build() { FocusScope() { Column() { TextInput({ placeholder: '请输入内容', controller: this.textInputController }) .width('90%') .height(40) .border({ width: 1 }) } .width('100%') .height('100%') .padding(16) } }} 结合组件生命周期的动态控制利用组件的aboutToAppear或onAppear生命周期函数,在组件即将显示或已显示时,通过设置focusable属性为false临时禁用焦点,待组件稳定后根据需要再启用。    @Componentstruct CustomTextInput { @State isFocusable: boolean = false; onAppear() { // 组件显示后延迟设置可聚焦,避免初始自动聚焦 setTimeout(() => { this.isFocusable = true; }, 100); } build() { TextInput({ placeholder: '请输入内容' }) .width('90%') .height(40) .border({ width: 1 }) .focusable(this.isFocusable) }}@Entry@Componentstruct TextInputPage { build() { Column() { CustomTextInput() } .width('100%') .height('100%') .padding(16) }}
  • [知识分享] 开发者技术支持-鸿蒙 Glide加载网络图片
    1.引入glide依赖 implementation 'io.openharmony.tpc.thirdlib:glide:1.0.3'2.核心代码: //new RoundedCorners(10)圆角 //new CircleCrop()-圆形 RequestOptions requestOptions = RequestOptions.centerCropTransform().transform(new CircleCrop()).diskCacheStrategy(DiskCacheStrategy.NONE)//不做磁盘缓存 .skipMemoryCache(true).placeholder(ResourceTable.Media_boy).error(ResourceTable.Media_boy);//不做内存缓存; Glide.with(getContext()) .load("https://xxx.png") .apply(requestOptions) .into(user_icon);
  • [技术干货] 使用split分割字符串的时候,数组会比实际长度大1
    使用split分割字符串的时候,数组会比实际长度大1 原因:是会多出一个字符 如这个例子:const count = ('AAAA').split('A').length 此时结果是5 原始字符串: AAAA 分隔符: A 分割过程: "" + A + "" + A + "" + A + "" + A + "" 结果数组: ["", "", "", "", ""]
  • [知识分享] 开发者技术支持-AppstorageV2用法
    AppStorageV2是在应用UI启动时会被创建的单例。它的目的是为了提供应用状态数据的中心存储,这些状态数据在应用级别都是可访问的。AppStorageV2将在应用运行过程保留其数据。数据通过唯一的键字符串值访问。需要注意的是,AppStorage与AppStorageV2之间的数据互不共享。AppStorageV2可以修改connect的返回值,实现与UI组件的同步。AppStorageV2支持应用的主线程内多个UIAbility实例间的状态共享。AppStorageV2是ArkUI中用于应用全局UI状态存储的模块,它提供了持久化存储和管理应用状态的能力。以下是AppStorageV2的详细用法: connect:AppStorageV2提供了connect方法,用于将键值对数据存储在应用内存中。如果给定的key已经存在于AppStorageV2中,返回对应的值;否则,通过获取默认值的构造器构造默认值,并返回。// 将key为SampleClass、value为new SampleClass()对象的键值对存储到内存中,并赋值给as1 const as1: SampleClass|undefined = AppStorageV2.connect(SampleClass, () => new SampleClass());  // 将key为key_as2、value为new SampleClass()对象的键值对存储到内存中,并赋值给as2 const as2: SampleClass = AppStorageV2.connect(SampleClass, 'key_as2', () => new SampleClass())!;  // key为SampleClass已经在AppStorageV2中,将key为SampleClass的值返回给as3 const as3: SampleClass = AppStorageV2.connect(SampleClass) as SampleClass;remove:移除数据使用remove方法可以从AppStorageV2中删除指定的键值对数据:// 从AppStorageV2中删除key为key_as2的键值对数据 AppStorageV2.remove('key_as2');  // 从AppStorageV2中删除key为SampleClass的键值对数据 AppStorageV2.remove(SampleClass);keys:获取所有键使用keys方法可以获取AppStorageV2中的所有key:// 获取AppStorageV2中的所有key const keys: Array<string> = AppStorageV2.keys();以下是一个完整的示例,展示了如何使用AppStorageV2进行状态管理:import { AppStorageV2 } from '@kit.ArkUI';  @ObservedV2 class SampleClass {   @Trace p: number = 0 ;}  // 将key为SampleClass、value为new SampleClass()对象的键值对存储到内存中,并赋值给as1 const as1: SampleClass | undefined = AppStorageV2.connect(SampleClass, () => new SampleClass());  // 将key为key_as2、value为new SampleClass()对象的键值对存储到内存中,并赋值给as2 const as2: SampleClass = AppStorageV2.connect(SampleClass, 'key_as2', () => new SampleClass())!;  // key为SampleClass已经在AppStorageV2中,将key为SampleClass的值返回给as3 const as3: SampleClass = AppStorageV2.connect(SampleClass) as SampleClass;  // 从AppStorageV2中删除key为key_as2的键值对数据 AppStorageV2.remove('key_as2');  // 获取AppStorageV2中的所有keyconst keys:  Array<string> = AppStorageV2.keys();通过以上方法,开发者可以方便地在ArkUI应用中进行全局状态管理。
  • [问题求助] LINK平台上开发 uuid怎么生成
    LINK平台上  uuid怎么生成
  • [问题求助] 第三十期叙述不明确的若干问题.
    附件中给出的evaluation.py用处是什么??  在线上会调用我写的evaluation吗?我如果想提交一个有效的提交, 哪些文件是必要的? data文件夹需要吗, 代码的输出结果是直接放到提交的根目录还是data文件夹下?是否支持用pyTorch, 我可以自己添加第三方库吗, 不然怎么写ai, 难道自己再写一套轮子不成.
  • [案例共创] 【案例共创】基于 华为开发者空间+仓颉 完成健康指数计算器开发实践
    1. 仓颉编程语言介绍:设计理念与特性在编程语言领域,仓颉语言(https://cangjie-lang.cn/docs?url=%2F0.53.18%2Fwhite_paper%2Fsource_zh_cn%2Fcj-wp-abstract.html)的出现并非偶然。随着万物互联与智能时代的到来,软件开发的需求日益复杂,传统的编程语言已难以完全满足现代应用的高效、安全与并发需求。仓颉语言正是为解决这些问题而生,它通过一系列现代语言特性与工具链支持,为开发者提供了更友好的开发体验和更卓越的性能表现。首先,仓颉语言注重高效编程。它支持多种编程范式,包括函数式、命令式和面向对象编程,并通过类型推断、简洁语法和领域专用语言(DSL)的支持,显著降低了开发者的学习门槛和心智负担。开发者可以用更少的代码表达更复杂的逻辑,从而提升开发效率。其次,安全可靠是仓颉语言的核心目标之一。通过静态类型系统、自动内存管理以及运行时检查(如数组越界、数值溢出等),仓颉确保了程序的稳定性和安全性。此外,代码扫描工具和混淆技术的引入,进一步增强了跨语言互操作的安全性和代码保护能力。在并发编程方面,仓颉语言采用了轻量级用户态线程模型,使得并发任务的开发变得简单高效。开发者无需深入理解底层线程管理,即可编写出高性能的并发程序。同时,仓颉提供的并发对象库和无锁算法优化,进一步减少了线程阻塞,提升了程序的并发性能。最后,仓颉语言在性能优化和工具链支持上也下足了功夫。从编译器前端到后端,再到运行时,全栈优化技术确保了程序的高效执行。而丰富的工具链,包括调试、静态检查、性能分析等工具,则为开发者提供了全方位的支持,让开发过程更加顺畅。总的来说,仓颉语言通过现代语言设计、安全机制、并发模型和性能优化,为开发者提供了一种更高效、更可靠的编程选择。它的出现,不仅回应了现代软件开发的挑战,也为未来编程语言的发展提供了新的思路。2. 仓颉编程语言开发环境搭建在开始使用仓颉编程语言进行开发时,环境的搭建是首要步骤。传统方式需要开发者自行前往官网下载对应平台的版本,并完成安装和配置工作。这一过程往往涉及复杂的依赖管理和环境变量设置,对新手开发者存在一定门槛。图-官网下载一图-官网下载二为此,华为开发者空间提供了更为便捷的解决方案。该平台为每位开发者免费提供云主机资源,每年可享有数百小时的使用时长。云主机已预先集成了CodeArts IDE、代码仓库以及JDK、Python、仓颉等常用运行时环境,有效解决了本地开发环境中常见的配置复杂、稳定性不足等问题,为开发者打造了高效可靠的云端开发环境。华为开发者空间云主机主要面向三类用户群体:个人开发者:提供完整的工具链支持,满足日常开发需求高校师生:支持教学实验和课程实践开源贡献者:提供完整的开源开发环境,支持项目发布平台具备以下核心功能:即时访问:通过Web即可随时随地连接云主机开箱即用:预装CodeArts IDE及其配套插件云端存储:提供专属存储空间管理开发资产快速部署:内置华为云、鲲鹏等场景化沙箱环境申请流程极为简便,只需按指引操作即可免费获取。云主机采用Ubuntu 24.04.1 LTS系统,搭载Kunpeng-920 4C8G配置,并已预装CodeArts IDE for Cangjie,真正做到即开即用,省去了繁琐的安装配置环节。图-开发者空间工作台图-云主机桌面3.仓颉编程语言的学习路径对于想要掌握仓颉编程语言的开发者而言,系统的学习资源至关重要。目前,仓颉语言官网提供了基础文档、视频教程、示例代码等技术资料。然而作为一门新兴语言,其学习资源的丰富程度仍有较大提升空间。基于这一现状,我们推荐以清华大学出版社的《仓颉语言程序设计》(https://gitcode.com/Cangjie-SIG/cangjieyuyanchengxusheji-DY/blob/main/README.md)(董昱 著)作为入门学习教材。在有限的学习时间内,我们研读了该教材的前四章内容,这些章节主要涉及仓颉语言的基础知识体系:第一章:语言基础认知系统介绍了仓颉语言的诞生背景与发展历程,阐述了其作为现代编程语言的特性优势。同时详细说明了开发环境的搭建方法,涵盖编译器配置、编辑器选择以及调试工具的使用,为后续学习奠定实践基础。第二章:语法入门实践通过经典的"Hello World"示例,引导开发者快速上手仓颉语言的开发流程。重点讲解了变量声明、数据类型、运算符等基础语法元素,并结合具体案例演示了数值运算的实现方式。此外,还介绍了在VSCode中开发仓颉程序的配置方法。第三章:程序控制结构深入解析了仓颉语言的条件判断与循环控制机制。从布尔运算入手,逐步展开if表达式、match表达式的使用方法,并通过枚举类型展示了模式匹配的实际应用。循环结构部分则系统介绍了for、while等循环语句及其控制技巧。第四章:代码组织优化着重探讨了函数定义与模块化编程。详细讲解了函数参数传递、返回值处理等核心概念,并引入递归和重载等进阶特性。在代码组织方面,阐述了多文件编译、包模块管理等工程化实践,最后介绍了标准数学库的使用方法。图-《仓颉语言程序设计》代码仓4. 开发一个小应用:健康指数计算器基于前四章所学的仓颉语言核心知识(包括基础语法、结构化编程和函数模块化),我们设计实现了一个兼具实用性和趣味性的健康指数计算器。这个小应用运用了变量声明、条件分支、函数封装等编程要素,同时加入了必要的异常处理机制。在华为开发者空间的云主机环境中,我们使用预装的CodeArts IDE for Cangjie进行开发。图-CodeArts IDE for Cangjie启动后界面具体步骤如下:新建名为"health"的工程编写main.cj源代码文件实现功能:用户信息采集体脂率计算算法健康评估与建议生成图-IDE新建工程图-编写功能代码通过集成终端执行cjpm run命令后,程序交互过程如下:cjpm run ==== 健康指数计算器 ==== 请输入性别(男/女): 男 请输入体重(kg): 70 请输入年龄: 45 请输入身高(m): 1.72 === 计算结果 === BMI指数: 23.661439 体重状态: 正常 体脂率: 23.223726% 建议: 体脂率在正常范围,保持良好习惯 感谢使用! cjpm run finished图-程序编译运行main.cj完整源码如下:package health import std.math.* import std.io.* import std.console.* import std.convert.* // 计算BMI指数 func calculateBMI(weight: Float64, height: Float64) : Option<Float64> { if (height <= 0.0 || weight <= 0.0) { return None } return Some(weight / (height * height)) } // 计算体脂率(使用第三章的条件判断) func calculateBodyFat(gender: String, age: Float64, height: Float64, weight: Float64) : Option<Float64> { if (age <= 0.0 || weight <= 0.0) { return None } let coefficient = match (gender) { case "男" => 1.0 case "女" => 0.0 case _ => return None } Some((1.2 * weight / (height * height)) + (0.23 * coefficient) - 5.4) } // 主交互函数(整合第四章函数模块化) func healthReport() { println("==== 健康指数计算器 ====") try { print("请输入性别(男/女): ") let gender = Console.stdIn.readln().getOrThrow() print("请输入体重(kg): ") let weight = Float64.tryParse(Console.stdIn.readln().getOrThrow())??0.0 print("请输入年龄: ") let age = Float64.tryParse(Console.stdIn.readln().getOrThrow())??0.0 print("请输入身高(m): ") let height = Float64.tryParse(Console.stdIn.readln().getOrThrow())??0.0 // 计算BMI match (calculateBMI(weight, height)) { case Some(bmi) => println("\n=== 计算结果 ===") println("BMI指数: ${bmi}") // BMI评级(第三章条件分支) let bmiStatus = if (bmi < 18.5) { "偏瘦" } else if (bmi < 24.0) { "正常" } else if (bmi < 28.0) { "超重" } else { "肥胖" } println("体重状态: ${bmiStatus}") case None => println("! 输入数据不合法") } // 计算体脂率 match (calculateBodyFat(gender, age, height, weight)) { case Some(fatRate) => println("体脂率: ${fatRate}%") // 体脂率建议(第二章运算符应用) let (lower, upper) = match (gender) { case "男" => (18.0, 24.0) case "女" => (25.0, 31.0) case _ => (0.0, 0.0) } if (fatRate < lower) { println("建议: 体脂率偏低,注意营养摄入") } else if (fatRate > upper) { println("建议: 体脂率偏高,建议增加运动量") } else { println("建议: 体脂率在正常范围,保持良好习惯") } case None => println("! 体脂率计算失败") } } catch(e: Exception) { println("\n错误: 输入格式不正确") } } // 程序入口 main() : Int64 { healthReport() println("\n感谢使用!") return 0 } 技术要点采用函数式编程思想,将计算逻辑封装为独立函数使用模式匹配处理不同性别的体脂率计算公式通过条件表达式实现健康状态分级评估加入输入验证确保数据的合法性通过这个小应用的开发,我们巩固了基础知识,也体会到了仓颉语言在开发实用工具时的简洁性和高效性。5. 后续学习计划基于当前的学习进度,后续将采取理论与实践相结合的方式,按章节顺序完成《仓颉语言程序设计》剩余内容的学习,系统性地深入掌握仓颉编程语言。积极参与开源社区(https://gitcode.com/Cangjie)讨论,解决实际问题,希望采用这种循序渐进的学习方式,既能保证理论知识的系统性掌握,又能通过实际项目开发培养工程实践能力,最终实现对仓颉编程语言的熟练运用。我正在参加【案例共创】第4期 基于华为开发者空间+仓颉/DeepSeek/MCP完成应用构建开发实践