学习Rust的第29天: cat in Rust

今天即将是这个系列的最后一次内容,我们正在catRust 中从 GNU 核心实用程序进行重建。cat用于将文件内容打印到STDOUT.听起来很容易构建,所以让我们开始吧。

GitHub 存储库:GitHub - shafinmurani/gnu-core-utils-rust

伪代码

function read(path)->result{
  read contents of path
  propogate any errors to the caller
}

args = command_line_arguments
remove the first element of the args vector

if args.length == 0 {
  print error_message
}
else if args.contains("--help") {
  print help_message
} else {
  for path in args {
    result = remove(path);
    error handling
  }
}

设置任务

正如我们往常所做的那样,让我们impl​​在库箱中创建一个结构体和一个块。

pub struct Config<'a> {
  file_names: &'a Vec<String>,
}

impl Config<'_> {
  pub fn new(args: &Vec<String>){
    Config{ file_names: args }
  }

  fn not_enough_arguments(){
    eprintln!("cat: missing operand");
    eprintln!("for help: cat --help");
  }

  fn help(){
    eprintln!("Welcome to cat in Rust, This is a a little copy of the cat utility present in the GNU core utilities. I made this to practice my rust skills. Check out my articles at https://shafinmurani.medium.com");
    eprintln!("To use: cat file_name1 file_name2 file_name3");
  }

  fn read_documents(){}

  pub fn run(&self){
    if self.file_names.len() == 0 {
      Self::not_enough_arguments();
    } else if self.file_names.contain(&String::from("--help")){
      Self::help();
    } else {
      //We call the read_documents function here
    }
  }
}
  • 该代码定义了一个Config带有生命周期参数的结构体'a,其中包含一个file_names对字符串向量的引用的字段。
  • Config结构有一个关联的实现块 ( impl),用于与 相关的方法Config
  • new方法是 的构造函数Config,将对字符串向量的引用args作为输入,并返回一个设置为 的Config实例。file_namesargs
  • not_enough_arguments方法向 stderr 打印一条错误消息,指示该cat命令缺少操作数,建议使用cat --help.
  • help方法打印欢迎消息和cat命令的使用说明。
  • read_documents方法当前留空,可能会被实现来读取和打印指定文件的内容。
  • run方法是执行命令的主要函数cat
  • 它首先检查是否没有提供文件名,在这种情况下它调用not_enough_arguments.
  • 然后它检查--help文件名中是否存在该标志,如果存在,则调用该help方法。
  • 否则,假设提供了文件名,并且它将继续读取和打印这些文件的内容,当前将其作为注释保留。

read_documents() 方法

我们将向此函数传递一个文件路径,它将输出文件的内容,为此,我们使用以下内容:

  1. std::fs::File: 打开文件
  2. std::io::Read:将内容读取到字符串变量

让我们导入这些东西并编写read_document()函数并使用它

use std::fs::File;
use std::io::Read;

pub struct Config<'a> {
  file_names: &'a Vec<String>,
}

impl Config<'_> {
  pub fn new(args: &Vec<String>){
    Config{ file_names: args }
  }

  fn not_enough_arguments(){
    eprintln!("cat: missing operand");
    eprintln!("for help: cat --help");
  }

  fn help(){
    eprintln!("Welcome to cat in Rust, This is a a little copy of the cat utility present in the GNU core utilities. I made this to practice my rust skills. Check out my articles at https://shafinmurani.medium.com");
    eprintln!("To use: cat file_name1 file_name2 file_name3");
  }

  fn read_documents(file: String) -> std::io::Result<String>{
    let mut file_buffer = File::open(file)?;
    let mut file_content = String::new();

    file_buffer.read_to_string(&mut file_content)?;
    Ok(file_content)
  }

  pub fn run(&self){
    if self.file_names.len() == 0 {
      Self::not_enough_arguments();
    } else if self.file_names.contain(&String::from("--help")){
      Self::help();
    } else {
      for file in self.file_names {
        let result = Self::read_document(file.to_string());
        match result {
          Ok(data) => println!("{}",data),
          Err(e) => eprintln!("Application Error: `{}` {}", file, e),
        };
      }
    }
  }
}

