Menu
Coddy logo textTech

할 일 완료하기

Coddy GO 여정의 로직 & 흐름 섹션에 포함된 레슨 — 68개 중 23번째.

challenge icon

챌린지

쉬움

작업 관리 시스템의 이번 파트에서는 작업을 완료로 표시하는 기능을 구현하게 됩니다. 이 챌린지는 포인터 리시버를 사용하여 원본 작업 데이터를 수정하는 데 중점을 두며, 포인터가 구조체 필드를 영구적으로 업데이트하는 방법을 보여줍니다.

중요 참고 사항: 작업 이름에 공백이 포함될 수 있으므로(예: "Buy groceries"), 전체 입력 줄을 읽기 위해 bufio.Scanner를 사용해야 합니다. fmt.Scanf 함수는 첫 번째 공백에서 읽기를 중단하므로 공백이 포함된 작업 이름이 잘릴 수 있습니다. bufio.NewScanner(os.Stdin)를 사용하고 scanner.Scan()을 호출한 뒤 scanner.Text()를 호출하여 전체 줄을 읽으세요.

세 가지 입력을 받게 됩니다:

  • 작업 수를 나타내는 문자열 (예: "4")
  • 다음 형식의 작업 데이터를 포함하는 문자열: "name1:status1,name2:status2,name3:status3" (여기서 status는 "true" 또는 "false"입니다. 예: "Buy groceries:false,Call dentist:true,Finish project:false,Review code:false")
  • 완료할 작업의 인덱스를 나타내는 문자열 (예: 세 번째 작업을 위해 0 기반 인덱스를 사용하는 "2")

여러분의 과제는 다음과 같습니다:

  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. 두 번째 입력에서 작업 데이터를 파싱하여 작업 슬라이스를 생성합니다:
    • 입력을 쉼표로 분할하여 개별 작업 항목을 얻습니다.
    • 각 항목을 콜론으로 분할하여 이름과 상태를 분리합니다.
    • 상태 문자열을 불리언으로 변환합니다 ("true"true로, "false"false로).
  6. 세 번째 입력 문자열을 정수로 변환하여 작업 인덱스를 얻습니다.
  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)
}

로직 & 흐름의 모든 레슨