2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Rustを極めたい - 3

Posted at

前回の記事
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では01などを条件式に用いることはできません。
下記のような記述をした場合はコンパイルエラーとなります。

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が代入されます。expfalseの場合は、0が代入されます。

ifletで用いる場合、すべての分岐で同じ型を戻り値として返す必要があります。

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より大きくなったらbreakloop処理を抜けます。

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時に使用していたifbreak、ラベル等が不要になり、よりすっきりした繰り返し処理を書くことが出来ます。

また、下記のようにすることでコレクションの中身を取り出し処理することが出来ます。

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(構造体)について書いていこうと思います。

参考

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?