반응형

간단하게 정리해본 Rust 강좌입니다. 

다음 문서를 기반으로 작성했습니다.

 

Tour of Rust

https://tourofrust.com/00_ko.html 



2022. 9. 12  최초작성

2023. 3. 29  최종작성




Rust 개발 환경 만드는 방법은 아래 포스트를 참고하세요.

https://webnautes.tistory.com/2110



문자열

 

Rust에서 문자열은 유니코드이며 데이터 타입은 &'static str입니다.

 

&는 메모리 내의 장소를 참조하고 있다는 의미이며, mut가 없다는 것은 컴파일러가 문자열 값의 변경을 허용하지 않는다는 뜻입니다

'static은 string 데이터가 프로그램이 끝날 때까지 유효하다는 것이고  str은  utf-8인 바이트 열을 가리키고 있다는 의미입니다

 

Rust 컴파일러는 문자열을  데이터 세그먼트에 저장합니다. 



문자열을 출력하는 간단한 코드입니다.

fn main() {

    let a: &'static str = "hi 🦀";
   
    println!("{} {}", a, a.len());
}



hi와 빈칸이 3바이트이고 러스트 게 이모티콘이 4바이트라서 아래 실행결과에 7이 출력됩니다. 




utf-8

 

utf-8에선 하나의 문자가  1 ~ 4 사이의 바이트를 가집니다.  

 

더 많은 바이트를 사용가능해져서 사용가능한 문자가 많아진 대신 단순한 인덱싱(예: my_text[3]으로 네 번째 문자를 가져옴)으로  문자열에서 개별 문자를 지정할 수 없는 단점이 있습니다.  문자 하나가 1~4 사이의 바이트를 가지기 때문에  인덱싱으로 4번째 문자를 지정할수 없습니다. 

 

인덱스  대신에 utf-8 바이트 열을 하나씩 돌면서 각각의 유니코드 문자가 실제로 어디에서 시작하는지 찾아야 합니다.



이스케이프 코드(escape code)

시각적으로 표현하기 어려운 문자를 이스케이프 코드로 대체하여 씁니다.

 

 

전체 목록은 아래 링크에 있습니다.

 

https://doc.rust-lang.org/reference/tokens.html



fn main() {

    let a: &'static str = "Ferris가 말하길:\t\"안녕하세요\"\n반가워요";

    println!("{}", a);
}






여러 줄로 된 문자열

 

Rust의 문자열은 기본적으로 여러 줄로 되어 있습니다.

줄바꿈 문자를 원하지 않을 경우, 줄 맨 뒤에 \를 사용하세요.



fn main() {


    // 줄바꿈이 적용되어 출력됩니다.
    let haiku: &'static str = "
        나는 쓰고, 지우고, 다시 쓴다
        다시 지우고, 그러고 나면
        양귀비 꽃이 핀다.
        - 가쓰시카 호쿠사이";

    println!("{}", haiku);


    // \를 사용함으로써 줄바꿈이 무시되고 한 줄로 출력됩니다.
    println!(
        "hello \
    world"
    ) // w 앞의 공백이 무시 되었음을 주의하세요
}






원시 문자열

 

원시 문자열은 r#"로 시작하고 "#로 끝나며 문자열을 있는 그대로 출력해줍니다. 

 

fn main() {

    let a: &'static str = r#"
        <div class="advice">
            원시 문자열은 일부 상황에서 유용합니다.
        </div>
        "#;
   
    println!("{}", a);

}

 




텍스트 파일에서 문자열 가져오기

 

include_str!를 사용하여 텍스트 파일을 읽어서 문자열로 가져올 수 있습니다. 

 

fn main() {

    let text = include_str!("main.rs");

    println!("{}", text);
}

 




문자열 슬라이스

 

문자열 슬라이스(slice) 는 인덱스를 지정하여 문자열의 일부를 가져오는 것입니다. utf-8에선 하나의 문자가 4바이트인 경우  문자의 일부를 가져올 수는 없습니다. 

