Menu
Coddy logo textTech

タスクの完了

CoddyのGOジャーニー「論理とフロー」セクションの一部 — レッスン 23/68。

challenge icon

チャレンジ

簡単

タスク管理システムのこのパートでは、タスクを完了としてマークする機能を実装します。このチャレンジでは、ポインタレシーバを使用して元のタスクデータを変更することに焦点を当て、ポインタによって構造体のフィールドを永続的に更新する方法を学びます。

重要な注意点: タスク名にはスペースが含まれる可能性があるため(例:「Buy groceries」)、入力行全体を読み取るために bufio.Scanner を使用する必要があります。fmt.Scanf 関数は最初のスペースで読み取りを停止するため、スペースを含むタスク名が正しく読み取れません。bufio.NewScanner(os.Stdin) を使用し、scanner.Scan() に続いて scanner.Text() を呼び出すことで、完全な行を読み取ってください。

3つの入力を受け取ります:

  • タスクの数を示す文字列(例:"4"
  • タスクデータを含む文字列。形式は "name1:status1,name2:status2,name3:status3" で、ステータスは "true" または "false" です(例:"Buy groceries:false,Call dentist:true,Finish project:false,Review code:false"
  • 完了させるタスクのインデックスを示す文字列(例:3番目のタスクの場合は "2"、0ベースのインデックスを使用)

あなたのタスクは以下の通りです:

  1. 以前のチャレンジと同じ、Name (string) と Completed (bool) フィールドを持つ Task 構造体を定義します
  2. Task 構造体のスライスへのポインタとインデックス (int) をパラメータとして受け取る completeTask という関数を作成します
  3. completeTask 関数内で、指定されたインデックスにあるタスクの Completed フィールドを true に変更します
  4. bufio.Scanner を使用して入力行を適切に読み取ります:
    • スキャナーを作成します:scanner := bufio.NewScanner(os.Stdin)
    • 各入力行に対して:scanner.Scan() を呼び出し、次に scanner.Text() を呼び出します
    • これにより、スペースを含むタスク名が正しく読み取られるようになります
  5. 2番目の入力からタスクデータを解析して、タスクのスライスを作成します:
    • 入力をカンマで分割して、個々のタスクエントリを取得します
    • 各エントリをコロンで分割して、名前とステータスを分離します
    • ステータス文字列をブール値に変換します("true"true に、"false"false になります)
  6. 3番目の入力文字列を整数に変換して、タスクのインデックスを取得します
  7. スライスへのポインタとインデックスを指定して completeTask 関数を呼び出します
  8. タスクを完了させた後、前のチャレンジと同じ形式ですべてのタスクを表示します:
    • 完了したタスクの場合:"[x] [task_name]"
    • 未完了のタスクの場合:"[ ] [task_name]"
  9. 確認メッセージを出力します:"Task '[task_name]' marked as completed!"
  10. 更新されたサマリーを出力します:"Total: [total_count] tasks ([completed_count] completed, [incomplete_count] remaining)"

インデックス文字列を整数に変換するには strconv パッケージを使用してください。このチャレンジは、ポインタレシーバによって元のデータ構造を変更し、関数が終了した後もタスクリストへの永続的な変更を維持する方法を示しています。

自分で試してみよう

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

type Task struct {
	Name      string
	Completed bool
}

func viewAllTasks(tasks []Task) {
	for _, task := range tasks {
		if task.Completed {
			fmt.Printf("[x] %s\n", task.Name)
		} else {
			fmt.Printf("[ ] %s\n", task.Name)
		}
	}
}

func main() {
	var numTasksStr string
	fmt.Scanln(&numTasksStr)
	numTasks, _ := strconv.Atoi(numTasksStr)

	scanner := bufio.NewScanner(os.Stdin)
	scanner.Scan()
	taskData := scanner.Text()

	var tasks []Task
	taskEntries := strings.Split(taskData, ",")

	for _, entry := range taskEntries {
		parts := strings.Split(entry, ":")
		if len(parts) >= 2 {
			name := parts[0]
			completed, _ := strconv.ParseBool(parts[1])
			task := Task{
				Name:      name,
				Completed: completed,
			}
			tasks = append(tasks, task)
		}
	}

	viewAllTasks(tasks)

	completedCount := 0
	for _, task := range tasks {
		if task.Completed {
			completedCount++
		}
	}

	incompleteCount := numTasks - completedCount
	fmt.Printf("Total: %d tasks (%d completed, %d remaining)\n", numTasks, completedCount, incompleteCount)
}

論理とフローのすべてのレッスン