第10章: 実践: 小さなRustプロジェクト

プロジェクト概要

このプロジェクトでは、ユーザーの入力を受け取り、それに基づいてタスクを管理するシンプルな「To-Doリスト」を構築します。このTo-Doリストは、ユーザーがタスクを追加、一覧表示、削除できる機能を備えた、簡単なコマンドラインアプリケーションです。Rustの基本的なデータ構造や関数、エラーハンドリングなどを効果的に使うことで、実際に役立つプログラムを作成します。


10.1 設計とプロジェクトの準備

10.1.1 必要な機能の洗い出し

To-Doリストアプリケーションに必要な機能は次のとおりです。

  1. タスクの追加: ユーザーが新しいタスクを入力し、リストに追加できる。
  2. タスクの表示: すべてのタスクを一覧表示できる。
  3. タスクの削除: 指定したタスクをリストから削除できる。
  4. アプリケーションの終了: ユーザーがプログラムを終了できる。

10.1.2 プロジェクトの設定

  1. Cargoプロジェクトの作成: 新しいプロジェクトフォルダを作成し、Cargoで初期化します。
    cargo new todo_list cd todo_list
  2. src/main.rs: メインのコードはこのファイルに記述していきます。

10.1.3 初期設定

このプログラムでは標準入力からのユーザーの指示を取得するためにstd::ioクレートを使用し、タスクの管理にはVec<String>を用います。以下がその初期コードです。

use std::io;

fn main() {
println!("To-Doリストアプリへようこそ!");
}

10.2 基本機能の実装

10.2.1 メインループの作成

アプリケーションはユーザーからの指示を待ち、入力に基づいて適切なアクションを実行します。これをメインループで実現します。

fn main() {
println!("To-Doリストアプリへようこそ!");
println!("コマンド: 'add', 'list', 'remove', 'exit' で操作してください。");

loop {
// ユーザー入力を受け取る
let mut input = String::new();
io::stdin().read_line(&mut input).expect("入力エラー");

// コマンドの処理
let command = input.trim();
match command {
"add" => add_task(),
"list" => list_tasks(),
"remove" => remove_task(),
"exit" => {
println!("アプリケーションを終了します。");
break;
}
_ => println!("無効なコマンドです。再入力してください。"),
}
}
}

ここで、loop文によりユーザー入力を待ち続け、適切なコマンドが入力されると対応する関数が実行されます。

10.2.2 タスクを格納するデータ構造

タスクを格納するためにVec<String>型の変数を使います。タスクをmain関数の中で管理するため、mainのスコープに持たせることにします。

let mut tasks: Vec<String> = Vec::new();

10.3 タスク追加機能の実装

ユーザーからタスク内容を入力してもらい、それをtasksリストに追加するadd_task関数を実装します。

fn add_task(tasks: &mut Vec<String>) {
println!("追加するタスクを入力してください:");
let mut task = String::new();
io::stdin().read_line(&mut task).expect("入力エラー");

tasks.push(task.trim().to_string());
println!("タスクが追加されました。");
}

ポイント

  • &mut Vec<String>という参照で受け取ることで、リストに新しいタスクを追加可能にしています。
  • trim()で余分な空白を取り除き、無駄なスペースを省きます。

10.4 タスク一覧表示機能の実装

次に、すべてのタスクを表示する関数list_tasksを作成します。

fn list_tasks(tasks: &Vec<String>) {
if tasks.is_empty() {
println!("タスクはありません。");
} else {
println!("現在のタスク:");
for (i, task) in tasks.iter().enumerate() {
println!("{}: {}", i + 1, task);
}
}
}

ポイント

  • iter().enumerate()を使用し、インデックス番号とタスク内容を同時に表示。
  • is_empty()を使ってタスクがない場合のエラーメッセージも出力しています。

10.5 タスク削除機能の実装

特定のタスクをリストから削除するremove_task関数を追加します。

fn remove_task(tasks: &mut Vec<String>) {
println!("削除するタスクの番号を入力してください:");
let mut index_str = String::new();
io::stdin().read_line(&mut index_str).expect("入力エラー");

match index_str.trim().parse::<usize>() {
Ok(index) if index > 0 && index <= tasks.len() => {
tasks.remove(index - 1);
println!("タスクが削除されました。");
}
_ => println!("無効な番号です。"),
}
}

ポイント

  • parse::<usize>()を使って、入力文字列を数値に変換。
  • 無効なインデックスの処理もmatch式で対応。

