ジェネリックスタック
CoddyのRustジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 59/61。
チャレンジ
簡単stackは、「後入れ先出し」(LIFO)の原則に従う基本的なデータ構造です。最後に追加されたitemが最初に削除されます。皿のstackを思い浮かべてください。皿は上に追加し、上から削除します。
任意の型のelementを保持できるgenericなStackデータ構造を作りましょう。stackは、本のstackのように、上からのみ追加または削除できる「後入れ先出し」の原則に従います。
コードを2つのファイルに分けて整理します。
stack.rs:Vec<T>をinternally使用してelementを格納するgenericなStack<T>structをDefineします。3つのmethodsをImplementします。空のstackをCreateするnew、topにelementを追加するpush、そしてtopのelementを削除してreturnsするpopです(stackがemptyの場合があるため、Option<T>をreturnsします)。main.rs:stack moduleを取り込み、Stackがintegersで動作することを示します。stackをCreateし、指定されたnumbersをそのstack ontoにpushしてから、elementをpopしてそれぞれをprintします。popが返すOptionをhandleするためにunwrap_orをusesします。stackがemptyの場合は、default valueとして-1をusesします。
stackには2つのessentialな操作が必要です。
- push:stackのtopにelementを追加する
- pop:topのelementを削除してreturnsする
pop methodは、stackがemptyの場合があるため、Option<T>をreturnsする必要があります。Vec typeにはすでにOption<T>をreturnsするpop methodがあるため、Implementでそれを活用できます。
stackは次のように動作する必要があります。values 10、20、30を(そのorderで)pushした場合、3回popすると30、20、10(逆order)が得られます。emptyなstackに対する4回目のpopは、default valueをreturnsする必要があります。
popした各valueをそれぞれ独自のlineにprintします。
30
20
10
-1たとえば、inputsが5、15、25の場合:
25
15
5
-1stackにpushする3つのinputs、つまり3つのintegersを受け取ります(それぞれをi32としてparseします)。3つすべてをpushした後、成功するpopとemptyなstackのcaseの両方を示すために4回popします。
自分で試してみよう
mod stack;
use stack::Stack;
fn main() {
// 入力から3つの整数を読み取る
let mut input1 = String::new();
std::io::stdin().read_line(&mut input1).expect("Failed to read line");
let num1: i32 = input1.trim().parse().expect("Invalid number");
let mut input2 = String::new();
std::io::stdin().read_line(&mut input2).expect("Failed to read line");
let num2: i32 = input2.trim().parse().expect("Invalid number");
let mut input3 = String::new();
std::io::stdin().read_line(&mut input3).expect("Failed to read line");
let num3: i32 = input3.trim().parse().expect("Invalid number");
// TODO: 新しい Stack を作成する
// TODO: 3つの数値をスタックにプッシュする(num1, num2, num3 の順)
// TODO: 4回ポップして各結果を出力する
// 空のスタックの場合を処理するために unwrap_or(-1) を使用する
}
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Rustオンラインコンパイラ