🎯 Swift로 계산기 만들기
1️⃣ Intro : iOS 개발 언어인 Swift를 학습해 봅시다🔥
- 지금까지 배운 Swift 문법을 응용해서 나만의 계산기를 만들어 봅시다!
- 간소화된 버전의 계산기 입니다.
- 과제는 Lv1~Lv3까지 필수 구현, Lv4 추가 구현으로 진행됩니다.
2️⃣ 개발 프로세스 가이드
1. 개발 환경 세팅
- 파일 생성방법 : Xcode - New - Playground - [iOS] - Blank 생성
- 최신 맥 OS에서 Xcode를 설치하면 Xcode 16 이상 버전을 사용하게 되는데 프로젝트 생성 시 Swift 6으로 되어 있을 경우, Swift 5로 변경하고 진행
- Playground를 사용하여 함수의 파라미터로 직접 사용자의 입력값을 받을 수 있습니다.
// 함수의 파라미터로 숫자를 직접 입력
let calculator = Calculator()
let addResult = calculator.calculate(operator: "+", firstNumber: 10, secondNumber: 20)
* 필수 구현기능(Lv1~Lv3)
class Calculator {
// Todo : 내부 구현하기
}
let calculator = Calculator() // 인스턴스 생성하여 변수에 할당
// Todo : calculator 변수를 활용하여 사칙연산을 진행
Lv1
- 더하기, 빼기, 나누기, 곱하기 연산을 수행할 수 있는 Calculator 클래스 만들기
- 생성한 클래스를 이용하여 연산을 진행하고 출력
- 오류가 날 수 있는 "예외처리" 상황에 대해 고민해 보기
Lv2
- Lv1에서 만들 Calculator 클래스에 "나머지 연산"이 가능하도록 코드를 추가하고, 연산 진행 후 출력
- ex) 나머지 연산 예시 : 6을 3으로 나눈 나머지는 0 / 5를 3으로 나눈 나머지는 2
- 오류가 날 수 있는 '예외처리' 상황에 대해 고민해 보기 + 구현하기
Lv3
- 아래 각각의 클래스들을 만들고 클래스 간의 관계를 고려하여 Calculator 클래스와 관계 맺기
- AddOperation(더하기)
- SubtractOperation(빼기)
- MultiplyOperation(곱하기)
- DivideOperation(나누기)
- Calculator 클래스의 내부 코드를 변경
- 관계를 맺은 후 필요하다면 별도로 만든 연산 클래스의 인스턴스를 Calculator 내부에서 사용
- Lv2와 비교하여 어떠한 점이 개선되었는지 스스로 생각해 봅시다.
- hint. 클래스의 책임(단일 책임 원칙)
✅ 직접 구현해 보기 - Lv1
Lv1
- 더하기, 빼기, 나누기, 곱하기 연산을 수행할 수 있는 Calculator 클래스 만들기
- 생성한 클래스를 이용하여 연산을 진행하고 출력
- 오류가 날 수 있는 "예외처리" 상황에 대해 고민해 보기
class Calculator {
func add (num1: Int, num2: Int) -> Int {
return num1 + num2
}
func sub (num1: Int, num2: Int) -> Int {
return num1 - num2
}
func mul (num1: Int, num2: Int) -> Int {
return num1 * num2
}
func div(num1: Double, num2: Double) -> Double? {
if num1 == 0 || num2 == 0{
return nil
}
return num1 / num2
}
}
let calculator = Calculator()
print(calculator.add(num1: 20, num2: 10))
print(calculator.sub(num1: 20, num2: 10))
print(calculator.mul(num1: 20, num2: 10))
print(calculator.div(num1: 20, num2: 3) ?? "0으로 나눌 수 없습니다.")
// 0으로 나누었을 때 (예외처리)
print(calculator.div(num1: 20, num2: 0) ?? "0으로 나눌 수 없습니다.")
맨 처음 작성했던 코드이다.
Calculator class안에 각각의 기능을 하는 func 함수를 추가해서 작성했다.
calculator에 Calculator 인스턴스를 생성하고 calculator.add()처럼 함수를 사용했다.
// 나누기 부분 함수
func div(num1: Double, num2: Double) -> Double? {
if num1 == 0 || num2 == 0{
return nil
}
return num1 / num2
}
나누기 부분 함수는 파라미터의 데이터 타입은 소수점 표현을 위해 Double로 변경하였고,
if문을 사용해서 num1 또는 num2가 0인 경우 nil 값을 return 하도록 구현했다.
num1 또는 num2가 0이 아닌 경우
정상적으로 두 수를 나눈 값을 return 하도록 구현했다.
// 나누기 함수 호출 부분
print(calculator.div(num1: 20, num2: 3) ?? "0으로 나눌 수 없습니다.")
나누기 함수 호출 부분에서는 '??' 널 병합 연산자를 사용하여
calculator.div(num1: x, num2: y)의 값이 nil이 return 될 때
"0으로 나눌 수 없습니다"라는 기본값을 반환하도록 구현하였다.
따라서 num1 또는 num2가 0일 때 nil이 반환되므로
최종적으로는 "0으로 나눌 수 없습니다"가 출력된다.
🎯 트러블 슈팅 1 - 코드 수정
여기까지 코드를 구현했는데 문제를 다시 보니
// 함수의 파라미터로 숫자를 직접 입력
let calculator = Calculator()
let addResult = calculator.calculate(operator: "+", firstNumber: 10, secondNumber: 20)
파라미터가 3개인 calculate 함수를 사용하고 있었다...
그래서 코드를 다시 수정하기로 했다.
String 값의 operator를 사용하는 함수를 어떻게 구현할까 고민하다가 switch문이 생각났다.
class Calculator {
func calculate (op: String, num1: Double, num2: Double) -> String {
switch op {
case "+":
var result = Int(num1 + num2)
return "\(result)"
case "-":
var result = Int(num1 - num2)
return "\(result)"
case "*":
var result = Int(num1 * num2)
return "\(result)"
case "/":
if num1 == 0 || num2 == 0 {
return "0으로 나눌 수 없습니다."
}
var result = num1 / num2
return "\(result)"
default:
return "에러 발생"
}
}
}
let calculator = Calculator()
let addResult = calculator.calculate(op: "+", num1: 10, num2: 5)
print(addResult)
let subResult = calculator.calculate(op: "-", num1: 10, num2: 5)
print(subResult)
let mulResult = calculator.calculate(op: "*", num1: 10, num2: 5)
print(mulResult)
let divResult = calculator.calculate(op: "/", num1: 10, num2: 3)
print(divResult)
// 0으로 나누었을 때 (예외처리)
let divResult2 = calculator.calculate(op: "/", num1: 10, num2: 0)
print(divResult2)
그렇게 완성된 두 번째 코드이다.
operator라는 이름의 변수를 사용하려고 했는데 예약어라 사용이 안돼서 op라는 이름의 변수를 사용했다.
나누기 연산에서는 num1과 num2의 값을 Double 타입으로 받고, result변수에 연산 결과를 Float형식으로 타입 변환하여 저장 후 return 하고 나누기 연산을 제외한 다른 연산에서는 num1과 num2의 값을 Double 타입으로 받고, result 변수에 연산 결과를 Int형식으로 타입 변환하여 저장하고 return 한다.
✅ 직접 구현해 보기 - Lv2
Lv2
- Lv1에서 만들 Calculator 클래스에 "나머지 연산"이 가능하도록 코드를 추가하고, 연산 진행 후 출력
- ex) 나머지 연산 예시 : 6을 3으로 나눈 나머지는 0 / 5를 3으로 나눈 나머지는 2
- 오류가 날 수 있는 '예외처리' 상황에 대해 고민해 보기 + 구현하기
내가 만든 코드에 나머지 연산 (mod 연산)을 추가해 보았다.
class Calculator {
// 파라미터 3개 (String 타입의 op, Double 타입의 num1, Double 타입의 num2) 함수
func calculate (op: String, num1: Double, num2: Double) -> String {
switch op {
case "+": // 더하기 연산
var result = Int(num1 + num2) // 타입 변경
return "\(result)"
case "-": // 빼기 연산
var result = Int(num1 - num2) // 타입 변경
return "\(result)"
case "*": // 곱하기 연산
var result = Int(num1 * num2) // 타입 변경
return "\(result)"
case "/": // 나누기 연산
if num1 == 0 || num2 == 0 { // 0 입력 예외 처리
return "0으로 나눌 수 없습니다."
}
var result = num1 / num2
return "\(result)"
case "%": // 나머지 연산
var result = Int(num1) % Int(num2) // mod연산자 사용을 위한 타입 변경
return "\(result)"
default: // 기본값
return "에러 발생"
}
}
}
let calculator = Calculator()
let addResult = calculator.calculate(op: "+", num1: 10, num2: 5)
print(addResult)
let subResult = calculator.calculate(op: "-", num1: 10, num2: 5)
print(subResult)
let mulResult = calculator.calculate(op: "*", num1: 10, num2: 5)
print(mulResult)
let divResult = calculator.calculate(op: "/", num1: 10, num2: 3)
print(divResult)
// 0으로 나누었을 때 (예외처리)
let divResult2 = calculator.calculate(op: "/", num1: 10, num2: 0)
print(divResult2)
// 나머지 연산 호출 부분 추가
let modResult = calculator.calculate(op: "%", num1: 10, num2: 3)
print(modResult)
Lv3은 다음에 구현해 보도록 하겠다.
🎯 트러블 슈팅 2 - % (mod 연산자) 사용
case "%":
var result = num1 % num2
return "\(result)"
오류의 내용을 찾아봤더니 나머지 연산은 실수형에서도 가능하지만 % 연산자의 사용은 정수형에서만 사용이 가능해서 발생하는 오류였다.
현재 num1과 num2가 Double 형으로 받아오기 때문에 그대로 나머지 연산을 사용하려면 truncatingRemainder 함수를 사용하라는 안내였다.
내가 필요한 나머지 연산은 소수점 나머지 연산이 아니라 정수형 나머지 연산이기 때문에 다음과 같이 코드를 수정했다.
// 나머지 연산
case "%":
var result = Int(num1) % Int(num2)
return "\(result)"
// 나머지 연산 호출
let modResult = calculator.calculate(op: "%", num1: 10, num2: 3)
print(modResult)
num1과 num2를 Int로 감싸 타입 변환을 시켜주고 % 연산자를 사용해서 나머지 연산을 수행했다.
✓ TIL
- 타입 변환 String(), Int(), Float() 등
- % 연산자는 Int형에서만 직접 사용 가능, 실수형에서는 truncatingRemainder 함수 사용
- 나누기를 수행하면 소수점 2자리까지만 출력하도록 처리해 보기
'스파르타 코딩 클럽 - iOS 스타터 6기 > 본 캠프' 카테고리의 다른 글
12. 스파르타 코딩 클럽 - 열거형 (Enum) (1) | 2025.03.13 |
---|---|
11. 스파르타 코딩 클럽 - 클로저 (Closure) (0) | 2025.03.12 |
9. 스파르타 코딩 클럽 - guard 조건문 (0) | 2025.03.11 |
8. 스파르타 코딩 클럽 - 주석과 print (0) | 2025.03.10 |
7. 스파르타 코딩 클럽 - Camel case, Snake case, : 컨벤션 (0) | 2025.03.10 |