[Chapter 5-2] Rust 구조체를 이용한 예제 프로그램
사각형의 넓이를 계산하는 프로그램을 작성해봅시다.
Cargo로 픽셀 단위로 명시된 사각형의 길이와 넓이를 입력받아 사각형의 넓이를 계산하는 rectangles 라는 이름의 새로운 바이너리 프로젝트를 만듭니다.
cargo new rectangles --bin
filename: src/main.rs
fn main() {
let length1 = 50;
let width1 = 30;
println!(
"The area of the rectangle is {} square pixels.",
area(length1, width1)
);
}
fn area(length: u32, width: u32) -> u32 {
length * width
}
cargo run
으로 실행하면 다음과 같은 결과를 얻을 수 있습니다.
The area of the rectangle is 1500 square pixels.
튜플을 이용한 리팩터링
위의 코드를 더 좋게 변경할 수 있습니다. area
함수의 두 파라미터들은 연관되어 있지만 코드 내 어디에도 표현되지 않았습니다. 튜플을 이용하여 이를 명시할 수 있습니다.
fn main() {
let rect1 = (50, 30);
println!(
"The area of the rectangle is {} square pixels.",
area(rect1)
);
}
fn area(dimensions: (u32, u32)) -> u32 {
dimensions.0 * dimensions.1
}
하지만 다른 한편으로는 튜플에 요소에 대한 이름이 없기 때문에 덜 명확하다고 할 수 있습니다. 튜플 내의 값을 인덱스로 접근해야 하기 때문에 계산이 혼란스러울 수 있습니다. 만약 면적을 구하는 것이 아닌 사각형을 화면에 그리는 상황이라면 문제가 발생할 것입니다.
구조체를 이용한 리펙터링: 의미 추가하기
데이터에 이름표를 붙여 의미를 부여하기 위해 구조체를 사용할 수 있습니다.
struct Rectangle {
length: u32,
width: u32,
}
fn main() {
let rect1 = Rectangle { length: 50, width: 30 };
println!(
"The area of the rectangle is {} square pixels.",
area(&rect1)
);
}
fn area(rectangle: &Rectangle) -> u32 {
rectangle.length * rectangle.width
}
area
함수는 하나의 파라미터를 갖도록 수정되었습니다. 이는 Rectangle
구조체 인스턴스의 불변 참조자 타입입니다. 구조체의 소유권을 얻기 보다는 빌리기를 원하므로, 함수 호출시에 &
를 사용하여 main
이 소유권을 유지하고 rect1
을 계속 사용할 수 있게 됩니다.
파생 트레잇(derived trait)으로 유용한 기능 추가
struct Rectangle {
length: u32,
width: u32,
}
fn main() {
let rect1 = Rectangle { length: 50, width: 30 };
println!("rect1 is {}", rect1);
위의 코드는 Rectangle
인스턴스 출력을 시도하는 코드입니다. 코드를 실행시키면 다음과 같은 메세지와 함께 에러가 발생하게 됩니다.
error[E0277]: the trait bound `Rectangle: std::fmt::Display` is not satisfied
구조체를 사용하는 경우 println!
이 출력을 형식화하는 방법이 모호하기 때문입니다. 사용자가 쉼표를 이용하고 싶은지, 중괄호를 이용하고 싶은지 등이 모호합니다. Rust는 사용자가 원하는 것을 추론하려고 하지 않습니다.
에러 메세지 중에서 아래와 같은 도움말을 볼 수 있습니다.
note: `Rectangle` cannot be formatted with the default formatter; try using
`:?` instead if you are using a format string
이를 적용하여 println!
매크로 호출을 println!("rect1 is {:?}", rect1);
의 형태로 사용해봅시다. { }
내에 : ?
명시자를 넣는 것은 println!
에게 Debug라 불리는 출력 포맷을 사용하고 싶다고 알려주는 것입니다.
하지만 변경한 코드를 실행해도 여전히 에러가 발생합니다.
error: the trait bound `Rectangle: std::fmt::Debug` is not satisfied
note: `Rectangle` cannot be formatted using `:?`; if it is defined in your
crate, add `#[derive(Debug)]` or manually implement it
구조체에 대해 해당 기능을 활성화하도록 명시적인 사전동의가 필요합니다. 구조체 정의부분 바로 전에 #[derive(Debug)]
어노테이션을 추가합니다.
#[derive(Debug)]
struct Rectangle {
length: u32,
width: u32,
}
fn main() {
let rect1 = Rectangle { length: 50, width: 30 };
println!("rect1 is {:?}", rect1);
}
rect1 is Rectangle { length: 50, width: 30 }
println!
스트링 내에 { : ? }
대신 { : # ? }
을 사용할 수 있습니다. 출력은 아래와 같습니다.
rect1 is Rectangle {
length: 50,
width: 30
}
Author And Source
이 문제에 관하여([Chapter 5-2] Rust 구조체를 이용한 예제 프로그램), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@inhwa1025/Chapter-5-2-Rust-구조체를-이용한-예제-프로그램저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)