前回の記事
https://qiita.com/on_c98/items/f6541d6d793ad2a0b75d
Rustの制御フロー
条件分岐
if
Rustではif
を用いて条件分岐を行うことが出来ます。
fn main() {
let num = 5;
if num > 3 {
println!("bigger than 3");
} else {
println!("smaller than 3");
}
}
条件式に()
は不要です。条件式には結果がbool
値のみ指定可能で、C/C++等と違い、Rustでは0
や1
などを条件式に用いることはできません。
下記のような記述をした場合はコンパイルエラーとなります。
fn main() {
let integer = 1;
if integer {
println!("true?")
} else {
println!("false?");
}
}
$ cargo run
Compiling sample v0.1.0 (C:\path\to\sample)
error[E0308]: mismatched types
--> src\main.rs:2:8
|
2 | if integer {
| ^^^^^^^ expected `bool`, found integer
For more information about this error, try `rustc --explain E0308`.
error: could not compile `sample` due to previous error
else if
を用いることで、複数の分岐を扱うことが出来ます。
fn main() {
let count = 1;
if count == 1 {
println!("one");
} else if count == 2 {
println!("two");
} else {
println!("{}", count);
}
}
if
は式
なので、let
で使用することが出来ます。
fn main() {
let exp = true;
let result = if exp { 1 } else { 0 };
}
上記の例では、result
には値1
が代入されます。exp
がfalse
の場合は、0
が代入されます。
if
をlet
で用いる場合、すべての分岐で同じ型を戻り値として返す必要があります。
fn main() {
let exp = false;
let result = if exp { 1 } else { "false" };
}
上記では、true
の場合はi32
を、false
の場合は&str
を返しているため、コンパイルエラーになります。
それぞれのブロック({}
)には文
を記述することも可能です。
fn main() {
let num = 10;
let result = if num % 15 == 0 {
println!("3と5の倍数です。");
num / 15
} else if num % 5 == 0 {
println!("5の倍数です。");
num / 5
} else if num % 3 == 0 {
println!("3の倍数です。");
num / 3
} else {
println!("{}", num);
num
};
println!("{}", result);
}
繰り返し
loop
Rustでは、loop
を用いて繰り返し処理をすることが出来ます。
fn main() {
loop {
println!("loop!");
}
}
loop
では条件式などは受け取らず、無限ループになります。loop
から抜け出すには、break
キーワードを用います。
fn main() {
let mut count = 0;
loop {
println!("count: {}", count);
if count > 10 {
break;
}
count += 1;
}
}
上記例では、count
に1を足していき、10より大きくなったらbreak
でloop
処理を抜けます。
break
には戻り値を渡すことが出来ます。
fn main() {
let mut x = 0;
let z = 5;
let y = loop {
x += 1;
if x == z {
break x * z;
}
}
println!("y is {}", y);
}
上記例では、繰り返しのたびにx
の値がインクリメントされていき、z
の値と同等になった時点で、x * z
の値がyに代入されloop
処理を抜けます。
ネストされたloop
で外側のloop
から抜けたい場合、ラベルを用います。
fn main() {
let mut x = 0;
'outer_loop: loop {
let mut y = 0;
loop {
if y == 10 {
break;
}
if x == 2 {
break 'outer_loop; //ラベルが付与されている外側のloopから抜ける
}
y += 2;
println!("x: {}, y: {}", x, y);
}
x += 1;
}
}
上記を実行した場合、下記のように出力されます。
❯ cargo run
Compiling sample v0.1.0 (C:\path\to\sample)
Running `target\debug\sample.exe`
x: 0, y: 2
x: 0, y: 4
x: 0, y: 6
x: 0, y: 8
x: 0, y: 10
x: 1, y: 2
x: 1, y: 4
x: 1, y: 6
x: 1, y: 8
x: 1, y: 10
ネストされた内側のloop
内でbreak
を2か所使用していますが、y == 10
の時に実行されるbreak;
ではラベルが指定されていないため、内側のloop
からのみ抜けて、外側のloopは続行されます。x == 3
の時に実行されるbreak 'outer_loop;
では、ラベル'outer_loop
が指定されているため外側のループから抜けて処理が終了します。
while
Rustでは、while
を用いて条件付きの繰り返し処理を行うことが出来ます。上記のloop
で作成したプログラムをwhile
で記述する場合、下記のようになります。
fn main() {
let mut x = 0;
while x < 2 {
let mut y = 0;
while y < 10 {
y += 2;
println!("x: {}, y: {}", x, y);
}
x += 1;
}
}
loop
時に使用していたif
やbreak
、ラベル等が不要になり、よりすっきりした繰り返し処理を書くことが出来ます。
また、下記のようにすることでコレクションの中身を取り出し処理することが出来ます。
fn main() {
let arr = [1, 2, 3, 4, 5];
let mut index = 0;
while index < 5 {
println!("{}", arr[index]);
index += 1;
}
}
ただし、while
でインデックスを使用したコレクションへのアクセスは、コレクションのサイズが変更された場合などに範囲外のインデックスへのアクセスが発生してしまい、プログラムがパニックを起こしてしまうため、あまり推奨されていません。
代わりにfor
を使用して安全にコレクションを処理することが出来ます。
for
Rustのfor
では、配列などのコレクションから一つずつ要素を取り出しながら繰り返し処理をします。
fn main() {
let a = [1, 2, 3, 4, 5];
for value in a {
println!("{}", value);
}
}
上記の例では、配列a
から一つずつ要素を取り出し、変数value
として処理しています。要素数を気にすることなく、安全にコレクションを処理することが出来ます。
また、下記のように書くことで決まった回数をループさせることも可能です。
fn main() {
for i in 0..10 {
println!("{}", i);
}
}
0..10
は、0から9までのRange
を表しており、10回ループさせることが出来ます。
0..=10
と書くことで、0から10までのRange
を表現することも可能です。
終わりに
次回はstruct
(構造体)について書いていこうと思います。
参考