邱 璇洛 (ゝ∀・)

邱 璇洛 (ゝ∀・)

你好哇(*゚∀゚*)~这里是邱璇洛的博客,常常用来记录一些技术文章和小日常~(σ゚∀゚)σ
twitter
tg_channel

Learn Rust with a console program.

We will create a simple console program for Polish notation using Rust, which supports floating point numbers and negative numbers.

Console Input#

In Rust, obtaining console input is simple. The standard library env provides a way for us to easily obtain console input.

let symbol:String = env::args()
    // the nth input
    .nth(1)
    // simple error handling
    .expect("Incomplete input");

let var_a:String = env::args().nth(2).expect("Incomplete input");
let var_b:String = env::args().nth(3).expect("Incomplete input");


println!("|{}|{}|{}|", symbol, var_a, var_b);

Now, let's run it and see.

cargo run -- 1 2 3

If everything is fine, you will see the following output in the console:

|1|2|3|

Here is the code:

use std::env;

// basic console input
fn obtain_var() {
    // desired values
    let symbol:String = env::args().nth(1).expect("Incomplete input");
    let var_a:String = env::args().nth(2).expect("Incomplete input");
    let var_b:String = env::args().nth(3).expect("Incomplete input");
    println!("|{}|{}|{}|", symbol, var_a, var_b);
}

fn main() {
    obtain_var();
}

But this is not enough. We also need to pass the obtained data to the calculation module, which involves type conversion.

Type Conversion#

To ensure the usability of our console application, we support decimal numbers and negative numbers. Numeric types need to be converted to f64, which is a floating-point number.

// type conversion
fn change_type(var:String) -> f64 {
    let var:f64 = match var.trim().parse() {
        Ok(num) => num,
        Err(_) => {
            println!("Error: Invalid input");
            // return Err
            return 0.0;
        }
    };

    // return the converted value
    var
}

Next, we need to find a way to store our converted types. Here, I chose to use an array for storage.
Current code:

// obtain console input
fn obtain_var() {
    // desired values
    let symbol:String = env::args().nth(1).expect("Incomplete input");
    let var_a:String = env::args().nth(2).expect("Incomplete input");
    let var_b:String = env::args().nth(3).expect("Incomplete input");

    // convert types and store in an array for easy management
    let number_var:[f64; 2] = [change_type(var_a), change_type(var_b)];
...

We also need a method to store the obtained values. Here, I chose to use a struct:
First, declare the struct at the beginning of the program:

...
// use a struct to store data
struct ComputeData {
    symbol:String,
    var_a:f64,
    var_b:f64
}
...

Then, we set this function to return a struct for easy calling.
And create a struct to store the return values:

// obtain console input
fn obtain_var() -> ComputeData {
    // desired values
    let symbol:String = env::args().nth(1).expect("Incomplete input");
    let var_a:String = env::args().nth(2).expect("Incomplete input");
    let var_b:String = env::args().nth(3).expect("Incomplete input");

    // convert types and store in an array for easy management
    let number_var:[f64; 2] = [change_type(var_a), change_type(var_b)];

    // store the data in a struct
    let data = ComputeData {
        symbol:String::from(symbol),
        var_a:number_var[0],
        var_b:number_var[1]
    };

    // function returns a struct
    data
}

Now, we can write a calculation function.

Calculation#

Input data and return result:

// calculation
fn compute(symbol:String, var_a:f64, var_b:f64) -> f64

In theory, we only need to use a match statement to check and return the value. However, in Rust, match cannot directly check the String type, so we need to convert it to &str type.
Complete code:

// calculation
fn compute(symbol:String, var_a:f64, var_b:f64) -> f64 {
    // use a reference to a slice to convert symbol to `&str`
    let symbol:&str = &symbol.to_string()[..];
    match symbol {
        "+" => var_a + var_b,
        "-" => var_a - var_b,
        "*" => var_a * var_b,
        "/" => var_a / var_b,
        // error handling
        _ => {
            println!("Invalid calculation symbol");
            // return `0.0` to indicate an error
            0.0
        }
    }
}

Done!#

Now, let's write a main function.

// improved readability
fn main() {
    println!("{}",compute(
            obtain_var().symbol,
            obtain_var().var_a,
            obtain_var().var_b
        )
    );
}

Running#

cargo run -- operator number1 number2

For example:

cargo run -- / 2 5

When running in the terminal, the result will be returned as 0.4

Complete Code#

use std::env;

// use a struct to store data
struct ComputeData {
    symbol:String,
    var_a:f64,
    var_b:f64
}

fn main() {
    println!("{}",compute(
            obtain_var().symbol,
            obtain_var().var_a,
            obtain_var().var_b
        )
    );
}

// obtain console input
fn obtain_var() -> ComputeData {
    // desired values
    let symbol:String = env::args().nth(1).expect("Incomplete input");
    let var_a:String = env::args().nth(2).expect("Incomplete input");
    let var_b:String = env::args().nth(3).expect("Incomplete input");

    // convert types and store in an array for easy management
    let number_var:[f64; 2] = [change_type(var_a), change_type(var_b)];

    // store the data in a struct
    let data = ComputeData {
        symbol:String::from(symbol),
        var_a:number_var[0],
        var_b:number_var[1]
    };

    // function returns a struct
    data
}

// type conversion
fn change_type(var:String) -> f64 {
    let var:f64 = match var.trim().parse() {
        Ok(num) => num,
        Err(_) => {
            println!("Error: Invalid input");
            // return Err
            return 0.0;
        }
    };

    // return the converted value
    var
}

// calculation
fn compute(symbol:String, var_a:f64, var_b:f64) -> f64 {
    // use a reference to a slice to convert symbol to `&str`
    let symbol:&str = &symbol.to_string()[..];
    match symbol {
        "+" => var_a + var_b,
        "-" => var_a - var_b,
        "*" => var_a * var_b,
        "/" => var_a / var_b,
        // error handling
        _ => {
            println!("Invalid calculation symbol");
            // return `0.0` to indicate an error
            0.0
        }
    }
}

This is actually the first example I have done since learning Rust.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.