学习Rust的第29天: cat in Rust

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

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

伪代码

ba 复制代码
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在库箱中创建一个结构体和一个块。

ba 复制代码
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_names``args
  • 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()函数并使用它

ba 复制代码
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()

让我们实践并运行它。

ba 复制代码
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 💀

ba 复制代码
# ./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_names``args
  • 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命令。
相关推荐
十八朵郁金香7 分钟前
通俗易懂的DOM1级标准介绍
开发语言·前端·javascript
阿尔法波11 分钟前
python与pycharm如何设置文件夹为源代码根目录
开发语言·python·pycharm
xing251619 分钟前
pytest下allure
开发语言·python·pytest
眸笑丶24 分钟前
使用 Python 调用 Ollama API 并调用 deepseek-r1:8b 模型
开发语言·python
计算机毕设指导626 分钟前
基于Springboot学生宿舍水电信息管理系统【附源码】
java·spring boot·后端·mysql·spring·tomcat·maven
计算机-秋大田34 分钟前
基于Spring Boot的兴顺物流管理系统设计与实现(LW+源码+讲解)
java·vue.js·spring boot·后端·spring·课程设计
enyp801 小时前
Qt QStackedWidget 总结
开发语言·qt
gu201 小时前
c#编程:学习Linq,重几个简单示例开始
开发语言·学习·c#·linq
lly2024061 小时前
SQLite 删除表
开发语言
wjs20241 小时前
HTML 字符实体
开发语言