assert!
マクロ
アサートは,プログラムの異常に気付きやすいようにするための手段です.次のコードを見てください.
use proconio::input;
fn main() {
input! {
x: i32,
}
let r = x % 10;
assert!(0 <= r && r < 10);
println!("あまりは {}", r);
}
input!
マクロで整数 assert!
マクロです.
assert!( )
の括弧内に条件を書き, assert!(0 <= r && r < 10);
とします.
- ここでもし
0 <= r && r < 10
が成り立っていれば,何事もなかったかのようにプログラムの続きが実行されます. - 一方,もし
0 <= r && r < 10
が成り立っていなければ,プログラムはこの時点で実行時エラーとなり,続きは実行されません(panic!
マクロと同じ).
まず,このプログラムに標準入力として 123
を与えて実行してみましょう. あまりは 3
と出力され,ちゃんと assert!
の続きが実行されていることが分かります.
次に,標準入力を -123
に変えてみましょう.おや?標準出力に何も出力されません(println!
が実行されていません).代わりに標準エラー出力に
thread 'main' panicked at 'assertion failed: 0 <= r && r < 10', src/main.rs:8:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
と出力され,終了コードが 0 以外の値になっています.これが, assert!
で括弧内の条件が成り立っていなかったときの挙動です.
つまり,このプログラムでは
実は,/
/ %
演算子を使うときは,負の場合の挙動に注意する必要があります. x
と y
の正負を変えながら x / y
と x % y
を計算すると次のようになります.
x |
y |
x / y |
x % y |
---|---|---|---|
これを避け, x.div_euclid(y)
/ x.rem_euclid(y)
と書きます.
use proconio::input;
fn main() {
input! {
x: i32,
}
let r = x.rem_euclid(10);
assert!(0 <= r && r < 10);
println!("あまりは {}", r);
}
x |
y |
x.div_euclid(y) |
x.rem_euclid(y) |
---|---|---|---|
今回は println!
で余りを出力するだけでしたが,もしこの前後に膨大な処理が書かれていた場合,どこに異常があるのか特定するのが困難になります.アサートを使うことで,どこで異常が発生しているのか気付きやすくなります.
メッセージ
assert!(0 <= r && r < 10);
の代わりに
assert!(0 <= r && r < 10, "割った余りが想定の範囲を超えています");
と書くと,失敗したときの文面を
thread 'main' panicked at '割った余りが想定の範囲を超えています', src/main.rs:8:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
のように変えられます. println!
マクロと同じように
assert!(0 <= r && r < 10, "割った余りが {} で,想定の範囲を超えています", r);
と書くこともできます.
assert_eq!
/ assert_ne!
マクロ
assert!
マクロの中で ==
を使って assert!(a == b)
のように書くときは,代わりに assert_eq!
マクロを使って assert_eq!(a, b)
と書くこともできます.
use proconio::input;
fn main() {
input! {
x: i32,
y: i32
}
let rounded = x / y * y;
assert_eq!(rounded % y, 0); // rounded % y == 0 をチェック
}
同様に, assert!(a != b)
の代わりに assert_ne!(a, b)
と書くことができます.
assert_eq!
/ assert_ne!
の場合も, assert_eq!(a, b, "メッセージ");
のようにして失敗時のメッセージを追加することができます.