17. 一个I/O项目:构建命令行程序(下)

目录

  • 五、采用测试驱动开发完善库的功能
    • 5.1 编写失败测试用例
    • 5.2 编写成功测试用例
    • 5.3 在run函数中打印搜索到的行
  • 六、添加大小写不敏感功能
  • 七、将错误信息输出到标准错误
  • 八、附录完整代码

五、采用测试驱动开发完善库的功能

5.1 编写失败测试用例

  1. 在lib.rs中写一个简单的search函数
pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str>{vec![]
}
  • 目前该函数是一个总是返回空的vector函数;
  • 函数的参数是&str型,因此需要显式地定义生命周期;
  • 生命周期指定contents的生命周期与返回值的相关连;
  1. 在lib.rs中编写测试代码
#[cfg(test)]
mod tests{use super::*;#[test]fn one_result(){let query = "duct";let contents = "\
Rust:
safe, fast, productive.
Pick there.";assert_eq!(vec!["safe, fast, productive."],search(query, contents))}
}
  1. 运行测试会如预期的失败了;

5.2 编写成功测试用例

失败的原因在于search返回空,因此完善它就行

pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str>{let mut results = Vec::new();for line in contents.lines(){if line.contains(query){results.push(line);}}results
}
  • 创建一个可变的Vector;
  • 使用字符串类的迭代方法一次读取一行;
  • 在此行中查找,找到后 push进入Vector即可;

编译测试用例
在这里插入图片描述

5.3 在run函数中打印搜索到的行

  • 修改run函数,将搜索到的行内容打印出来
pub fn run(config: Config) -> Result<(), Box<dyn Error>> {let contents = fs::read_to_string(config.filename)?;for line in search(&config.query, &contents) {println!("{}", line);}Ok(())
}

运行命令cargo run body poem.txt,旨在poem.txt文件内查找body字符串
在这里插入图片描述

六、添加大小写不敏感功能

  • 编写大小写不敏感的测试函数search_case_insensitive
  • 将旧的one_result改名为大小写敏感函数case_sensitive

大小写不敏感的search函数

pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {let query = query.to_lowercase();let mut results = Vec::new();for line in contents.lines() {if line.to_lowercase().contains(&query) {results.push(line);}}results
}
  • 大小写不敏感的做法就是将读取到的字母以及目标子串全部改为大写或小写;

编写测试函数

#[cfg(test)]
mod tests {use super::*;#[test]fn case_sensitive() {let query = "duct";let contents = "\
Rust:
safe, fast, productive.
Pick three.
Duct tape.";assert_eq!(vec!["safe, fast, productive."],search(query, contents));}#[test]fn case_insensitive() {let query = "rUsT";let contents = "\
Rust:
safe, fast, productive.
Pick three.
Trust me.";assert_eq!(vec!["Rust:", "Trust me."],search_case_insensitive(query, contents));}
}

在Config中增加case_sensitive并修改构造函数

use std::env;pub struct Config{query: String,filename: String,case_sensitive: bool, 
}impl Config{pub fn new(args: &[String]) -> Result<Config, &'static str>{if args.len() < 3{return Err("Not enough arguments!");}let query = args[1].clone();let filename = args[2].clone();let case_sensitive = env::var("CASE_INSENSITIVE").is_err();Ok(Config {query, filename, case_sensitive})}
}
  • 在Config中添加了case_sensitive的布尔值,用来说明是否大小写敏感;
  • 在Config的new函数中使用env::var读取CASE_INSENSITIVE的环境变量设置情况;
  • 如果设置了CASE_INSENSITIVE的值is_err返回True就是大小写不敏感的,否则是敏感的;
  • 注意:不论CASE_INSENSITIVE设置为多少,都是大小写不敏感的

修改run函数,以判断是否起用大小写敏感

pub fn run(config: Config) -> Result<(), Box<dyn Error>> {let contents = fs::read_to_string(config.filename)?;let results = if config.case_sensitive {search(&config.query, &contents)}else{search_case_insensitive(&config.query, &contents)};for line in results{println!("{}", line);}Ok(())
}

测试,先不加环境变量测试大小写敏感的,再测试不敏感的。
在这里插入图片描述

七、将错误信息输出到标准错误

  • 通过println!打印的信息都输出到了终端;
  • 大部分终端都提供了两种输出:标准输出(standard output,stdout)和标准错误(standard error,stderr);
  • 标准输出对应一般信息,标准错误用于错误信息;
  • Rust提供eprintln!宏输出标准错误信息;

修改main的标准错误输出

fn main() {let args: Vec<String> = env::args().collect();let config = Config::new(&args).unwrap_or_else(|err| {eprintln!("Problem parsing arguments: {}", err);process::exit(1);});if let Err(e) = minigrep::run(config) {eprintln!("Application error: {}", e);process::exit(1);}
}

八、附录完整代码

main.rs

