在Rust中使用stdin数据实例化struct

 张露-Luna_309 发布于 2023-02-07 12:18

我对Rust非常非常新,并试图实现一些简单的东西来感受语言.现在,我绊倒了实现类似类的结构的最佳方法,该结构涉及将字符串转换为int.我正在使用全局命名空间的函数,我觉得我的红宝石大脑感觉不对.

这样做的乡村方式是什么?

use std::io;

struct Person {
  name: ~str,
  age: int
}

impl Person {  
  fn new(input_name: ~str) -> Person {
    Person { 
      name: input_name, 
      age: get_int_from_input(~"Please enter a number for age.")
    }
  }

  fn print_info(&self) {
    println(fmt!("%s is %i years old.", self.name, self.age));
  }

}

fn get_int_from_input(prompt_message: ~str) -> int {
  println(prompt_message);
  let my_input = io::stdin().read_line();
  let my_val =
    match from_str::(my_input) {
      Some(number_string)   => number_string,
      _                     => fail!("got to put in a number.")
  };

  return my_val;
}


fn main() {
  let first_person = Person::new(~"Ohai");
  first_person.print_info();
}

这会编译并具有所需的行为,但我不知道该做什么 - 显然我不了解最佳实践或如何实现它们.

编辑:这是0.8

1 个回答
  • 这是我的代码版本,我更加惯用:

    use std::io;
    
    struct Person {
      name: ~str,
      age: int
    }
    
    impl Person {
      fn print_info(&self) {
        println!("{} is {} years old.", self.name, self.age);
      }
    
    }
    
    fn get_int_from_input(prompt_message: &str) -> int {
      println(prompt_message);
      let my_input = io::stdin().read_line();
      from_str::<int>(my_input).expect("got to put in a number.")
    }
    
    
    fn main() {
      let first_person = Person {
        name: ~"Ohai",
        age: get_int_from_input("Please enter a number for age.")
      };
      first_person.print_info();
    }
    

    fmt!/format!

    首先,Rust正在弃用fmt!宏,使用printf基于语法的语言format!,而使用类似于Python格式字符串的语法.新版本的Rust 0.9将抱怨使用fmt!.因此,你应该更换fmt!("%s is %i years old.", self.name, self.age)使用format!("{} is {} years old.", self.name, self.age).但是,我们有一个方便的宏println!(...),意味着完全相同的东西println(format!(...)),所以在Rust中编写代码的最惯用的方法是

    println!("{} is {} years old.", self.name, self.age);
    

    初始化结构

    对于类似的简单类型Person,在Rust中使用struct literal语法创建该类型的实例是惯用的:

    let first_person = Person {
        name: ~"Ohai",
        age:  get_int_from_input("Please enter a number for age.")
    };
    

    如果你想要一个构造函数,Person::new是一个类型的'默认'构造函数(我指的是最常用的构造函数)的惯用名Person.但是,默认构造函数要求从用户输入初始化似乎很奇怪.通常,我认为你会有一个person模块,例如(person::Person由模块导出).在这种情况下,我认为使用模块级函数是最惯用的fn person::prompt_for_age(name: ~str) -> person::Person.或者,您可以在Person- 上使用静态方法Person::prompt_for_age(name: ~str).

    &str~str函数参数

    我已经改变了的签名get_int_from_input采取&str代替~str.~str表示在交换堆中分配一个字符串-换句话说,该堆malloc/ free在C,或new/ deleteC++中进行操作.但是,与C/C++不同,Rust强制要求交换堆上的值一次只能由一个变量拥有.因此,将a ~str作为函数参数意味着函数的调用者不能重用~str它传入的参数 - 它必须复制~str使用该.clone方法.

    另一方面,&str是字符串中的切片,它只是对字符串中一系列字符的引用,因此在调用带&str参数的函数时,不需要分配新的字符串副本.

    使用的原因&str,而不是~str用于prompt_messageget_int_from_input是该功能不需要守住过去的函数结束的消息.它只使用提示信息来打印它(并println采用a &str而不是a ~str).一旦你改变了要使用的函数&str,就可以调用它get_int_from_input("Prompt")来代替它get_int_from_input(~"Prompt"),这样可以避免"Prompt"在堆上进行不必要的分配(同样,你可以避免s在下面的代码中克隆):

    let s: ~str = ~"Prompt";
    let i = get_int_from_input(s.clone());
    println(s);    // Would complain that `s` is no longer valid without cloning it above
                   // if `get_int_from_input` takes `~str`, but not if it takes `&str`.
    

    Option<T>::expect

    Option<T>::expect方法是您拥有的匹配语句的惯用快捷方式,x如果您收到Some(x)或未通过消息,您希望返回该方法None.

    没有回来 return

    在Rust中,它是惯用的(遵循像Haskell和OCaml这样的函数式语言的示例)来返回值而不显式编写return语句.实际上,函数的返回值是函数中最后一个表达式的结果,除非表达式后跟一个分号(在这种情况下它返回(),也就是unit,它本质上是一个空的占位符值 - ()也是什么由没有显式返回类型的函数返回,例如mainor print_info).

    结论

    无论如何,我不是Rust的伟大专家.如果您需要有关Rust的任何帮助,除了Stack Overflow之外,您还可以尝试irc.mozilla.org上的#rust IRC频道或Rust subreddit.

    2023-02-07 12:20 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有