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.mfbz.cn/a/721799.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JAVAEE之网络原理(2)_传输控制协议(TCP)、概念、格式、确认应答及超时重传机制

前言 在上一节中&#xff0c;我们介绍了 UDP (用户数据报) 的相关知识&#xff0c;在这一节中我们将继续介绍传输层中另一种更为重要的协议。 一、什么是TCP协议&#xff1f; 1.1 TCP 基本概念 TCP协议全称&#xff1a;传输控制协议&#xff08;TCP&#xff0c;Transmission C…

Vatee万腾平台:创新科技,助力企业腾飞

在全球化竞争日益激烈的今天&#xff0c;企业如何借助科技力量实现转型升级&#xff0c;已成为摆在众多企业家面前的重大课题。Vatee万腾平台凭借其卓越的创新科技和专业的服务能力&#xff0c;成为众多企业实现腾飞的得力助手。 一、创新科技&#xff0c;引领企业前行 Vatee万…

计算机网络实验(9):路由器的基本配置和单臂路由配置

一、 实验名称 路由器的基本配置和单臂路由配置 二、实验目的&#xff1a; &#xff08;1&#xff09;路由器的基本配置&#xff1a; 掌握路由器几种常用配置方法&#xff1b; 掌握采用Console线缆配置路由器的方法&#xff1b; 掌握采用Telnet方式配置路由器的方法&#…

Spring事务 和 事务传播机制

这里的 事务 和之前 MySQL的事务 一样&#xff0c;都是表示将⼀组操作封装成⼀个执⾏单元&#xff08;封装到⼀起&#xff09;&#xff0c;要么全部成功&#xff0c;要么全部失败。 Spring 中事务的实现 1. 编程式事务&#xff08;手动档&#xff09;。 package com.example.…

Java线程池基本概念

全局和局部线程池 全局线程池 在Spring框架中&#xff0c;全局线程池如ThreadPoolTaskExecutor通常是作为Spring Bean存在的&#xff0c;它们的生命周期由Spring容器管理。当Spring容器关闭时&#xff0c;这些线程池也会被适当地清理和关闭。因此&#xff0c;开发者通常不需要手…

MCK主机加固在防漏扫中的关键作用

在当今这个信息化飞速发展的时代&#xff0c;网络安全成为了企业不可忽视的重要议题。漏洞扫描&#xff0c;简称漏扫&#xff0c;是一种旨在发现计算机系统、网络或应用程序中潜在安全漏洞的技术手段。通过自动化工具&#xff0c;漏扫能够识别出系统中存在的已知漏洞&#xff0…

调度算法-进程调度算法

发⽣ CPU 调度通常有以下情况&#xff1a; 1. 当进程从运⾏状态转到等待状态&#xff1b;2. 当进程从运⾏状态转到就绪状态&#xff1b;3. 当进程从等待状态转到就绪状态&#xff1b;4. 当进程从运⾏状态转到终⽌状态 常⻅的调度算法&#xff1a; 先来先服务调度算法最短作业…

Airtest初使用

https://airtest.doc.io.netease.com/tutorial/2_Airtest_introduction/ 什么是Airtest Airtest是一款基于Python语言、跨平台的UI自动化测试框架&#xff0c;基于图像识别原理&#xff0c;比较适用于游戏和App。 它的主要特点包括&#xff1a; 跨平台支持&#xff1a;支持A…

打造精致UI界面:字体设计的妙招

字体设计是UI设计的关键模块之一。字体设计是否有效可能直接实现或破坏整个UI界面。那么&#xff0c;界面设计的字体设计有哪些规范呢&#xff1f;如何设计细节字体&#xff1f;本文将解释字体设计规范的可读性、可读性和可用性&#xff0c;并介绍UI界面中的字体设计技巧。 如…

团队管理的三个要点,打造高执行力团队

一、明确目标与责任 明确的目标与责任是团队高效运作的基石。只有当团队成员对目标有清晰的认识&#xff0c;并明确自己的责任时&#xff0c;才能形成强大的合力&#xff0c;推动团队不断前进。 1、目标设定 目标应该具体、可衡量、有挑战性但可实现。项目经理可以与团队成员…

