간단하게 정리해본 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
'Rust > Rust 강좌' 카테고리의 다른 글
간단하게 정리해본 Rust 강좌 7 : &self, &mut self, trait, 동적 디스패치, 정적 디스패치, Generic 메서드, Box (0) | 2023.10.28 |
---|---|
간단하게 정리해본 Rust 강좌 6 : 모듈 (0) | 2023.10.28 |
간단하게 정리해본 Rust 강좌 4 : 소유권, 참조, 역참조, 생명주기 (0) | 2023.10.28 |
간단하게 정리해본 Rust 강좌 3 : 열거형, 제네릭 데이터 타입, Option, Result, unwrap, vector (0) | 2023.10.28 |
간단하게 정리해본 Rust 강좌 2 : if-else, loop, while, for, match, struct, method (2) | 2023.10.28 |
시간날때마다 틈틈이 이것저것 해보며 블로그에 글을 남깁니다.
블로그의 문서는 종종 최신 버전으로 업데이트됩니다.
여유 시간이 날때 진행하는 거라 언제 진행될지는 알 수 없습니다.
영화,책, 생각등을 올리는 블로그도 운영하고 있습니다.
https://freewriting2024.tistory.com
제가 쓴 책도 한번 검토해보세요 ^^
그렇게 천천히 걸으면서도 그렇게 빨리 앞으로 나갈 수 있다는 건.
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!