✏️ 성적 관리 프로그램
프로그램의 메뉴
- 학생추가
- 학생삭제
- 성적추가(변경)
- 성적삭제
- 평점보기
- 종료
프로그램 동작조건
- 사용자가 종료 메뉴를 선택하기 전까지는 계속해서 사용자의 입력을 받습니다.
- 메뉴 선택을 포함한 모든 입력은 숫자 또는 영문으로 받습니다.
성적별 점수
- A+ (4.5점) / A (4점)
- B+ (3.5점) / B (3점)
- C+ (2.5점) / C (2점)
- D+ (1.5점) / D (1점)
- F (0점)
✏️ 풀이 방법
✔️ while문으로 무한루프를 돌아 사용자가 종료 메뉴를 선택할 때 break를 사용하여 while문을 종료하도록 큰 틀을 잡았다.
✔️ 학생 정보는 구조체를 통해 학생 정보를 담는 구조체 배열을 만들어 담았다.
✔️ 성적별 점수는 Dictionary로 만들었다. (키 값을 통해 접근하기 위함)
✔️ while문에서는 if문으로 해당하는 메뉴에 접근하면 메뉴의 기능을 하는 함수를 실행하도록 했다.
1️⃣ 학생 구조체 선언
struct Student {
var name: String // 학생 이름
var gradeArr: [String:String] = [:] // 과목(grade), 성적(score) dictionary
func calcRating() {
gradeArr.forEach {
print("\($0.key): \($0.value)")
}
let avgRating = gradeArr.compactMap {
gradeRating[$0.value]
}.reduce(0, +) / Float(gradeArr.count)
let numberFomatter = NumberFormatter()
numberFomatter.roundingMode = .floor
numberFomatter.maximumSignificantDigits = 3
let avgStrRating = numberFomatter.string(for: avgRating) ?? ""
print("평점 : \(avgStrRating)")
}
}
Student 구조체에 name(학생 이름), gradeArr(성적 정보를 담을 Dictionary)을 선언했다. 또 gradeArr에 바로 접근할 수 있게 하기위해서 평점을 계산해주는 함수도 한번에 선언했다. 평점 함수는 forEach를 통해 gradeArr의 모든 요소를 출력하고, 과목의 평균 값을 담을 avgRating 변수에 compactMap메소드를 이용해서 gradeArr의 모든 요소를 가져와 gradeRating의 value값에 접근하여 reduce 메소드를 이용해 결합하고, 평균을 구해야 하므로 gradeArr의 개수만큼 나눠주면 된다. numberFomatter를 이용하여 .roundingMode 프로퍼티에서 .floor() (버림)으로 설정하고 .maximumSignificantDigits로 3자리로 잘라준다. 그리고 string으로 변환하여 출력하도록 한다.
2️⃣ 학생 정보를 담을 배열 선언
var stuArr: [Student] = [] // 학생 배열
[Student] 타입을 갖는 학생 배열을 선언한다.
3️⃣ 평점 정보를 담을 Dictionary 선언
let gradeRating: [String: Float] = ["A+":4.5, "A":4.0, "B+":3.5, "B":3.0, "C+":2.5, "C":2.0,"D+":1.5, "D":1.0, "F":0]
평점 정보를 담을 gradeRating Dictionary를 선언했다. key값을 통해 value값에 접근하기 위해 Dictionary로 선언했다. (평점 계산을 위함)
4️⃣ 학생 추가 함수
func addStu() {
print("추가할 학생의 이름을 입력해주세요")
let input = readLine()! // readLine()은 리턴 값이 옵셔널이므로 언래핑, 값이 확실하므로 !로 강제언래핑함
if input != "" && input != " " {
if stuArr.contains(where: { $0.name == input }) { // 클로저로 축약
print("\(input)은 이미 존재하는 학생입니다. 추가하지 않습니다.")
} else {
stuArr.append(.init(name: input))
print("\(input) 학생을 추가했습니다.")
}
} else {
print("입력이 잘못되었습니다. 다시 확인해주세요.")
}
}
학생을 추가하는 함수 addStu()를 정의한다. readLine()을 이용하여 값을 읽어오는데, readLine()은 리턴 값이 옵셔널이므로 언래핑 해야한다. 값이 확실하므로 !로 강제 언래핑 했다. (❗️원래는 옵셔널 바인딩(if let, guard)를 이용하는 것이 좋다.) 조건문을 이용해서 input값이 공백이거나, 값이 없으면 입력이 잘못되었다고 출력해준다. 만약 값이 공백이 아니거나, 값이 없으면 조건문을 이용해서 stuArr에 contains 메소드를 이용해서 존재하는 학생인지 여부를 확인하고, 존재하지 않으면 append 메소드를 이용하여 input 값을 name에 추가한다.
5️⃣ 학생 삭제 함수
func delStu() {
print("삭제할 학생의 이름을 입력해주세요")
let input = readLine()!
if input != "" && input != " " {
if let stuIndex = stuArr.firstIndex(where: {$0.name == input}) {
stuArr.remove(at: stuIndex)
print("\(input) 학생을 삭제하였습니다.")
} else {
print("\(input) 학생을 찾지 못했습니다.")
}
} else {
print("입력이 잘못되었습니다. 다시 확인해주세요.")
}
}
학생을 삭제하는 함수 delStu()를 정의한다. 마찬가지로 readLine()을 통해 값을 읽어온다. 조건문을 이용해서 input값이 공백이거나, 값이 없으면 입력이 잘못되었다고 출력해준다. 만약 값이 공백이 아니거나, 값이 없으면 stuArr에 firstIndex메소드를 이용하여 해당 학생의 index를 가져오고, remove 메소드를 이용해 해당 인덱스를 삭제한다. 해당하는 학생이 없으면 학생을 찾지 못했다고 출력한다.
6️⃣ 성적 추가 함수
func addGrade() {
print("성적을 추가할 학생의 이름, 과목 이름, 성적(A+, A, F 등)을 띄어쓰기로 구분하여 차례로 작성해주세요.")
print("입력예) Mickey Swift A+")
print("만약에 학생의 성적 중 해당 과목이 존재하면 기존 점수가 갱신됩니다.")
if let inputArr = readLine()?.split(separator: " "),
inputArr.count == 3,
let stuName = inputArr.first,
let stuScore = inputArr.last,
let stuIndex = stuArr.firstIndex(where: { $0.name == stuName }),
gradeRating.contains(where: { $0.key == stuScore }) {
let stuGrade = String(inputArr[1])
stuArr[stuIndex].gradeArr[stuGrade] = String(stuScore)
print("\(stuName) 학생의 \(stuGrade) 과목이 \(stuScore)로 추가(변경)되었습니다.")
} else {
print("입력이 잘못되었습니다. 다시 확인해주세요.")
}
}
성적을 추가하는 함수 addGrade()를 정의한다. input값을 담을 배열 inputArr을 선언한다. split을 이용해서 입력 값을 공백으로 구분하고, count를 이용해서 배열의 크기가 3을 넘지 않도록 했다. stuName은 inputArr의 첫번째 요소, stuScore는 inputArr의 마지막 요소, 자동으로 stuGrade는 inputArr의 두번째 요소가 된다. stuArr에 firstIndex메소드를 이용하여 해당 학생의 index를 가져오고, 평점 정보를 가지고 있는 gradeRating에 contains로 접근하여 입력한 평점이 gradeRating에 존재한다면, 해당 학생의 인덱스 배열에 접근하여 성적 배열에 학생의 점수를 입력한다.
7️⃣ 성적 삭제 함수
func delGrade() {
print("성적을 삭제할 학생의 이름, 과목 이름을 띄어쓰기로 구분하여 차례로 작성해주세요.")
print("입력예) Mickey Swift")
if let inputArr = readLine()?.split(separator: " "),
inputArr.count == 2,
let stuName = inputArr.first,
let stuGrade = inputArr.last {
if let stuIndex = stuArr.firstIndex(where: { $0.name == stuName }) {
stuArr[stuIndex].gradeArr.removeValue(forKey: String(stuGrade))
print("\(stuName) 학생의 \(stuGrade) 과목의 성적이 삭제되었습니다.")
} else {
print("\(stuName) 학생을 찾지 못했습니다.")
}
} else {
print("입력이 잘못되었습니다. 다시 확인해주세요.")
}
}
성적을 삭제하는 함수 delGrade()를 정의한다. input값을 담을 배열 inputArr을 선언한다. split을 이용해서 입력 값을 공백으로 구분하고, count를 이용해서 배열의 크기가 2을 넘지 않도록 했다. stuName은 inputArr의 첫번째 요소, stuGrade는 inputArr의 마지막 요소가 된다. stuArr에 firstIndex메소드를 이용하여 해당 학생의 index를 가져오고, 해당 학생 인덱스의 gradeArr배열에 접근하여 removeValue 메소드를 이용하여 성적을 삭제한다.
8️⃣ 평점 보기 함수
func viewRating() {
print("평점을 알고싶은 학생의 이름을 입력해주세요")
let input = readLine()!
if input != "" && input != " " {
if let stuIndex = stuArr.first(where: { $0.name == input }) {
stuIndex.calcRating()
} else {
print("\(input) 학생을 찾지 못했습니다.")
}
} else {
print("입력이 잘못되었습니다. 다시 확인해주세요.")
}
}
평점을 확인하는 함수 viewRating()을 정의한다. input값을 받아와서 조건문을 이용해서 input값이 공백이거나, 값이 없으면 입력이 잘못되었다고 출력해준다. stuArr에 firstIndex메소드를 이용하여 해당 학생의 index를 가져오고, 해당 학생 인덱스에 Student 구조체에서 정의한 calcRating() 함수를 실행한다.
9️⃣ while문 및 종료
while true {
print("원하는 기능을 입력해주세요")
print("1: 학생추가, 2: 학생삭제, 3: 성적추가(변경), 4: 성적삭제, 5: 평점보기, X: 종료")
let input = readLine()!
if input == "1" {
addStu()
}
else if input == "2" {
delStu()
}
else if input == "3" {
addGrade()
}
else if input == "4" {
delGrade()
}
else if input == "5" {
viewRating()
}
else if input == "X" {
print("프로그램을 종료합니다...")
break
}
else {
print("뭔가 입력이 잘못되었습니다. 1~5 사이의 숫자 혹은 X를 입력해주세요.")
}
}
while문의 조건을 true로 하여 무한루프 하도록 만들었고, input이 "X" 일 때, break문을 이용해서 종료하도록 만들었다.