现在这一切都完成了,我们可以处理我们的二进制箱并专注于运行它......

二进制箱

这里的逻辑很简单

  1. 导入Config结构体
  2. 获取命令行参数
  3. 删除第一个参数
  4. 实例化配置
  5. 配置.run()

让我们实践并运行它。

use cat::Config;
use std::env;

fn main(){
  let mut args: Vec<String> = env::args().collect();
  args.remove(0);
  
  let config = Config::new(args);
  config.run();
}

运行它

cat我们将使用该工具来阅读我们工具的源代码cat。谈论 Catception 💀

# ./cat lib.rs

use std::fs::File;
use std::io::Read;

pub struct Config<'a>{
    file_names: &'a Vec<String>,
}

impl Config<'_>{
    pub fn new(args: &Vec<String>) -> Config{
        Config{ file_names: args }
    }

    fn help(){
        eprintln!("Welcome to cat in Rust, This is a little copy of the cat utility present in the GNU core utilities. I made this to practice my rust skills. Check out my articles at https://shafinmurani.medium.com");
        eprintln!("To use: cat file_name1 file_name2 ... file_nameN");
    }

    fn not_enough_arguments(){
        eprintln!("cat: missing operand");
        eprintln!("for help: cat --help");
    }

    fn read_document(file: String) -> std::io::Result<String>{
        let mut file_buffer = File::open(file)?;
        let mut file_content = String::new();

        file_buffer.read_to_string(&mut file_content)?;
        Ok(file_content)
    }

    pub fn run(&self){
        if self.file_names.len() == 0 {
            Self::not_enough_arguments();
        } else if self.file_names.contains(&String::from("--help")) {
            Self::help();
        } else {
            for file in self.file_names {
               let result = Self::read_document(file.to_string());
                match result {
                    Ok(r) => println!("{}",r),
                    Err(e) => eprintln!("Application Error: `{}` {}",file,e)
                };
            }
        }
    }
}

结论

库文件

  • lib.rs文件定义了 crate 的主要功能cat
  • 它从标准库(std::fs::Filestd::io::Read)导入必要的模块以进行文件处理。
  • 它声明了一个Config带有生命周期参数的结构体'a,其中包含一个file_names对字符串向量的引用的字段。
  • impl与 相关的方法有一个实现块 ( ) Config
  • new方法是 的构造函数Config,将对字符串向量的引用args作为输入,并返回一个设置为 的Config实例。file_namesargs
  • help方法打印欢迎消息和cat命令的使用说明。
  • not_enough_arguments方法向 stderr 打印一条错误消息,指示该cat命令缺少操作数,建议使用cat --help.
  • read_document方法读取由名称指定的文件的内容并将其作为 a 返回String,处理潜在的 IO 错误。
  • run方法是执行命令的主要函数cat
  • 它检查是否没有提供文件名,在这种情况下它调用not_enough_arguments.
  • 然后它检查--help文件名中是否存在该标志,如果存在,则调用该help方法。
  • 否则,它会迭代每个文件名,使用 读取其内容read_document,并将其打印到标准输出。

主程序.rs

  • main.rs文件充当可执行文件的入口点。
  • 它从板条箱Config中导入结构catenv从标准库中导入模块。
  • main函数将命令行参数收集到字符串向量中,删除第一个参数(程序名称本身),然后Config使用剩余参数创建一个实例Config::new
  • 最后,它调用实例run上的方法Config来执行cat命令。

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

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

相关文章

Transformer详解:从放弃到入门(一)

Transformer由论文《Attention is All You Need》提出&#xff0c;是一种用于自然语言处理&#xff08;NLP&#xff09;和其他序列到序列&#xff08;sequence-to-sequence&#xff09;任务的深度学习模型架构&#xff0c;在自然语言处理领域获得了巨大的成功&#xff0c;在这个…