문자열 슬라이스의 문자열 타입은 &str이며 여러가지 메서드를 제공합니다. 

 

슬라이스

 

슬라이스는 인덱스를 사용하여 문자열의 일부를 가져오는 것입니다. 

문자열 슬라이스를 위해 변수에 인덱스를 지정시 변수 이름 앞에 &를 붙여줘야 합니다. 

 

fn main() {

    let a = "hi 🦀";

    println!("문자열의 길이 {}", a.len()); // 문자열의 글자수가 아닌 바이트 길이입니다. 러스트 게 그림문자는 4바이트입니다.

    let first_word = &a[0..2]; // 문자열의 인덱스는 0부터 시작, 0..2는 시작 인덱스 0부터이며 끝 인덱스 2를 포함하지 않습니다.
    let second_word = &a[3..7]; // 3..7는 시작인덱스 3부터이며 끝 인덱스 7은 포함하지 않음, 러스트 게 그림문자는 4 바이트입니다.

    println!("첫번째 단어 [{}] ,  두번째 단어 [{}]", first_word, second_word);
}





러스트 게 그림문자의 절반을 슬라이스 하려고하면  에러가 발생합니다.  러스트 문자의 절반만 가져오는 것은 허용되지 않기 때문입니다.

 

fn main() {

    let a = "hi 🦀";

    let half_crab = &a[3..5];

    println!("러스트 문자 반쪽 [{}]", half_crab);
}





find

 

find 메서드는 지정한 문자열이 발견된 인덱스를 Option<usize>로 리턴합니다. 

 

fn main() {

    let a = "12345678901234567890";

    println!("{:?}", a.find("789")); // 문자열 "789"가 처음 발견된 인덱스를 Option<usize>로 리턴합니다.

    println!("{:?}", a.find("111")); // 문자열 "111"을 발견할 수 없어서 None를 리턴합니다.

}






is_empty

 

is_empty 메서드는 문자열의 길이가 0인 경우 true를 리턴합니다. 



fn main() {

    let a = "";

    println!("{:?}", a.is_empty());
}





starts_with / ends_with

 

starts_with 메서드는 문자열의 앞에 지정한 문자열이 포함되어 있으면 true를 리턴합니다.

ends_with 메서드는 문자열의 끝에 지정한 문자열이 포함되어 있으면  true를 리턴합니다.

 

fn main() {

    let a = "abcdefg";

    println!("{:?}", a.starts_with("abc")); // 문자열의 앞에 "abc"가 포함되어 있으면 ture를 리턴합니다.
    println!("{:?}", a.ends_with("fg")); // 문자열의 끝에 "fg"가 포함되어 있으면 ture를 리턴합니다.
}






문자

 

유니코드를 다루는 것이 어렵다보니, Rust에서는 utf-8 바이트 열을 char 자료형의 vector로 돌려주는 기능을 제공합니다.



use std::mem;


fn main() {

    let text = "hi 🦀~";

    // 문자열에서 문자들을 char의 vector로 가져옵니다
    let chars = text.chars().collect::<Vec<char>>();

    println!("{:?}", chars); // 문자별로 분리된 것을 볼 수 있습니다.
    println!("{}", chars.len()); // 벡터에 저장된 문자의 개수는 5개입니다.

    // 각 문자의 크기가 4바이트인 것을 볼 수 있습니다.
    println!("{} {} {} {} {}", mem::size_of_val(&chars[0]), mem::size_of_val(&chars[1]), mem::size_of_val(&chars[2]), mem::size_of_val(&chars[3]), mem::size_of_val(&chars[4]));

    // 문자열에서 슬라이스로 가져온 문자 하나의 크기는 1바이트입니다.
    println!("{} {}", &text[0..1], mem::size_of_val(&text[0..1]));

}






스트링

 

String은 utf-8 바이트 열을 heap memory에 소유하는 struct입니다.

