Menu
Coddy logo textTech

Podsumowanie — bezpieczne dzielenie

Część sekcji Logika i przepływ sterowania ścieżki GO w Coddy. Lekcja 44 z 68.

challenge icon

Wyzwanie

Łatwy

Stwórz wszechstronny kalkulator matematyczny, który implementuje bezpieczne dzielenie z wieloma niestandardowymi typami błędów i prawidłową obsługą błędów. To wyzwanie łączy niestandardowe typy błędów, opakowywanie błędów i sprawdzanie błędów, aby utworzyć niezawodny system, który sprawnie obsługuje różne niepowodzenia operacji matematycznych.

Otrzymasz dwa wejścia:

  • Łańcuch zawierający szczegóły operacji w formacie "operation,num1,num2,precision" (np. "divide,10,0,2")
  • Łańcuch zawierający ustawienia kalkulatora w formacie "calculator_name,mode" (np. "ScientificCalc,strict")

Twoje zadanie:

  1. Utworzyć dwa niestandardowe typy błędów:
    • strukturę DivisionError z polami Dividend (float64) i Divisor (float64)
    • strukturę ValidationError z polami Field (string) i Value (float64)
  2. Zaimplementować metodę Error() string dla DivisionError, która zwraca: "division error: cannot divide [dividend] by [divisor]"
  3. Zaimplementować metodę Error() string dla ValidationError, która zwraca: "validation error: invalid [field] value [value]"
  4. Przeanalizować pierwsze wejście, dzieląc je po przecinkach, aby uzyskać operację, num1, num2 i precision
  5. Przeanalizować drugie wejście, dzieląc je po przecinkach, aby uzyskać nazwę kalkulatora i tryb
  6. Przekonwertować liczby zapisane jako łańcuchy na float64, a precision na int
  7. Utworzyć funkcję safeDivide, która przyjmuje dwa parametry float64 i zwraca (float64, error):
    • Jeśli dzielnik wynosi 0, zwrócić 0 i DivisionError z wartościami dzielnej i dzielnika
    • Jeśli dzielna jest ujemna, a tryb to "strict", zwrócić 0 i ValidationError z polem "dividend" oraz wartością dzielnej
    • Jeśli dzielnik jest ujemny, a tryb to "strict", zwrócić 0 i ValidationError z polem "divisor" oraz wartością dzielnika
    • W przeciwnym razie zwrócić wynik dzielenia i nil
  8. Utworzyć funkcję performCalculation, która opakowuje wynik safeDivide:
    • Jeśli safeDivide zwraca błąd, opakować go w: "calculation failed in [calculator_name]: %w"
    • Jeśli operacja zakończy się powodzeniem, zwrócić wynik i nil
  9. Wywołać performCalculation i obsłużyć wynik:
    • Jeśli nie ma błędu: wypisać "Calculation successful: [result_formatted_to_precision_decimal_places]"
    • Jeśli wystąpi błąd: wypisać "Calculation failed: [error_message]"
  10. Użyć errors.As, aby sprawdzić konkretne typy błędów w opakowanym błędzie:
    • Wypisać "Checking for division error: [true/false]"
    • Wypisać "Checking for validation error: [true/false]"
  11. Jeśli zostanie znaleziony DivisionError, wypisać jego szczegóły:
    • "Division Error Details:"
    • "Dividend: [dividend]"
    • "Divisor: [divisor]"
  12. Jeśli zostanie znaleziony ValidationError, wypisać jego szczegóły:
    • "Validation Error Details:"
    • "Field: [field]"
    • "Value: [value]"
  13. Wyświetlić końcowe podsumowanie:
    • "Calculator Summary:"
    • "Name: [calculator_name]"
    • "Mode: [mode]"
    • "Operation: [operation]"
    • "Input: [num1] [operation_symbol] [num2]", gdzie operation_symbol to "/" dla dzielenia
    • "Precision: [precision] decimal places"
    • "Status: [Success/Failed]"

Użyj pakietu strings, aby podzielić wejściowe łańcuchy po przecinkach, pakietu strconv, aby przekonwertować łańcuchy na liczby, pakietu errors dla errors.As oraz pakietu fmt do opakowywania i formatowania błędów. To wyzwanie pokazuje, jak niestandardowe typy błędów, opakowywanie błędów i prawidłowe sprawdzanie błędów współdziałają, tworząc niezawodne systemy obsługi błędów, które dostarczają szczegółowych informacji o różnych typach niepowodzeń.

Spróbuj swoich sił

package main

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
)

func main() {
	// Wczytaj dane wejściowe
	var operationInput string
	var settingsInput string
	fmt.Scanln(&operationInput)
	fmt.Scanln(&settingsInput)
	
	// Przeanalizuj dane wejściowe operacji (operation,num1,num2,precision)
	operationParts := strings.Split(operationInput, ",")
	operation := operationParts[0]
	num1, _ := strconv.ParseFloat(operationParts[1], 64)
	num2, _ := strconv.ParseFloat(operationParts[2], 64)
	precision, _ := strconv.Atoi(operationParts[3])
	
	// Przeanalizuj dane wejściowe ustawień (calculator_name,mode)
	settingsParts := strings.Split(settingsInput, ",")
	calculatorName := settingsParts[0]
	mode := settingsParts[1]
	
	// TODO: Napisz kod poniżej
	// 1. Utwórz struktury DivisionError i ValidationError z metodami Error()
	// 2. Zaimplementuj funkcję safeDivide
	// 3. Zaimplementuj funkcję performCalculation
	// 4. Wywołaj performCalculation i obsłuż wyniki
	// 5. Użyj errors.As, aby sprawdzić, czy występują błędy określonych typów
	// 6. Jeśli wystąpią błędy, wypisz ich szczegóły
	// 7. Wyświetl końcowe podsumowanie
	
}

Wszystkie lekcje w sekcji Logika i przepływ sterowania

Poćwicz samodzielnie: Kompilator Go online