免费开源线上线下交友社交圈子系统 小程序+APP+H5 可支持二开!

为什么要玩社交软件&#xff1a;互联网社交软件的独特优势 首先&#xff0c;社交软件为我们提供了一个便捷的沟通方式。在传统的交往方式中&#xff0c;人们需要面对面交流&#xff0c;这种方式在时间和空间上都受到限制。而社交软件打破了这些限制&#xff0c;无论我们身处何地…

如何复制本地docker镜像到其他主机

&#xff08;1&#xff09;打包镜像 比如我要复制的镜像是grafana的镜像 docker images 这里我把打包的镜像放在了根~目录下&#xff0c;如截图所示&#xff1a; docker save grafana/grafana:latest -o ~/grafana.jar &#xff08;2&#xff09;移动镜像 scp命令拷贝镜像到目标…

linux学习:线程池

目录 原理 初始线程池 运行中的线程池 相关结构体 api 线程池初始化 投送任务 增加活跃线程 删除活跃线程 销毁线程池 例子 thread_pool.h thread_pool.c test.c 测试程序 原理 一个进程中的线程就好比是一家公司里的员工&#xff0c;员工的数目应该根据公司的…

AI神助攻!小白也能制作自动重命名工具~

我们平时从网上下载一些文件&#xff0c;文件名很多都是一大串字母和数字&#xff0c;不打开看看&#xff0c;根本不知道里面是什么内容。 我想能不能做个工具&#xff0c;把我们一个文件夹下面的所有word、excel、ppt、pdf文件重命名为文件内容的第一行。 我们有些朋友可能不会…

刷代码随想录有感(57):二叉搜索树中的众数

题干&#xff1a; 代码&#xff1a; class Solution { public:unordered_map<int,int>map;void traversal(TreeNode* root){if(root NULL)return;traversal(root->left);map[root->val];traversal(root->right);}bool static cmp(const pair<int,int>&a…

[蓝桥杯2024]-PWN:ezheap解析(堆glibc2.31,glibc2.31下的double free)

查看保护 查看ida 大致就是只能创建0x60大小的堆块&#xff0c;并且uaf只能利用一次 完整exp&#xff1a; from pwn import* #context(log_leveldebug) pprocess(./ezheap2.31)def alloc(content):p.sendlineafter(b4.exit,b1)p.send(content) def free(index):p.sendlineaft…

C++:运算符重载(=/==)

赋值运算符&#xff08;&#xff09;重载 在C中&#xff0c;赋值运算符可以被重载&#xff0c;允许用户定义类对象的赋值行为。通过重载赋值运算符&#xff0c;可以自定义对象的赋值操作&#xff0c;以便适应特定的需求和语义。当我们定义一个自定义的类时&#xff0c;比如一个…

语音识别---节拍器

⚠申明&#xff1a; 未经许可&#xff0c;禁止以任何形式转载&#xff0c;若要引用&#xff0c;请标注链接地址。 全文共计3077字&#xff0c;阅读大概需要3分钟 &#x1f308;更多学习内容&#xff0c; 欢迎&#x1f44f;关注&#x1f440;【文末】我的个人微信公众号&#xf…

商城数据库88张表结构完整示意图41~50(十二)

四十一&#xff1a; 四十二&#xff1a; 四十三&#xff1a; 四十四&#xff1a; 四十五&#xff1a; 四十六&#xff1a; 四十七&#xff1a; 四十八&#xff1a; 四十九&#xff1a; 五十&#xff1a;

说说你对盒子模型的理解?

一、是什么 当对一个文档进行布局&#xff08;layout&#xff09;的时候&#xff0c;浏览器的渲染引擎会根据标准之一的 CSS 基础框盒模型&#xff08;CSS basic box model&#xff09;&#xff0c;将所有元素表示为一个个矩形的盒子&#xff08;box&#xff09; 一个盒子由四…

