HiveBrain v1.2.0
Get Started
← Back to all entries
patternrustMinor

Simple array "manager"

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
arraysimplemanager

Problem

I'm new to Rust, coming from C++, and so to increase my knowledge of Rust I made a small program to manage an array. You can add, insert, delete, print and more an array or its elements.

I don't really care much about performance at this point, but more on readability, good practices and so on.

So, what could I have done better?

```
use std::io;

fn get_element() -> i64 {
println!("Enter the element: ");

let mut element = String::new();
io::stdin().read_line(&mut element).expect("Failed to read line!");

match element.trim().parse() {
Ok(num) => num,
Err(_) => {
println!("Invalid number! Try again.");
get_element()
}
}
}

fn get_index(length: usize) -> usize {
println!("Enter the index: ");

let mut index = String::new();
io::stdin().read_line(&mut index).expect("Failed to read line!");

match index.trim().parse() {
Ok(index) if index index,
Ok(index) => {
println!("Invalid index! {} is not in range [0, {})! Try again.", index, length);
get_index(length)
},
Err(_) => {
println!("Invalid number! Try again.");
get_index(length)
}
}
}

fn main() {
println!("Welcome to the Vector application!");

let mut vec: Vec = Vec::new();

loop {
println!("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-");
println!("What do you want to do?");
println!("1. Clear the vector");
println!("2. Add element");
println!("3. Insert element at pos");
println!("4. Delete an element at index");
println!("5. Print an element");
println!("6. Print vector");
println!("*. Exit");

let mut input = String::new();
io::stdin().read_line(&mut input).expect("Failed to read line");
let input: u8 = match input.trim().parse() {
Ok(num) if num num,
Ok(num) => {
println!("{} is

Solution

-
Become familiar with rustfmt. For example, else goes on the same line as the previous closing brace:

- }
  • else if input == 2 {


+ } else if input == 2 {


-
Rust doesn't do tail call optimization, so unbounded recursive calls are better replaced with iteration.

-
I might extract a function that does the reading from standard input, trimming, and parsing.

-
No need for a type on the vec; inference will kick in.

-
You can use match with values like numbers. This can be used to replace the large if-else chain at the end of main.

-
Move the command out-of-range check/warning from the "parse" match to the match of the command value. This groups the error text closer to the place that will change.

-
I wouldn't embed the match inside the println!; it's not obvious enough. Instead, put the print inside the match.

-
Can then remove the continue because that's the normal flow

-
Don't convert the number to a string to print it; numbers implement Display.

-
You check the index twice; once when getting the value, once when actually indexing. Remove one or the other.

use std::io;

fn parsed_line() -> Result
    where T: std::str::FromStr
{
    let mut element = String::new();
    io::stdin().read_line(&mut element).expect("Failed to read line!");
    element.trim().parse()
}

fn get_element() -> i64 {
    loop {
        println!("Enter the element: ");

        match parsed_line() {
            Ok(num) => return num,
            Err(_) => println!("Invalid number! Try again."),
        }
    }
}

fn get_index(length: usize) -> usize {
    loop {
        println!("Enter the index: ");

        match parsed_line() {
            Ok(index) if index  return index,
            Ok(index) => {
                println!("Invalid index! {} is not in range [0, {})! Try again.", index, length);
            },
            Err(_) => {
                println!("Invalid number! Try again.");
            }
        }
    }
}

fn main() {
    println!("Welcome to the Vector application!");

    let mut vec = Vec::new();

    loop {
        println!("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-");
        println!("What do you want to do?");
        println!("1. Clear the vector");
        println!("2. Add element");
        println!("3. Insert element at pos");
        println!("4. Delete an element at index");
        println!("5. Print an element");
        println!("6. Print vector");
        println!("*. Exit");

        let input: u8 = match parsed_line() {
            Ok(num) => num,
            Err(_) => break,
        };

        let length = vec.len();

        match input {
            1 => vec.clear(),
            2 => vec.push(get_element()),
            3 => vec.insert(get_index(length), get_element()),
            4 => {
                vec.remove(get_index(length));
            },
            5 => println!("The element is: {}", vec[get_index(length)]),
            6 => {
                for i in &vec {
                    println!("{} ", i);
                }
            }
            other => println!("{} is not in the range [0, 6]!", other),
        };
    }
}

Code Snippets

use std::io;

fn parsed_line<T>() -> Result<T, T::Err>
    where T: std::str::FromStr
{
    let mut element = String::new();
    io::stdin().read_line(&mut element).expect("Failed to read line!");
    element.trim().parse()
}

fn get_element() -> i64 {
    loop {
        println!("Enter the element: ");

        match parsed_line() {
            Ok(num) => return num,
            Err(_) => println!("Invalid number! Try again."),
        }
    }
}

fn get_index(length: usize) -> usize {
    loop {
        println!("Enter the index: ");

        match parsed_line() {
            Ok(index) if index < length => return index,
            Ok(index) => {
                println!("Invalid index! {} is not in range [0, {})! Try again.", index, length);
            },
            Err(_) => {
                println!("Invalid number! Try again.");
            }
        }
    }
}

fn main() {
    println!("Welcome to the Vector application!");

    let mut vec = Vec::new();

    loop {
        println!("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-");
        println!("What do you want to do?");
        println!("1. Clear the vector");
        println!("2. Add element");
        println!("3. Insert element at pos");
        println!("4. Delete an element at index");
        println!("5. Print an element");
        println!("6. Print vector");
        println!("*. Exit");

        let input: u8 = match parsed_line() {
            Ok(num) => num,
            Err(_) => break,
        };

        let length = vec.len();

        match input {
            1 => vec.clear(),
            2 => vec.push(get_element()),
            3 => vec.insert(get_index(length), get_element()),
            4 => {
                vec.remove(get_index(length));
            },
            5 => println!("The element is: {}", vec[get_index(length)]),
            6 => {
                for i in &vec {
                    println!("{} ", i);
                }
            }
            other => println!("{} is not in the range [0, 6]!", other),
        };
    }
}

Context

StackExchange Code Review Q#159815, answer score: 2

Revisions (0)

No revisions yet.