포맷 출력

출력 매크로

Rust의 인쇄(출력) 기능은 std::fmt 모듈 안에 있는 일련의매크로로 구현됩니다. 자주 사용하는 매크로 설명은 아래와 같습니다:

  • format!:포맷된 텍스트를 문자열에 기록
  • print!:콘솔(표준 출력)에 내용 출력
  • println!print!와 동일하며 끝에 자동 개행 삽입
  • eprint!:표준 오류 스트림에 내용 출력
  • eprintln!eprint!와 동일하며 끝에 자동 개행

끝에 ln이 붙는 매크로는 개행 문자가 추가되어 출력 완료 후 줄이 바뀝니다.

앞자리에 붙는 e는 error의 약자로 오류 정보를 출력할 때 사용합니다

위 모든 매크로는 포맷 문법이 완전히 동일하며, Rust는컴파일 단계에서 포맷 코드의 유효성을 검사합니다.

사용 예시

기본 자리 표시자 {}

{}는 범용 자리 표시자로 뒤에 전달한 매개변수를 순서대로 교체하고 자동으로 문자열로 변환하여 출력합니다.

fn main() {
    println!("{} days", 31);
    // 출력:31 days
}Code language: JavaScript (javascript)

위치 매개변수

{} 안에숫자 인덱스(0부터 시작)를 적으면 원하는 순서의 매개변수를 직접 지정할 수 있으며 매개변수 재사용, 순서 뒤섞기를 지원합니다.

fn main() {
    println!("{0}, this is {1}. {1}, this is {0}", "Alice", "Bob");
    // 출력:Alice, this is Bob. Bob, this is Alice
}Code language: JavaScript (javascript)

위 예시에서 보듯 매개변수 인덱스를 0,1,2 순서대로 사용하지 않고 순서를 섞어도 됩니다. 뒤에 적은 매개변수 “Alice”는 0번, “Bob”은 1번으로 할당됩니다.

이름 지정 매개변수

인덱스로 참조하는 방식이 직관적이지 않다면 “이름 지정 매개변수“를 사용할 수 있습니다. 포맷 문자열 안에 {매개변수명}을 쓰고 호출할 때 매개변수명=값 형식으로 전달합니다. 전달 순서에 구애받지 않고 가독성이 더 좋습니다.

fn main() {
    println!("{subject} {verb} {object}",
         object="the lazy dog",
         subject="the quick brown fox",
         verb="jumps over");
    // 출력:the quick brown fox jumps over the lazy dog
}Code language: JavaScript (javascript)

뒤에 전달하는 값에 이름을 붙이고 포맷 문자열에서 {매개변수명}으로 호출하는 방식이라 훨씬 직관적입니다.