开源推荐榜【MalusAdmin基于 Vue3/TypeScript/NaiveUI 和 NET7 Sqlsugar 开发的后台管理框架】

简介 Malus是海棠的意思&#xff0c;顾名思义&#xff0c;海棠后台管理系统&#xff0c;读音与【马卢斯】相近&#xff0c;也可称作为马卢斯后台管理系统。 基于NET Core | NET7/8 & Sqlsugar | Vue3 | vite4 | TypeScript | NaiveUI 开发的前后端分离式权限管理系统,采用…

2024SCVN南方时尚之夜:童模冰雪之境惊艳亮相

在广州黄埔君澜酒店&#xff0c;璀璨的灯光下&#xff0c;一场主题为“雪山”、“童模”与“时尚”的盛宴于2024年5月1日至5月3日华丽上演。这场名为“2024SCVN南方时尚之夜&绽放冰雪之境”的活动&#xff0c;如同一颗璀璨的明珠&#xff0c;镶嵌在初夏的广州&#xff0c;熠…

IPD-开发流程

2024-5-6记录于PR办公室 在上一家公司做硬件产品经理的时候&#xff0c;Richard Li曾花费“巨资”请了华为前战略专家给我们培训&#xff0c;讲授IPD这门课的模式都很IPD&#xff0c;当时完全没重视&#xff0c;光想着不可能靠这个能把产品做好&#xff0c;这样做产品必定是一批…

【电影】【指环王】【中土世界】影碟播放记录

一、写在前面 笔者于5月5日&#xff08;昨天&#xff09;在新加坡淘到了一套《指环王 The Lord of the Rings》DVD光碟&#xff0c;今天却听闻噩耗&#xff0c;Rohan国王Theoden的扮演者&#xff0c;英国演员Bernard Hill去世&#xff08;享年79岁&#xff09;&#xff0c;发文…

接口自动化测试之-requests模块详解

一、requests背景 Requests 继承了urllib2的所有特性。Requests支持HTTP连接保持和连接池&#xff0c;支持使用cookie保持会话&#xff0c;支持文件上传&#xff0c;支持自动确定响应内容的编码&#xff0c;支持国际化的 URL 和 POST 数据自动编码。 二、requests安装 利用p…

Windows环境下VSCode C无法跳转自动补全

前言&#xff1a; 本文记录了自己在配置 Windows环境下 VSCode C开发环境的遇到的问题和解决方法。 参考: vscode c语言没有代码提示_clangd提示不生效-CSDN博客 VSCODE无法跳转_vscode 不能跳转-CSDN博客 vscode c/c环境配置&#xff08;MinGW&#xff09;调用第三官方库…

鸿蒙内核源码分析(事件控制篇) | 任务间多对多的同步方案

官方概述 先看官方对事件的描述. 事件&#xff08;Event&#xff09;是一种任务间通信的机制&#xff0c;可用于任务间的同步。 多任务环境下&#xff0c;任务之间往往需要同步操作&#xff0c;一个等待即是一个同步。事件可以提供一对多、多对多的同步操作。 一对多同步模型…

冯喜运:5.6周一国际黄金实时盘面走势分,原油最新操作

【黄金消息面分析】&#xff1a;周一(5月6日)亚市盘中&#xff0c;黄金市场出现大行情。现货黄金短线加速飙升&#xff0c;金价一度触及2315美元/盎司&#xff0c;较日内低点大幅反弹逾20美元/盎司&#xff0c;目前交投于2310.61美元/盎司附近。COMEX最活跃黄金期货合约北京时间…

集合定义和使用方法

一.集合的长度 集合的长度,可以添加和删除,长度也会跟着去发生改变,数组一旦创建完成他的长度就不会发生改变。 二.集合的定义方式 ArrayList<String> list new ArrayList(); 三.集合能存储的数据类型 集合能够存储引用数据类型,存储基本数据类型需要使用包装类: 四…