String의 메모리는 heap에 있기 때문에, 문자열과는 달리 늘리거나 변경하는 등을 할 수 있습니다.



fn main() {

    let mut text = String::from("hello");
    println!("{}", text);
   
    // 문자열을 결합합니다.
    text.push_str(" world");
    println!("{}", text);

    // 문자열을 결합합니다.
    text = text + "!";
    println!("{}", text);

    //부분 문자열을 교체합니다.
    text = text.replace("world", "universe");
    println!("{}", text);

    // 대문자로 변환합니다.
    text = text.to_uppercase();
    println!("{}", text);

    // 소문자로 변환합니다.
    text = text.to_lowercase();
    println!("{}", text);

    // 문자열의 공백을 제거합니다.
    let mut text = String::from(" momo   ");
    println!("{}", text);
    text = text.trim().to_string();
    println!("{}", text);
}

 




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

 

문자열과 string은 일반적으로 함수에 문자열 슬라이스 형태로 전달됩니다. 이 방법을 사용하면 소유권을 넘길 필요가 없습니다. 

 

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

fn main() {

    // 문자열 &'static str을 &str로 넘겨줄 수 있습니다.
    let s : &'static str = "hello";
    say_it_loud(s);
   
    // 문자열 String을 &str로 넘겨줄 수  있습니다.
    let s = String::from("goodbye");
    say_it_loud(&s);
}

 




문자열 합치기

 

문자열을 합치기 위해 concat과 join을 사용할 수 있습니다. 



fn main() {

    let helloworld = ["hello", " ", "world", "!"].concat();

    //문자열을 결합시 사이에 넣을 문자로 콤마를 지정합니다.
    let abc = ["a", "b", "c"].join(",");

    println!("{}", helloworld);
    println!("{}",abc);

}

 




문자열 양식 만들기

 

format! 매크로를 사용하면 문자열을 삽입할 위치를 지정할 수 있습니다. 

 

fn main() {
    let a = 42;
    let f = format!("삶, 우주, 그리고 모든 것에 대한 해답: {}", a);
   
    println!("{}", f);
}






문자열 변환

 

대부분의 데이터 타입에 to_string을 사용하면 문자열로 변환이 가능합니다. 



fn main() {
   
    let a = 42;

    let a_string = a.to_string();
   
    println!("{}", a);
}

 



간단하게 정리해본 Rust 강좌 1 : 변수, 상수, 함수, 튜플, 배열, 데이터타입, println

https://webnautes.tistory.com/2194

 

간단하게 정리해본 Rust 강좌 2 : if-else, loop, while, for, match, struct, method

https://webnautes.tistory.com/2195

 

간단하게 정리해본 Rust 강좌 3 : 열거형, 제네릭 데이터 타입, Option, Result, unwrap, vector

https://webnautes.tistory.com/2196

 

간단하게 정리해본 Rust 강좌 4 : 소유권, 참조, 역참조, 생명주기

https://webnautes.tistory.com/2197

 

간단하게 정리해본 Rust 강좌 5 : 문자열, utf-8

https://webnautes.tistory.com/2198

 

간단하게 정리해본 Rust 강좌 6 : 모듈

https://webnautes.tistory.com/2199

 

간단하게 정리해본 Rust 강좌 7 : &self, &mut self, trait, 동적 디스패치, 정적 디스패치, Generic 메서드, Box

https://webnautes.tistory.com/2200

 

간단하게 정리해본 Rust 강좌 8 : 참조자, 댕글링 참조, 원시 포인터

https://webnautes.tistory.com/2203

 

간단하게 정리해본 Rust 강좌 9 : Box, 재귀적 데이터타입, Deref 트레잇

https://webnautes.tistory.com/2202



반응형

문제 발생시 지나치지 마시고 댓글 남겨주시면 가능한 빨리 답장드립니다.

도움이 되셨다면 토스아이디로 후원해주세요.
https://toss.me/momo2024


제가 쓴 책도 한번 검토해보세요 ^^

+ Recent posts