How to read underscores in numbers from CLi

I currently have code that takes 1 or 2 number inputs from the CLI.
Currently I have to write them as: 123456789
But I also want to write them as : 1_234_456_789

How do you do that in Rust?

Here's my Rust code:

  let mut val = String::new();           // Inputs are 1 or 2 range values < 2**64
  std::io::stdin().read_line(&mut val).expect("Failed to read line");
  let mut substr_iter = val.split_whitespace();
  let mut next_or_default = |def| -> usize {
      substr_iter.next().unwrap_or(def).parse().expect("Input is not a number")
  };
  let mut end_num = std::cmp::max(next_or_default("3"), 3);  // min vals 3
  let mut start_num = std::cmp::max(next_or_default("3"), 3);

For comparison, here's how to read the underscores in Crystal:

  end_num   = {(ARGV[0].to_u64 underscore: true), 3u64}.max
  start_num = ARGV.size > 1 ? {(ARGV[1].to_u64 underscore: true), 3u64}.max : 3u64

You can use the replace method to replace '_' with nothing.

Example:

fn main() {
    let raw = "123_456_789 1_000_000";

    let v: Vec<u64> = raw
        .split_whitespace()
        .map(|r| r.replace('_', "").parse().unwrap())
        .collect();

    assert_eq!(v, [123_456_789, 1_000_000]);
}

Playground.

Dies this example for String::retain help? String in std::string - Rust

I can't get either of those 2 to work|compile in my code.

Could you show how to use them in my code example?

Like this, maybe? You only need to change the call in your next_or_default closure and add a replace('_', "") before parse():

fn main() {
    let val = "123_456_789 1_000_000";
    
    let mut substr_iter = val.split_whitespace();
    
    let mut next_or_default = |def| -> usize {
        substr_iter.next().unwrap_or(def).replace('_', "").parse().expect("Input is not a number")
    };
    
    assert_eq!(next_or_default("3"), 123_456_789);
    assert_eq!(next_or_default("3"), 1_000_000);
    assert_eq!(next_or_default("3"), 3);
}

Playground.

Thanks! That works like a charm. :hugs:

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.