진수 포맷팅(:서식 기호

자리 표시자 안에 : 뒤에 서식 문자를 적으면 숫자를이진수, 팔진수, 십육진수 등 다른 진수로 변환할 수 있습니다.

  • :b:이진수
  • :o:팔진수
  • :x:소문자 십육진수
fn main() {
    println!("십진수:    {}",   69420);    // 69420
    println!("이진수:  {:b}", 69420);    // 10000111100101100
    println!("팔진수:  {:o}", 69420);    // 207454
    println!("십육진수:{:x}", 69420);    // 10f2c
}Code language: JavaScript (javascript)

너비 정렬 및 채움 문자

1 오른쪽 정렬(>너비

{:>n}은 전체 출력 너비를 n으로 지정하고 내용을오른쪽 정렬한 뒤 왼쪽을 공백으로 채웁니다.

fn main() {
    println!("{number:>5}", number=1);
    // 총 너비5, 왼쪽 공백 4개 채움 → 출력:    1
}Code language: JavaScript (javascript)
2 0으로 채우는 정렬

정렬 기호 앞에 0을 적으면 공백 대신숫자 0으로 빈 공간을 채웁니다.

  • :0>5:오른쪽 정렬, 왼쪽 0 채움
  • :0<5:왼쪽 정렬, 오른쪽 0 채움
fn main() {
    println!("{number:0>5}", number=1); // 오른쪽 정렬 0채움 → 00001
    println!("{number:0<5}", number=1); // 왼쪽 정렬 0채움 → 10000
}Code language: JavaScript (javascript)

채우는 문자는 꼭 0이 아니고 다른 아무 문자도 사용 가능합니다. 아래 예시는 왼쪽을 대문자 A로 채우는 경우입니다

fn main() {
    println!("{number:A>5}", number=1); // 오른쪽 정렬 A채움 → AAAA1
    println!("{number:A<5}", number=1); // 왼쪽 정렬 A채움 → 1AAAA
}Code language: JavaScript (javascript)
3 동적 너비 지정(변수명$

너비를 하드코딩하지 않고 변수명$으로 외부 이름 지정 매개변수/변수를 참조해 동적으로 너비를 조절할 수 있습니다.

즉 출력 너비를 코드에 고정으로 적지 않고 변수로 제어할 수 있다는 뜻입니다.

fn main() {
    // 방식1:이름 지정 매개변수와 함께 사용
    println!("{number:0>width$}", number=1, width=8);

    // 방식2:코드 내 변수 직접 참조(Rust 1.58 이상 지원)
    let number: f64 = 1.0;
    let width: usize = 8;
    println!("{number:>width$}"); // 출력:       1
}Code language: JavaScript (javascript)

컴파일 단계 매개변수 검증

Rust는컴파일 단계에서 자리 표시자 개수와 전달한 매개변수 개수가 일치하는지 확인하며 매개변수가 부족하면 바로 컴파일 오류를 반환합니다.

fn main() {
    // 자리 표시자 2개인데 매개변수 1개만 전달 → 컴파일 실패
    println!("My name is {0}, {1} {0}", "Bond");
    // 수정:매개변수 "James" 추가
    println!("My name is {0}, {1} {0}", "Bond", "James");
}Code language: JavaScript (javascript)

컴파일 오류 메시지:{1} 위치가 유효하지 않음, 뒤에 매개변수가 한 개밖에 없기 때문

오류:존재하지 않는 위치 매개변수 1을 참조했습니다 (현재 전달된 매개변수는 단 1개)
 --> D:\rustdemo\hello.rs:3:29
  |
3 |     println!("My name is {0}, {1} {0}", "Bond");
  |                                ^
  |
  = 힌트:위치 매개변수는 0부터 번호가 매겨집니다

오류:컴파일 중단, 총 1건의 오류 발생Code language: JavaScript (javascript)

사용자 정의 타입 포맷 제한

기본 상태에서 {}는 오직fmt::Display 트레이트를 구현한 타입만 포맷팅할 수 있습니다. 사용자 정의 구조체는 기본적으로 해당 트레이트가 구현되지 않아 그냥 {}로 출력하면 컴파일 오류가 발생합니다.

fn main() {
    struct Structure(i32);
    // 아래 코드는 컴파일 불가
    println!("{}", Structure(3));
}Code language: JavaScript (javascript)
오류[E0277]:구조체 `Structure``std::fmt::Display` 트레이트가 구현되지 않음
 --> D:\rustdemo\hello.rs:4:20
4 |     println!("{}", Structure(3));
  |               --   ^^^^^^^^^^^^ 이 타입은 기본 포맷터로 출력할 수 없음
  |               |
  |               여기 서식 인자는 타입에 Display 트레이트 구현을 요구합니다

힌트:`Structure` 구조체에 `std::fmt::Display` 트레이트가 구현되지 않음
 --> D:\rustdemo\hello.rs:2:2
2 |     struct Structure(i32);
  |     ^^^^^^^^^^^^^^^^

추가 설명:서식 문자열에서 대안으로 `{:?}` (또는 보기 좋게 출력하는 `{:#?}`)를 사용해보세요
컴파일 중단, 총 1건의 오류.

오류 자세한 내용 확인 명령:rustc --explain E0277Code language: JavaScript (javascript)

* 1 구조체를 출력하려면 Display 트레이트를 구현해야 합니다 (지금은 가볍게 이해만 하고 다음 시간에 자세히 다룹니다)

use std::fmt;

struct Structure(i32);

// 구조체에 Display 트레이트 구현
impl fmt::Display for Structure {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // self.0으로 튜플 구조체 내부 i32 값 접근
        write!(f, "수치:{}", self.0)
    }
}

fn main() {
    println!("{}", Structure(3));
}Code language: PHP (php)
* 2 임시 디버깅 → 디버그 서식 {:?} / {:#?} 사용

프로그래머 디버깅에 적합합니다. 정식 환경이 아닌 단순히 구조체 내부 값을 확인하려면 Debug 디버그 트레이트를 활용하면 됩니다

Rust는 사용자 정의 타입에 기본적으로디버그 트레이트 Debug가 구현되어 있어 {:?}로 바로 출력 가능:

#[derive(Debug)]
#[allow(dead_code)] // 사용하지 않는 코드/필드 경고 숨기기
struct Structure(i32);

fn main() {
    println!("{:?}", Structure(3));
    println!("{:#?}", Structure(3));
}Code language: PHP (php)

* std::fmt 핵심 두 가지 포맷 트레이트

std::fmt 모듈에는 텍스트 표시를 제어하는 여러 트레이트가 포함되며 자주 쓰이는 두 가지는 다음과 같습니다:

  1. fmt::Debug는 자리 표시자 {:?}와 함께 쓰이며디버깅 용도 출력에 특화됩니다.
  2. fmt::Display는 자리 표시자 {}와 함께 쓰이며 일반 사용자에게 표준적이고 보기 좋은 형태로 내용을 보여줍니다.

표준 라이브러리 내장 타입은 두 트레이트가 기본 구현되어 바로 출력 가능;사용자 정의 타입은 바로 사용 불가이며 해당 트레이트를 직접 구현해야 합니다.

타입에 fmt::Display를 구현하면 자동으로 ToString 트레이트도 함께 구현되어 해당 타입을 문자열로 변환하는 기능을 쓸 수 있습니다.

#[allow(dead_code)]

#[allow(dead_code)]는 코드 속성으로 바로 뒤 코드 항목에 적용되어「미사용 코드」경고를 차단하는 역할입니다.

위 예시를 보자

fn main() {
    struct Structure(i32);
    // 아래 코드는 컴파일 불가
    //println!("{}", Structure(3));
}Code language: JavaScript (javascript)

두 번째 줄 println!(“{}”, Structure(3)); 이 오류가 나서 주석 처리했는데 이 상태로 실행하면,

경고:구조체 `Structure`가 한 번도 생성되지 않음
 --> D:\rustdemo\hello.rs:2:12
  |
2 |     struct Structure(i32);
  |            ^^^^^^^^^
  |
  = 참고:`#&#91;warn(dead_code)]` (`#&#91;warn(unused)]`에 포함) 기본 활성화

경고:총 1건의 경고 출력됨
Code language: JavaScript (javascript)

이런 경고가 뜨는 이유는 struct Structure(i32); 코드가 전혀 사용되지 않았기 때문입니다. 이 경고를 숨기고 싶다면 해당 속성을 추가하면 됩니다

fn main() {
    #[allow(dead_code)] 
    struct Structure(i32);
    // 아래 코드는 컴파일 불가
    //println!("{}", Structure(3));
}Code language: PHP (php)
부동 소수점 소수점 자리 지정

변수 pi = 3.141592를 정의하고 포맷 출력으로소수점 세 자리까지 표시하는 코드를 작성, 출력 내용:Pi is roughly 3.142

<code
Previous:

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다