use std::env;
use std::process;
use minigrep::Config;fn main() {let args: Vec<String> = env::args().collect();let config = Config::new(&args).unwrap_or_else(|err| {eprintln!("Problem parsing arguments: {}", err);process::exit(1);});if let Err(e) = minigrep::run(config) {eprintln!("Application error: {}", e);process::exit(1);}
}

lib.rs

use std::fs;
use std::env;
use std::error::Error;pub struct Config{query: String,filename: String,case_sensitive: bool, 
}impl Config{pub fn new(args: &[String]) -> Result<Config, &'static str>{if args.len() < 3{return Err("Not enough arguments!");}let query = args[1].clone();let filename = args[2].clone();let case_sensitive = env::var("CASE_INSENSITIVE").is_err();Ok(Config {query, filename, case_sensitive})}
}pub fn run(config: Config) -> Result<(), Box<dyn Error>> {let contents = fs::read_to_string(config.filename)?;let results = if config.case_sensitive {search(&config.query, &contents)}else{search_case_insensitive(&config.query, &contents)};for line in results{println!("{}", line);}Ok(())
}pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str>{let mut results = Vec::new();for line in contents.lines(){if line.contains(query){results.push(line);}}results
}pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {let query = query.to_lowercase();let mut results = Vec::new();for line in contents.lines() {if line.to_lowercase().contains(&query) {results.push(line);}}results
}#[cfg(test)]
mod tests {use super::*;#[test]fn case_sensitive() {let query = "duct";let contents = "\
Rust:
safe, fast, productive.
Pick three.
Duct tape.";assert_eq!(vec!["safe, fast, productive."],search(query, contents));}#[test]fn case_insensitive() {let query = "rUsT";let contents = "\
Rust:
safe, fast, productive.
Pick three.
Trust me.";assert_eq!(vec!["Rust:", "Trust me."],search_case_insensitive(query, contents));}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/29824.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

42.商城系统(二十三):sleuth+zipkin服务链路追踪

目录 一、什么是sleuth 1.为什么要用 2.基本概念 (1)span(跨度)、trace(跟踪) (2)Annotation(标注) 二、整合sleuth + zipkin 1.引入slenth依赖 2.开启日志 3.在docker中安装zipkin服务器 4.引入zipkin依赖 5.设置zipkin依赖 6.查看zipkin页面 7.zipkin…

【算法训练记录——Day31】

Day31——贪心算法Ⅰ 1. 理论1.1 什么是贪心1.2 什么时候用贪心1.3 贪心算法一般步骤 2.leetcode455——分发饼干3.leetcode376——摆动序列 目标&#xff1a; 理论leetcode455——分发饼干leetcode376——摆动序列leetcode53 —— 最大字序和 1. 理论 算法随想录——贪心 1…

持续总结中!2024年面试必问 20 道设计模式面试题(三)

上一篇地址&#xff1a;持续总结中&#xff01;2024年面试必问 20 道设计模式面试题&#xff08;二&#xff09;-CSDN博客 五、什么是建造者模式&#xff08;Builder Pattern&#xff09;&#xff1f;它解决了什么问题&#xff1f; 建造者模式&#xff08;Builder Pattern&am…

c语言---循环 、判断基础知识详解

if语句 else离最近的if语句结合。 if语句题目 //1. 判断一个数是否为奇数 //2. 输出1 - 100之间的奇数 #include <stdio.h> int main() {int n 0;scanf("%d", &n);if (n % 2){printf("奇数\n");}else{printf("不是奇数\n"…

[C#]使用深度学习算法opencvsharp部署RecRecNet广角图像畸变矫正校正摄像广角镜头畸变图像

【论文地址】 https://arxiv.org/abs/2301.01661 【训练源码】 https://github.com/KangLiao929/RecRecNet 【参考源码】 https://github.com/hpc203/recrecnet-opencv-dnn 【算法介绍】 广角镜头在VR技术中显示出诱人的应用&#xff0c;但它会在捕获的图像中引入严重的径…

镜头跟踪的两种方法

方法一 (1) 原理&#xff1a;使球与摄像机保持固定的角度和距离 (2) 给Main Camera添加CamraCtrller.cs组件 public Transform Player;//小球的Transformprivate Vector3 offset;//小球与摄像机位置的偏移&#xff08;在三轴上的距离&#xff09;void Start(){offset Playe…

深度神经网络——什么是降维?

引言 什么是降维&#xff1f; 降维是用于降低数据集维度的过程&#xff0c;采用许多特征并将它们表示为更少的特征。 例如&#xff0c;降维可用于将二十个特征的数据集减少到仅有几个特征。 降维通常用于无监督学习任务 降维是一个用于降低数据集维度的过程&#xff0c;采用许…

【中文】PDF文档切分\切片\拆分最优方案-数据预处理阶段,为后续导入RAG向量数据库和ES数据库实现双路召回

目的 将PDF文档拆开&#xff0c;拆开后每个数据是文档中的某一段&#xff0c;目的是保证每条数据都有较完整的语义&#xff0c;并且长度不会太长 项目自述 看了很多切分项目&#xff0c;包括langchain、Langchain-Chatchat、、Chinese-LangChain、LangChain-ChatGLM-Webui、…

c语言指针经典笔试题

指针的笔试题目 //深度讨论数组名 int main1() {int a[] { 1,2,3,4 };printf("%d\n", sizeof(a)); //sizeof内部出现数组名代表是整个数组的大小 //16printf("%d\n", sizeof(a 0)); //首元素地址0还是首元素地址 4/8printf("%d\n", sizeof(*…

TestProject Python SDK入门

2024软件测试面试刷题&#xff0c;这个小程序&#xff08;永久刷题&#xff09;&#xff0c;靠它快速找到工作了&#xff01;&#xff08;刷题APP的天花板&#xff09;-CSDN博客跳槽涨薪的朋友们有福了&#xff0c;今天给大家推荐一个软件测试面试的刷题小程序。​编辑https://…

阻力支撑相对强度(RSRS)选股系列报告之三

https://download.csdn.net/download/SuiZuoZhuLiu/89447699?spm1001.2014.3001.5503https://download.csdn.net/download/SuiZuoZhuLiu/89447699?spm1001.2014.3001.5503

《维汉翻译通》App一款免费的维吾尔语翻译工具,也是新疆人学习中文的利器!维吾尔文OCR识别提取文字神器,功能丰富、界面简洁无广告、操作简单!

免费翻译&#xff0c;无界限沟通 《维汉翻译通》App提供免费的短文本翻译服务&#xff0c;无论是日常对话还是专业术语&#xff0c;都能迅速给出准确的翻译结果。维吾尔语免费翻译工具的加入&#xff0c;更是让这款App成为学习维吾尔语的必备应用。 智能OCR&#xff0c;文字识…

#QT(QCharts绘制曲线)

1.IDE&#xff1a;QTCreator 2.实验&#xff1a;绘制曲线图表 3.记录&#xff1a; 4.代码 pro QT core gui #加入以下代码引入charts QT charts greaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c17# You can make your code fail to compile if it uses depre…

关于数据库导入导出excel后出现前面的0消失或者有-的变成了日期

1、数据导出0消失 在数据库导出excel后&#xff0c;发现前面的数字0都消失了&#xff0c;怎么办呢&#xff0c;将需要转换的列转成字符串在导出 2、数据导入时&#xff0c;excel的0消失 载excel中输入’00001’&#xff0c;发现变成了‘1’&#xff0c;选中列点击右键–>设置…

python写一个ai agent对接仓库管理系统的业务流程

要实现一个AI agent对接仓库管理系统的业务流程&#xff0c;首先需要了解仓库管理系统的具体业务流程和需求。以下是一个简单的示例&#xff0c;用Python编写一个AI agent&#xff0c;用于对接仓库管理系统的业务流程。 1. 首先&#xff0c;定义一个类WarehouseManager&#xf…

场景设计题

为什么要这样分表&#xff1f;跨库join如何解决&#xff1f;数据量突增怎么解决&#xff1f; 如何解决线上问题&#xff1f;cpu狂飙怎么办&#xff1f;频繁minor gc怎么办&#xff1f;可能造成的原因是什么&#xff1f;如何避免&#xff1f; 数据库 隔离级别&#xff0c;怎么实…

npm发布自己的插件包:新手教程

npm&#xff08;Node Package Manager&#xff09;是Node.js的包管理工具&#xff0c;广泛用于JavaScript项目中。本文将为你介绍如何从零开始发布一个npm插件包。 前提条件 在开始之前&#xff0c;你需要确保以下几点&#xff1a; 安装Node.js和npm&#xff1a;你可以在No…

C++ 二叉搜索树【面试】

以下是一个简单的二叉搜索树实现&#xff0c;包括插入和查找操作的示例代码&#xff1a; #include <iostream>// 定义二叉搜索树的节点结构 struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} };//…

Spring Boot定时任务编程指南:如何创建和配置周期性任务

&#x1f341; 作者&#xff1a;知识浅谈&#xff0c;CSDN签约讲师&#xff0c;CSDN博客专家&#xff0c;华为云云享专家&#xff0c;阿里云专家博主 &#x1f4cc; 擅长领域&#xff1a;全栈工程师、爬虫、ACM算法 &#x1f525; 微信&#xff1a;zsqtcyw 联系我领取学习资料 …

基于Langchain构建本地大型语言模型(LLM)问答系统的经验分享

基于Langchain构建本地大型语言模型&#xff08;LLM&#xff09;问答系统的经验分享 https://download.csdn.net/download/xziyuan/89334371?spm1001.2101.3001.9500 最近&#xff0c;我一直在探索如何利用Langchain来构建一个本地的大型语言模型问答系统。在这个过程中&…