ThomasKarba
ThomasKarba

Reputation: 113

Confusing Output to a HashMap iterable from input in Rust

This program takes as input a sentence " Add name to dept", passes the string into a function that splits the string by whitespace into a vector that then is inserted into a hashmap that is suppose to retain the values of name and dept, which it does for 1 input. On the second input only the first word "Add" is printed. Are there any glaring missteps that may cause this odd output?

use std::io; 
use std::collections::HashMap;
fn main() {
    let mut input = String::new();
    let mut db: HashMap<String,String>  = HashMap::new();
    loop {
        println!("'Add <name> to <department>'");
        io::stdin().read_line(&mut input).expect("Not input");
        add_to_hashmap(&input, &mut db);
        }
}
fn add_to_hashmap(input: &String, db: &mut HashMap<String,String>){
    let v: Vec<&str> = input.split(" ").collect();
    db.insert(v[1].to_string(),v[3].to_string());
    for (name, dept) in db{ 
        println!("{}, {}", name, dept);
    }
    
}

Upvotes: 0

Views: 73

Answers (1)

John Kugelman
John Kugelman

Reputation: 361555

Investigation

To diagnose this I added a dbg! call to check the value of input each time add_to_hashmap is called.

let v: Vec<&str> = dbg!(input).split(" ").collect();

The first time it prints:

'Add <name> to <department>'
Add john to math
[src/main.rs:13] input = "Add john to math\n"
john, math

The second time:

'Add <name> to <department>'
Add bill to science
[src/main.rs:13] input = "Add john to math\nAdd bill to science\n"
john, math
Diagnosis

input isn't being cleared. read_line doesn't erase the input buffer; it just appends to it.

In the documentation you can see that the example code clears the buffer after each call:

use std::io::{self, BufRead};

let mut cursor = io::Cursor::new(b"foo\nbar");
let mut buf = String::new();

// cursor is at 'f'
let num_bytes = cursor.read_line(&mut buf)
    .expect("reading from cursor won't fail");
assert_eq!(num_bytes, 4);
assert_eq!(buf, "foo\n");
buf.clear();

// cursor is at 'b'
let num_bytes = cursor.read_line(&mut buf)
    .expect("reading from cursor won't fail");
assert_eq!(num_bytes, 3);
assert_eq!(buf, "bar");
buf.clear();

// cursor is at EOF
let num_bytes = cursor.read_line(&mut buf)
    .expect("reading from cursor won't fail");
assert_eq!(num_bytes, 0);
assert_eq!(buf, "");

Upvotes: 2

Related Questions