完成任务
本课属于 Coddy GO 学习旅程的“逻辑与流程”单元。第 23 课,共 68 课。
挑战
简单在任务管理系统的这一部分,你将实现将任务标记为已完成的功能。本次挑战重点是使用指针接收者修改原始任务数据,展示指针如何让你永久更新结构体字段。
重要提示:由于任务名称可能包含空格(例如 "Buy groceries"),你需要使用 bufio.Scanner 读取完整的输入行。fmt.Scanf 函数会在第一个空格处停止读取,这会导致包含空格的任务名称无法正确读取。请使用 bufio.NewScanner(os.Stdin),并依次调用 scanner.Scan() 和 scanner.Text() 来读取完整的行。
你会收到 3 个输入:
- 一个表示任务数量的字符串(例如
"4") - 一个包含任务数据的字符串,格式为:
"name1:status1,name2:status2,name3:status3",其中 status 的值为"true"或"false"(例如"Buy groceries:false,Call dentist:true,Finish project:false,Review code:false") - 一个表示要完成的任务索引的字符串(例如,使用从 0 开始的索引时,
"2"表示第 3 个任务)
你的任务是:
- 定义与之前的挑战相同的
Task结构体,包含Name(string)和Completed(bool)字段 - 创建一个名为
completeTask的函数,它接受一个指向Task结构体切片的指针,以及一个索引(int)作为参数 - 在
completeTask函数中,将给定索引处任务的Completed字段修改为true - 使用
bufio.Scanner正确读取输入行:- 创建扫描器:
scanner := bufio.NewScanner(os.Stdin) - 对于每一行输入:先调用
scanner.Scan(),再调用scanner.Text() - 这样可以确保正确读取包含空格的任务名称
- 创建扫描器:
- 解析第二个输入中的任务数据,创建任务切片:
- 按逗号拆分输入,获取各个任务条目
- 对每个条目按冒号拆分,分离名称和状态
- 将状态字符串转换为布尔值(
"true"转换为true,"false"转换为false)
- 将第三个输入字符串转换为整数,获取任务索引
- 调用你的
completeTask函数,并传入指向切片的指针和索引 - 完成任务后,使用与上一道挑战相同的格式显示所有任务:
- 对于已完成的任务:
"[x] [task_name]" - 对于未完成的任务:
"[ ] [task_name]"
- 对于已完成的任务:
- 打印确认消息:
"Task '[task_name]' marked as completed!" - 打印更新后的摘要:
"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)
}逻辑与流程中的所有课
自己练习: Go 在线编译器