Intro
rust의 흐름 제어(분기문, 반복문)에 대한 설명과 예제입니다. rust는 이 부분에서는 타 언어들과 거의 비슷합니다. 차이가 있다고 한다면 다음과 같은 부분이 있습니다.
- 무한루프 예제인 loop
- slice 표기법 (1..5, 1..=10)
- match(switch, case), if let
코드 예제를 통해 확인해 보겠습니다.
Code Example
Rust 1.79.0 (released 2024-06-13)
fn main(){
// =========================================
// Conditionals (분기문)
// =========================================
/* [Example] if, else : 가장 기초적인 분기문 */
let number = 5;
if number > 0 {
println!("Positive number");
} else if number == 0{
println!("Zero");
} else {
println!("Negative number");
}
/* [Example] match : (switch case같은 동작) */
// match에서 <pattern>에 속하는지를 검사함.
// pattern에 올 수 있는 값들은 아래와 같음
fn match_number(number:i32) {
match number {
1 => println!("One"), // literal
2..5 => println!("Two, Three, Four"), // Range type도 사용할 수 있다.
5..=10 => println!("5 ~ 10"), // Range Type을 끝 숫자를 포함시킬 수도 있다.
_ => println!("no match"), // Default
}
}
match_number(number);
// compound Type의 match 활용
let tuple = (2, 4);
fn match_tuple(tuple: (i32, i32)){
match tuple {
// 값을 빼서 가져올 수 있다.
(1, y) => println!("tuple. first value is 1, second value is {y}"),
(2, y) => println!("tuple. first value is 2, second value is {y}"),
(x, 10) => println!("tuple. first value is {x}, second value is 10"),
_ => println!("no match"),
}
}
match_tuple(tuple);
// Custom Type의 match 활용 (Option, Result같은 차후 나올 Type에서 자주 활용)
enum Animal {
Dog(String),
Cat(String),
Bird(String),
}
let dog = Animal::Dog(String::from("bull"));
let cat = Animal::Cat(String::from("kitty"));
let bird = Animal::Bird(String::from("eagle"));
fn match_animal(animal: Animal){
match animal {
Animal::Bird(name) => println!("A bird named {}", name),
Animal::Cat(name) => println!("A cat named {}", name),
Animal::Dog(name) => println!("A dog named {}", name),
}
}
match_animal(dog);
match_animal(cat);
match_animal(bird);
/* [Example] if let */
// if let은 match에서 한 가지 match case에 대해 다루고 싶을 때 사용
// if (let <pattern> => <target>) {match true condition} else {match false condition}
// literal 예제 (match와 비슷하다는 것을 보여주는 예제일뿐, 이렇게는 사실 잘 사용 안함)
let number = 10;
if let 1..=10 = number { // number가 1..=10에 match되는가?
println!("number is in 1 ~ 10");
} else if let 11..=20 = number { // number가 11..=20에 match되는가?
println!("number is in 11 ~ 20");
} else {
println!("number is not in 1 ~ 20");
}
// enum을 활용한 if let example
// 차후에 Option Type 처리, Result Type을 활용한 Error handling에서 많이 사용된다.
#[allow(warnings)]
enum Status{
Success(String),
Fail(String),
}
let success_status = Status::Success(String::from("get message success"));
let fail_status = Status::Fail(String::from("get message failed"));
fn get_fail_status_message(status:Status){
if let Status::Fail(message) = status {
println!("status : success. message : {message}");
} // fail message인 경우 message 출력 함수
}
get_fail_status_message(success_status); // 아무 메세지를 출력하지 않음
get_fail_status_message(fail_status); // fail message 출력
// =========================================
// Loops (반복문)
// =========================================
/* for : 전통적인 방식 */
for i in 0..4{
println!("i : {i}"); // 0, 1, 2, 3
}
for i in 0..=4{ // 끝자리수를 포함하고 싶을 때
println!("i : {i}"); // 0, 1, 2, 3, 4
}
// array
let arr = [1, 2, 3, 4, 5];
// 배열 같은 type은 iter() method를 활용해 각 원소의 주소값을 받아올 수 있다.
for &item in arr.iter(){ // &item으로 선언해서 item을 값으로 받을 수 있다.
println!("arr item : {item}");
}
// ref를 사용하지 않는다면 어떻게 될까?
// println!은 &i32, i32를 둘 다 값으로 출력할 수 있다. 그래서 error를 출력하지 않는다.
// 하지만 pointer에 대한 개념이 잘 잡혀있지 않다면 이런 습관은 문제가 될 수 있다.
// println!에 value를 출력할 수 있도록 type을 지켜주도록 습관을 들이자
for item in arr.iter(){ // for item in arr.iter()로 하면 &i32가 출력된다.
println!("arr *item : {}", *item);
println!("arr item : {}", item); // println!은 &i32, i32를 둘 다 값으로 출력할 수 있다.
}
// enumerate : item의 index를 tuple로 묶어서 출력 (0, 1, 2, 3...)
let v = vec![10, 20, 30, 40];
for (index, &item) in v.iter().enumerate(){
println!("vector item {index} : {item}");
}
// zip : 2개의 iterator를 묶어서 출력
// 서로의 길이가 차이난다면 짧은쪽에 맞춰져서 출력됨
for (&arr_item, &vec_item) in arr.iter().zip(v.iter()) {
println!("arr item : {arr_item}, vec item : {vec_item}"); // (1, 2, 3, 4), (10, 20, 30, 40)
}
// mutable
let mut v_mut = vec![1, 2, 3];
let mut a_mut = [4, 5, 6];
// mutable한 ref를 받아온다.
for (v_item_ref, a_item_ref) in v_mut.iter_mut().zip(a_mut.iter_mut()){
*a_item_ref *= 10; // a_item_ref의 값을 control할 수 있도록 deref(*)한 후 값을 변경
*v_item_ref += 10; // a_item_ref의 값을 control할 수 있도록 deref(*)한 후 값을 변경
}
println!("{v_mut:?}, {a_mut:?}"); // [11, 12, 13], [40, 50, 60]
/* while: 조건이 false가 될때까지 반복. continue나 break keyword도 활용할 수 있다. */
let mut counter = 0;
while counter < 5 { // 5미만일때는 반복
println!("while counter : {counter}");
counter += 1;
if counter <= 3 { // counter가 3 미만이면
continue; // 반복문 처음으로 되돌림. 밑의 counter를 돌지 않음
}
println!("counter is over 3");
}
/* loop: 무한 루프 (while true같은 개념) */
let mut counter = 0;
loop {
if counter > 5 {
break; // loop는 break만으로 빠져나올 수 있다.
}
println!("loop counter : {counter}");
counter += 1;
}
}
* reference
'Rust > Basic' 카테고리의 다른 글
[Rust Tutorial] 8 - Struct, Impl, Trait (0) | 2024.11.18 |
---|---|
[Rust Tutorial] 7 - Ownership (0) | 2024.11.17 |
[Rust Tutorial] 5 - Function (0) | 2024.11.17 |
[Rust Tutorial] 4 - Data Type (0) | 2024.11.14 |
[Rust Tutorial] 3 - Variables (0) | 2024.11.14 |