unanimous0

[RUST 2-3] 표준입력과 Result 타입 본문

RUST

[RUST 2-3] 표준입력과 Result 타입

unanimous0 2025. 3. 11. 15:55
  • 표준 입력 (std::io::stdin())
    • 파이썬에는 input() 함수가 있지만 러스트는 표준 입력을 사용
    • 따라서 파이썬과 달리 편리한 input 함수가 없으므로 따로 정의해서 사용해야함
pub mod str_parse_f;

// 비만도 진단 도구
fn main() {
    // 키와 몸무게 입력
    let height_cm = input("키(cm) : ");
    let weight = input("몸무게(kg) : ");
    
    // BMI 계산
    let height = height_cm / 100.0;
    let bmi = weight / height.powf(2.0);
    println!("BMI={:.1}", bmi);

    // 비만도 진단
    if bmi < 18.5 { println!("저체중"); }
    else if bmi < 23.0 { println!("정상"); }
    else if bmi < 25.0 { println!("비만 전단계"); }
    else if bmi < 30.0 { println!("비만 1단계"); }
    else if bmi < 35.0 { println!("비만 2단계"); }
    else { println!("비만 3단계"); }
}


// 표준 입력에서 1줄씩 읽어 f64 타입으로 반환하는 함수
fn input(prompt: &str) -> f64 {
    // 메세지 출력
    println!("{}", prompt);

    // 입력 값 가져오기
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).expect("입력 에러");

    // 공백을 제거하고 숫자로 변환
    return s.trim().parse().expect("숫자가 아님");
}

 

  • std::io::stdin().read_line()
    • 표준 입력에서 한 줄씩 읽어들여 String 타입 변수 s에 대입
  • parse()
    • String 타입 변수를 f64 타입으로 변환
    • 러서트에서 문자열을 숫자로 변환할 때는 parse 메서드를 사용함
    • 위 코드에서는 단순히 parse 메서드를 사용했지만, 실제로는 타입 추론 기능이 동작해 함수의 반환값인 f64로 변환이 이루어짐
    • 즉 String::parse::<f64> 라는 메서드가 호출되는 것
      • 단 모든 문자열을 숫자로 바꿀 수는 없음
      • parse 메서드의 반환값은 Result 타입인데 Result 타입에서 값을 출력하기 위해서는 expect 메서드를 사용함
      • 변환에 실패하면 에러가 출력되고 프로그램은 강제 종료됨

 

  • Result 타입 처리
    • 구성 형태 : 'Result<"데이터 타입", "에러 타입">'
    • 위의 코드에서는 Result<f64, ParseFloatError> 형태
    • Result를 화면에 출력하는 다양한 방법
      • expect(에러메세지) : 에러 발생시 에러메세지 출력 (에러 발생하는 경우 프로그램은 강제 종료(Panic)됨)
      • unwrap() : 에러메세지 출력 불가 (expect와 같이 처리 실패시 바로 강제 종료)
      • println! 매크로에서 "{}" 대신 "{:?}" 사용 : Ok() 안에 결과가 표시됨
      • match
    • match로 Result 타입 처리
// 위의 코드에서 let s에 숫자가 아닌 다른 문자를 입력하면 에러가 표시되고 종료됨


fn main() {
	let s = "3.1414a";
    let num = s.parse::<f64>();
    match num {
    	Ok(result) => println!("{:.2}", result),
        Err(e) => println!("에러가 발생했습니다. 이유 : '{:?}'", e)
    }
}

// 실행 결과
// "에러가 발생했습니다. 이유 : 'ParseFloatError { kind: Invalid }'

 

 

  • 표준 입출력에서의 에러 처리
    • 콘솔로부터의 입력뿐 아니라 파일이나 네트워크로부터의 입출력에는 에러가 빈번하게 발생함
    • 따라서 입출력이 있는 프로그램에서는 에러 처리가 중요함
    • 코드 작성
      • 위의 코드에서는 숫자가 아닌 문자를 입력하면 에러가 발생해 강제 종료 됐었으나, 다시 숫자를 입력하도록 수정
fn main() {
    let mut height;

    // 반복문
    loop {
        println!("키(cm) : ");
        height = input_fault(0.0);  // 숫자 입력
        
        if height > 0.0 { break; }  // 숫자면 break
        println!("숫자만 입력 가능합니다.");  // 숫자 아니면 출력
    }

    // 표준 체중 계산
    let weight = 22.0 * (height / 100.0).powf(2.0);
    println!("표준 체중은 {:.1}kg 입니다.", weight);
}

// 표준 입력에서 문자열 얻기
fn input_str() -> String {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).expect("입력 에러");
    return s.trim_end().to_string();
}

// 표준 입력에서 실패 시 def 반환
fn input_fault(def: f64) -> f64 {
    let s = input_str();
    match s.trim().parse() {
        Ok(v) => v,
        Err(_) => def,
    }
}

// 실행시 숫자 외의 문자를 입력하면 에러 메세지가 뜨고 다시 입력 프롬프트가 표시됨
// 숫자를 입력하지 않는 이상 프로그램은 종료되지 않음
// 강제종료하려면 Ctrl+C 입력

'RUST' 카테고리의 다른 글

[RUST 2-5] 명령줄 다루기 (std::env::args)  (0) 2025.03.14
[RUST 2-4] HashMap  (0) 2025.03.14
[RUST 2-2] 난수를 이용한 미로 만들기 (Binary Tree)  (0) 2025.03.11
[RUST 2-1] Cargo & Crates  (1) 2025.03.06
[RUST 1-7] 참조  (0) 2025.03.02