Nginx Proxy 代理测试

目录 https://blog.csdn.net/Lzcsfg/article/details/139781909 一. 实验准备 二. 配置反向代理 三. 配置二层代理 解释流程 一. 实验准备 关闭防火墙和selinux&#xff0c;准备三台同一网段的虚拟机 localhostRoucky_linux9.4192.168.226.20localhostRoucky_linux9.419…

【2024泰迪杯】C 题:竞赛论文的辅助自动评阅 26页及31页2篇完整论文及Python 代码实现

【2024泰迪杯】C 题&#xff1a;竞赛论文的辅助自动评阅 26页及31页完整论文及Python 代码实现 相关链接 【2024泰迪杯】A 题&#xff1a;生产线的故障自动识别与人员配置 Python代码实现 【2024泰迪杯】B 题&#xff1a;基于多模态特征融合的图像文本检索Python代码实现 【2…

基于PHP的草莓种植信息管理系统

有需要请加文章底部Q哦 可远程调试 基于PHP的草莓种植管理系统 一 介绍 此草莓种植管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端采用jquery.js和kindeditor在线HTML编辑器。系统角色分为用户和管理员。 技术栈&#xff1a;phpmysqljquery.jsphpstudyvsco…

云计算【第一阶段(16)】安装及管理程序

一、linux 应用程序基础 当我们主机安装linux操作系统 时候&#xff0c;也会同时安装一些软件或网络服务等等&#xff0c;但是随着系统一起安装的软件包毕竟他是少数的&#xff0c; 能够实现的功能也是有限的&#xff0c;那么我们相拥为主机提供更多更丰富的功能的时候&#x…

注意力机制和Transformer模型各部分功能解释

文章目录 Transformer1、各部分功能解释2、通过例子解释a.输入预处理位置编码b.Encoder 的处理c.Decoder的输入Decoder的工作流程d.输出预测总结 Attention代码和原理理解 Transformer 运行机理&#xff1a; &#xff08;1&#xff09;假设我们需要进行文本生成任务。我们将已…

Java17 --- redis7缓存双写一致性

一、缓存双写一致性 如果redis中有数据&#xff1a;需要和数据库中的值相同。如果redis中没有数据&#xff1a;数据库中的值要是最新值&#xff0c;且准备回写redis。只读缓存。读写缓存&#xff1a;①、同步直写策略&#xff1a;写数据库后也同步写redis缓存&#xff0c;缓存…

计算机网络(谢希仁第六版)| 课后习题与答案 | 物理层 | 题目知识点详细分析

计算机网络&#xff08;谢希仁第六版&#xff09;课后习题与答案 物理层 博客只对老师给的重点进行整理&#xff0c;完整的课后习题答案见Gitee下载&#xff1a;《计算机网络教程&#xff08;第6版&#xff09;&#xff08;微课版&#xff09;》习题答案 2-5 请画出数据流1 0 1…

Java基础学习-流程控制语句-顺序结构-分支结构-循环结构

目录 顺序结构&#xff1a; 分支结构&#xff1a; if语句&#xff1a; 第一种格式&#xff1a; if第二种格式&#xff1a; 案例练习 if第三种格式&#xff1a; switch语句&#xff1a; 格式&#xff1a; switch其他知识点&#xff1a; 循环结构&#xff1a; for循环…

软件测试面试题:性能测试关注哪些指标?

问题 在工作中&#xff0c;使用JMeter做压力测试时&#xff0c;需要关注其中的哪些指标&#xff1f; 性能测试关注哪些指标&#xff1f; 考察点 面试官想了解&#xff1a; 是否用过 JMeter 指标进行分析 技术点 涉及的技术点&#xff1a; JMeter 结果分析 回答 性能指…

基于 Vitis HLS 的单个乘法 DSP 映射研究

文章目录 1 自媒体账号2 引言3 整数乘法4 定点乘法5 浮点乘法6 总结 1 自媒体账号 目前运营的自媒体账号如下&#xff1a; 哔哩哔哩 【雪天鱼】: 雪天鱼个人主页-bilibili.com 如果觉得有所收获的话&#xff0c;可以点击我的主页 -> 充电 -> 自定义充电 支持一下&#…