본문 바로가기
Rust

Rust 설치부터 실행까지 (형변환 및 에러 처리) - 3

by lms0806 2024. 12. 20.
728x90
반응형

오늘의 Rust의 문자열 입력 및 형변환, 반복문에 대해 배워보고자 합니다.

입출력

rust는 기본적으로 std::io를 활용하여 입력합니다.

 

C++의 std::cin과 비슷한 형식입니다.

use std::io;

fn main() {
    let mut guess = String::new();

    io::stdin()
        .read_line(&mut guess)
        .expect("Failed to read line");

    println!("You guessed: {guess}");
}

불변 / 가변

다음과 같이 guess에 String타입의 값을 입력합니다.

let mut guess = String::new();

여기서 rust의 불변과 가변 형식이 드러나게 됩니다.

 

다음과 같이 선언하여 사용하는 경우 rust는 default로 변수를 선언할 경우, 불변(변하지 않는)입니다.

let guess = String::new();

여기서 mut(mutable)을 추가하여 선언하게 되는 경우, 해당 값은 변경이 가능하게 됩니다.

let mut guess = String::new();

입력

rust는 다음과 같이 입력을 받을 수 있습니다.

io::stdin()
        .read_line(&mut guess)
        .expect("Failed to read line");

C++의 std::cin 방식과 동일하게 std::io::stdin 으로 입력을 받을 수 있습니다.

 

입력을 받되 read_line()으로 한줄을 입력받고 &mut guess로 인자로 전달하여 사용자가 입력한 문자열이 어디에 저장될지 알려줍니다.

 

rust는 특정 명령을 수행할 때마다, 성공과 실패에 대한 결과(Result)를 지정해주어야 합니다.

 

.expect("Failed to read line");이라는 expect을 통하여 만약, 문자열을 입력받는 행동에서 에러가 발생할 경우, 어떻게 할건지에 대하여 알려주게 됩니다.

 

알고리즘 문제 풀이의 경우, 잘못된 입력이 들어오지 않아 .OK()로 사용하셔도 무방합니다.

출력

출력의 경우 색다른 방식으로 가능합니다.


JAVA의 경우 System.out.println()으로 가능하고, C++의 경우 std::cout와 같은 방식으로 가능하지만 rust의 경우 println!();으로 진행합니다.

println!("You guessed: {guess}");

추가로 변수를 출력할 때는 JAVA의 String.format()과 같은 방식으로 진행하게 됩니다.

다음과 같은 두 방식 모두 같은 효과를 냅니다.

println!("You guessed: {guess}");
println!("You guessed: {}", guess);

형변환

인제 입력도 받았겠다 다시 정수형으로 바꿔봅시다.

use std::io;

fn main() {
    let mut guess = String::new();

    io::stdin()
        .read_line(&mut guess)
        .expect("Failed to read line");

    let guess: u32 = guess.trim().parse().expect("Please type a number!");

    println!("You guessed: {guess}");
}

다음과 같은 코드가 정상적으로 돌아갈까요?


네, 같은 변수명을 가지고 있어도 rust는 정상적으로 동작합니다.

 

러스트는 이전에 있던 guess라는 값을 새로운 값으로 가리는 shadow라는 것을 허용합니다.

 

새도잉(shadowing)이란, guess_str과 guess처럼 두 개의 다른 변수를 사용하도록 강제하기보다는 guess라는 변수명을 재사용할 수 있도록 해줍니다. (매우 좋지만 에러 체크하기에는 어려워 보인다)

 

자 다시 형변환으로 돌아와서

let guess: u32 = guess.trim().parse().expect("Please type a number!");

trim() 함수는 다른 언어들과 동일하게 처음과 끝부분의 공백을 제거해줍니다.

 

parse()함수는 rust에서 원래 타입과 다른 타입으로 바꿔줍니다.


우리는 guess라는 문자열을 u32이라는 부호가 없는 32비트 정수로 바꾸고자 할때 사용하여, guess: u32와 같은 방식으로 알려주어야 합니다.

 

여기서도 마찬가지로 String타입을 u32 정수타입으로 변경할 때, 에러가 발생할 경우에 대한 처리로 expect("Please type a number!"); 다음과 같이 해주었습니다.

반복문

JAVA나 C++의 경우 while(true)와 같은 방식으로 진행하지만, rust에서의 반복문은 loop로 가능합니다.

해당 코드는 무한으로 Heelo World를 출력하는 코드입니다.

fn main() {
    loop {
        println!("Hello World");
    }
}

loop를 탈출하는 방법에는 여러가지 존재합니다.

  1. loop안에 형변환과 같은 동작을 수행할 때, 맞지 않은 값을 입력하여 error를 발생해 종료시킨다.
  2. break 문으로 탈출한다.

입력이 잘못되어 에러가 발생해도 프로그램을 계속해서 유지하고 싶은 경우에는 어떻게 해야할까요?

use rand::Rng;
use std::cmp::Ordering;
use std::io;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::thread_rng().gen_range(1..=100);

    loop {
        println!("Please input your guess.");

        let mut guess = String::new();

        io::stdin()
            .read_line(&mut guess)
            .expect("Failed to read line");

        let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => continue,
        };

        println!("You guessed: {guess}");

        match guess.cmp(&secret_number) {
            Ordering::Less => println!("Too small!"),
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal => {
                println!("You win!");
                break;
            }
        }
    }
}

해당 코드를 보시다시피 다음과 같은 방법으로 가능합니다.

let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => continue,
        };

match를 통해 guess.trim().parse()에 대한 성공 혹은 에러가 발생한 경우에 대한 대응을 알려줍니다.


해당 코드는 형변환이 성공한 경우 값을 반환하고, 에러가 발생한 경우, continue를 통하여 넘어가도록 설정되어져 있습니다.

728x90
반응형

댓글