Rust 문자열

mohadang·2023년 1월 22일
0

Rust

목록 보기
12/30
post-thumbnail

Rust의 문자열 자료형

Rust의 문자열 자료형은 &'static str 이다.
& : 메모리를 참조하고 있다
'static : 문자열 데이터가 프로그램이 끝날 때까지 유효(Drop 되지 않음)
str : 언제나 유효한 UTF-8 바이트 열
mut : 없으니 값의 변경을 허용하지 않음

Rust의 문자열은 언제나 유효

fn main() {
    let a: &'static str = "Hi";
    println!("{} {}", a, a.len());
}

'r#', '#'

fn main() {
    let a: &'static str = r#"
        <div class="advice">
            Raw strings are ...
        </div>
        "#;
    println!("{} {}", a, a.len());
}

시작점의 r# : 원시 문자열 지정, 덕분에 "advice"를 온전히 문자열의 일부로 해석
끝점의 # : 문자열을 있는 그대로 표현

문자열을 char 벡터로 반환

fn main() {
    let chars = "Hello!".chars().collect::<Vec<char>>();
    println!("{}", chars.len());
    println!("{}", chars[3] as u32);
}

Rust에서는 UTF-8 바이트 열을 char 타입의 벡터로 돌려주는 기능 제공.
char 하나는 4바이트다.

스트링

UTF-8 바이트 열을 힙 메모리에 소유하는 구조체
문자열과는 달리 변경 가능

fn main() {
    let mut helloworld = String::from("hello");
    helloworld.push_str(" world");
    helloworld = helloworld + "!";
    println!("{helloworld}");
}

함수 배개변수로서의 텍스트

문자열과 스트링은 일반적으로 함수에 문자열 슬라이스 형태로 전달.
이 방법은 소유권을 넘길 필요가 없어 대부분의 경우에 유연.

fn say_it(msg: &str) {
    println!("{msg}");
}

fn main() {
    say_it("hello");
    say_it(&String::from("goodbye"));
}

스트링 만들기

concat 과 join은 스트링을 만드는 간단하지만 강력한 방법

fn main() {
    let hello = ["hello", " ", "world", "!"].concat();
    let abc = ["a", "b", "c"].join(",");
    println!("{}", hello);
    println!("{}", abc);

    let s = concat!("test", 10, 'b', true);
    assert_eq!(s, "test10btrue");    
}

format

문자열 포맷도 인스터스화 가능

fn main() {
    let a = 42;
    let f = format!("secret to lilfe: {}", a);
    println!("{}", f);
}

문자열 슬라이스

문자열 슬라이스는 메모리 상의 바이트 열에 대한 참조이다. String 처럼 문자열이 아니다
즉 &str이 바로 문자열 슬라이스이다.

문자열 슬라이스는 참조이기에 언제나 유효한 utf-8이어야 한다.
str slice의 문자열 slice (sub-slice)도 역시 유효한 utf-8이어야 합니다.

fn main() {
    let a = "hi 🦀";
    println!("{}", a.len());// 7 바이트
    let first_word = &a[0..2];//'hi ' -> 3 바이트
    let second_word = &a[3..7];'🦀' -> 4바이트
    // let half_crab = &a[3..5]; 실패
    // Rust는 유효하지 않은 유니코드 문자열의 slice를 허용하지 않습니다
    println!("{} {}", first_word, second_word);
}

&str의 흔히 사용되는 메소드는 다음과 같다.

  • len은 문자열의 바이트 길이(글자수가 아닌)를 가져온다.
  • starts_with/ends_with는 기본적인 비교에 사용
  • is_empty는 길이가 0일 경우 true를 리턴
  • find는 주어진 텍스트가 처음 등장하는 위치인 Option 값을 리턴

Rust 문자열 인덱싱

다른 언어에서는 정말 쉬운 문자열 인덱싱이 Rust에서는 굉장히 까다롭다.
문자열 인덱싱이 까다로운 이유는 고정된 문자 크기를 가지는 아스키가 아닌 가변적 문자 길이를 가지고 있는 UTF-8 이기 때문이다.

개발시 문자열 인덱싱은 가급적이면 사용하지 않는 편이 좋을 것이다.
그러나 문자열 인덱싱이 필요한 상황이라면 Vec<char>로 변환 해서 사용

fn main() {
    // 문자들을 char의 vector로 가져옵니다
    let chars = "hi 🦀".chars().collect::<Vec<char>>();

    println!("{}", chars.len()); // 4여야 합니다

    // char가 4 바이트이므로 u32로 변환할 수 있습니다
    println!("{}", chars[3] as u32);
}

함수의 매개변수로서의 텍스트

문자열과 string은 일반적으로 함수에 문자열 slice 형태로 전달된다.
이 방법은 소유권을 넘길 필요가 없어 대부분의 경우에 유연성을 제공한다.

fn say_it_loud(msg: &str) {
    println!("{}!!!", msg.to_string().to_uppercase());
}

fn main() {
    // say_it_loud는 &'static str을 &str로 대여
    say_it_loud("hello");
    // say_it_loud는 또한 String을 &str로 대여
    say_it_loud(&String::from("goodbye"));
}
profile
mohadang

0개의 댓글