邱 璇洛 (ゝ∀・)

邱 璇洛 (ゝ∀・)

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

Learn Rust with a console program

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

Console Input#

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

let symbol: String = env::args()
    // Input position
    .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|

The code at this point is:

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 that's not enough. We also need to pass the obtained data to the calculation module, which involves type conversion.

Type Conversion#

To ensure that our console application is somewhat usable, 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 0.0 to indicate an error
            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 them 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 values we obtained. 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 access.
Also, create a struct to store the returned 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 them 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.
Complete code:

// Calculation
fn compute(symbol: String, var_a: f64, var_b: f64) -> f64 {
    // Convert symbol to `&str` using slice reference mode
    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 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 them 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 0.0 to indicate an error
            return 0.0;
        }
    };

    // Return the converted value
    var
}

// Calculation
fn compute(symbol: String, var_a: f64, var_b: f64) -> f64 {
    // Convert symbol to `&str` using slice reference mode
    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.