10.6 コードの改善とデバッグのポイント

  1. 冗長なコードの整理
    • コマンドの受付と処理をmain関数で一つにまとめるのではなく、サブ関数で分離することでコードが読みやすくなり、拡張しやすくなります。
  2. ユーザー入力のバリデーション
    • 各関数でユーザー入力を必ず検証し、エラーメッセージを出力します。これによりユーザーエラーを未然に防ぎます。
  3. エラーハンドリングの追加
    • 入力に問題があった場合の処理も行い、ユーザーが操作を継続しやすいようにしました。

10.7 完成コード

最終的な完成コードは以下の通りです。

use std::io;

fn main() {
println!("To-Doリストアプリへようこそ!");
println!("コマンド: 'add', 'list', 'remove', 'exit' で操作してください。");

let mut tasks: Vec<String> = Vec::new();

loop {
let mut input = String::new();
io::stdin().read_line(&mut input).expect("入力エラー");

match input.trim() {
"add" => add_task(&mut tasks),
"list" => list_tasks(&tasks),
"remove" => remove_task(&mut tasks),
"exit" => {
println!("アプリケーションを終了します。");
break;
}
_ => println!("無効なコマンドです。再入力してください。"),
}
}
}

fn add_task(tasks: &mut Vec<String>) {
println!("追加するタスクを入力してください:");
let mut task = String::new();
io::stdin().read_line(&mut task).expect("入力エラー");

tasks.push(task.trim().to_string());
println!("タスクが追加されました。");
}

fn list_tasks(tasks: &Vec<String>) {
if tasks.is_empty() {
println!("タスクはありません。");
} else {
println!("現在のタスク:");
for (i, task) in tasks.iter().enumerate() {
println!("{}: {}", i + 1, task);
}
}
}

fn remove_task(tasks: &mut Vec<String>) {
println!("削除するタスクの番号を入力してください:");
let mut index_str = String::new();
io::stdin().read_line(&mut index_str).expect("入力エラー");

match index_str.trim().parse::<usize>() {
Ok(index) if index > 0 && index <= tasks.len() => {
tasks.remove(index - 1);
println!("タスクが削除されました。");
}
_ => println!("無効な番号です。"),
}
}

この章では、Rustの基本的な構文を活用した実用的なアプリケーションの構築方法と、ユーザー入力やエラーハンドリングの実装、そしてコードの改善ポイントを学びました。この経験により、実践的なRustのスキルがさらに身についたことでしょう。


初心者におすすめ!プログラミングスクールのススメ

未経験でも気軽に!サブスク型プログラミングスクール【Freeks】

プログラミングを始めたいと思っているそこのあなた、独学よりもプログラミングスクールが断然おすすめです!理由は簡単、続けやすさです。

独学の挫折率、驚きの87.5%!

独学でプログラミングを続けるのは、実はかなりハードルが高いんです。データによると、なんと87.5%もの学習者が途中で挫折しているとか。一方、各プログラミングスクールが公表しているデータによると、受講生の約95%が最後までやり抜いているとのこと。数字を見れば一目瞭然、プログラミングスクールの方が圧倒的に続けやすいんです。

有料と無料、スクールの違いは?

プログラミングスクールには有料と無料のタイプがありますが、その違いは次の通りです:

  • 受講条件が異なる
  • 学べるスキルやカリキュラム内容が異なる
  • 就職や転職のサポート内容が異なる

どちらが自分に合っているか、よく考えて選ぶのが大事です。

サブスク型プログラミングスクール『FREEKS(フリークス)』に注目!

プログラミング初心者でも学びやすいと評判の『FREEKS』、その特徴は以下の通り:

  • 未経験者向けのわかりやすいカリキュラム
  • 経験豊富なエンジニアのサポート
  • オンラインで自分のペースで学習可能

なんと、月会費のみで全カリキュラムが受け放題!Java、PHP、HTML/CSS、JavaScriptなど、多彩なプログラミング言語が学べるんです。しかも、AIが質問に自動で答えてくれるシステムも導入済み。

終了後は副業もサポート!

カリキュラムを終了した後には、Freeks経由で未経験者でも取り組める副業案件の受注が可能。実務を通じてスキルを磨き、市場価値の高いエンジニアへの道が開けます。

独学で悩むくらいなら、まずはプログラミングスクールをチェックしてみるのもアリかもしれませんよ!
 ↓ ↓ こちらをクリック ↓ ↓ 

p-school

Recent Posts

第6章: PHPのデータベース操作

PHPを使用してデータベースに…

2週間 ago

第5章: PHPのオブジェクト指向プログラミング(OOP)

オブジェクト指向プログラミング…

2週間 ago

第4章: PHPの関数

プログラミングにおいて、関数は…

2週間 ago

第3章: PHPの配列とコレクション

PHPでの配列とコレクションの…

2週間 ago

第2章: PHPの基本文法

PHPの基本的な構文や使い方を…

2週間 ago