< 返回版块

wpdzyx 发表于 2021-09-19 15:37

Tags:rust, match,readline

我在db.txt中存放了如下user name数据: alice bob david

下面的函数是从标准输入读取user name, 然后与存放在db.txt中的数据对比,如果存在,则打印exist,如果不存在,则写入到db.txt. 但是下面的函数check_user_exist中,match第一个条件总是匹配的,这是为什么呢?

use std::fs::File;
use std::io::{self, prelude::*, BufReader};
use std::path::Path;
use std::fs::OpenOptions;
use std::io::Write;

pub fn login()->io::Result<()>{
    db_init();

    let mut name = String::new();
    io::stdin().read_line(&mut name)?;
    match check_user_exist(name.as_str()) {
        Ok(exist) => println!("{:?}",exist),
        Err(_) => println!("register new name."),
    }
    Ok(())
}

fn check_user_exist(name:&str) -> io::Result<()> {

    let file = File::open("db.txt")?;
    let reader = BufReader::new(file);
    for line in reader.lines().map(|l| l.unwrap()) {
        match line.as_str(){
            name  => println!("found str {}",name),   // **always match, why ?? **
            _ => register(name),
        }
    }
    Ok(())
}  

fn register(name:&str){

    let mut file = OpenOptions::new().append(true).open("db.txt").expect(
        "cannot open file");
     file.write_all(name.as_bytes()).expect("write file faile");
}

fn db_init(){
    if Path::new("db.txt").exists() {
        println!("db already inited!");
    }
    else{
        println!("db not initialized. create db file!");
        let file = File::create("db.txt").expect("create file fail");
    }
}

fn main(){
    println!("start main\n");

    login();
}

评论区

写评论
作者 wpdzyx 2021-09-20 15:03

https://learnku.com/docs/rust-lang/2018/ch18-03-pattern-syntax/4572

看起来还是没把文档看透彻,我的疑问在18章节中可以找到答案了,多谢回复!

作者 wpdzyx 2021-09-19 23:10

match ... name if name == target

我尝试着加了match guard, 加外上input string strim结尾的空格后,貌似可以工作了,非常感谢。想请教的是,if语句是相当于重新binding了值到name上? 如果不加if, 为什么这里的name会屏蔽上面的name binding?这点一直没有明白,我在文档中也没有找到相关的说明。

--
👇
gwy15: ``` match line.as_str(){ name => println!("found str {}",name), // **always match, why ?? ** _ => register(name), }


创建了一个名叫 name 的 binding,而且屏蔽了你上面的 name binding,不信你把 name 改成 name2。

可以这样写

match ... name if name == target =>



作者 wpdzyx 2021-09-19 22:57

😂,你说的没错,我再看这里的逻辑是有问题的。if应该也是可以,可以试一下。

--
👇
rayw0ng: 你这逻辑也不对呀,应该循环完毕才能确定是不是exist,而不是每一行都register一下。这个地方用if就挺好,没必要非用match。

rayw0ng 2021-09-19 20:46

你这逻辑也不对呀,应该循环完毕才能确定是不是exist,而不是每一行都register一下。这个地方用if就挺好,没必要非用match。

gwy15 2021-09-19 15:51
match line.as_str(){
       name  => println!("found str {}",name),   // **always match, why ?? **
       _ => register(name),
}

创建了一个名叫 name 的 binding,而且屏蔽了你上面的 name binding,不信你把 name 改成 name2。

可以这样写

match ...
    name if name == target => 
作者 wpdzyx 2021-09-19 15:44

https://stackoverflow.com/questions/28225958/why-is-this-match-pattern-unreachable-when-using-non-literal-patterns

我有在stack overflow上搜索到一些讨论帖,讲到match 匹配必须是编译时期就可以确定的东西。现在从input读取的数据是运行时才能确定的,如果是这样的话,要比较input与文件中存放的数据,Match无法使用在这里了吗?

1 共 6 条评论, 1 页