[백준] 25206번 너의 평점은 (C++)

yeonjiyooo·2025년 5월 17일
0

PS

목록 보기
19/19

백준 5800번 성적 통계

문제

인하대학교 컴퓨터공학과를 졸업하기 위해서는, 전공평점이 3.3 이상이거나 졸업고사를 통과해야 한다. 그런데 아뿔싸, 치훈이는 깜빡하고 졸업고사를 응시하지 않았다는 사실을 깨달았다!

치훈이의 전공평점을 계산해주는 프로그램을 작성해보자.
전공평점은 전공과목별 (학점 × 과목평점)의 합을 학점의 총합으로 나눈 값이다.

인하대학교 컴퓨터공학과의 등급에 따른 과목평점은 다음 표와 같다.

학점과목평점
A+4.5
A04.0
B+3.5
B03.0
C+2.5
C02.0
D+1.5
D01.0
F0.0

P/F 과목의 경우 등급이 P또는 F로 표시되는데, 등급이 P인 과목은 계산에서 제외해야 한다. 과연 치훈이는 무사히 졸업할 수 있을까?


입력

20줄에 걸쳐 치훈이가 수강한 전공과목의 과목명, 학점, 등급이 공백으로 구분되어 주어진다.


출력

치훈이의 전공평점을 출력한다.

정답과의 절대오차 또는 상대오차가 10^-4 이하이면 정답으로 인정한다.


코드

#include <stdio.h>
#include <iostream>
#include <string>

using namespace std;

double grade2num(string grade) {
	double num;
	if (grade == "A+") num = 4.5;
	else if (grade == "A0") num = 4.0;
	else if (grade == "B+") num = 3.5;
	else if (grade == "B0") num = 3.0;
	else if (grade == "C+") num = 2.5;
	else if (grade == "C0") num = 2.0;
	else if (grade == "D+") num = 1.5;
	else if (grade == "D0") num = 1.0;
	else num = 0;
	return num;
}

int main() {
	
	string subject, grade;
	double credit;

	double sum = 0;
	double total_credit = 0;
	//학점 = sum / total_credit

	for (int i=1; i<=20; i++) {
		cin >> subject >> credit >> grade;
		if (grade == "P") continue; //학점이 P인 경우는 계산에 포함 X
		else {
			total_credit += credit;
			double score = grade2num(grade);
			sum += credit * score;
		}
	}

	cout<<fixed;
	cout.precision(6);
	cout << sum / total_credit;
    
	return 0;

}

코드풀이

풀이 방법 자체는 별 게 없다. 20줄짜리 과목명, 학점, 등급 input을 잘 처리해서 전체 학점과 전체 평점점수를 구해 나눠주기만 하면 된다. 몇 가지 주의해야할 점은 "등급이 P인 과목은 계산에서 제외한다", "오차범위가 10^-4이내여야 한다" 정도 있겠다.

✔️ C++ 출력 소수점 자리수 설정

C++에서는 별도의 설정이 없다면 소수를 출력하는 경우 소수점 6번째 자리수에서 반올림하여 소수점 5번째 자리까지 출력한다.

double a = 3.123456789;
cout << a;

따라서 문제 조건에 따라 출력해야 하는 소수점 자리수를 설정해야 한다면 fixed와 precision을 사용해야한다.

cout << fixed;
cout.precision(3); //소수점 3번째 자리까지 출력 (소수점 4번째 자리에서 반올림)

이 때 주의해야할 점은 precision과 함께 cout << fixed; 를 꼭 작성해줘야 한다.

만약 fixed를 사용하지 않는 경우는 정수 부분 자릿수까지 포함하여 해당 인자만큼의 숫자 개수를 출력하게 된다. precision(n)은 전체 출력값의 숫자 개수를 n개로 설정한다고 보면 된다.

//fixed와 precision을 함께 사용하는 경우
cout << fixed;
cout.precision(3);
cout << 3.123456789;
output: 3.123

//precision만 사용하는 경우
cout.precision(3);
cout << 30.123456789;
output: 30.1

✔️ C++ 타입 변환 (번외)

이 문제의 풀이에서는 사용되지 않았지만 덧붙이는 이유는...

갑자기 처음 구현당시 소수점까지 string으로 받아서 처리하느라 진땀을 뺐기 때문이다. (지금 생각하면 어이 X) 일단 처음 내가 생각했던 방법은 이러하다.

  1. 입력으로 들어오는 credit은 1.0, 2.0, 3.0, 4.0 이므로 가장 앞 문자만 보면 된다.
  2. string 타입의 변수 credit에 해당 입력을 저장한다.
  3. credit[0]을 double로 타입 변환을 하여 저장한다.

다시 봐도 황당하지만; 어쨌든 이렇게 진행하면서 문제가 되었던 부분은 3번 단계이다.

int 🔄 double 형변환이 아닌 char 🔄 double 이기 때문에 아무리 credit[0] 문자 값이 3이더라도 변환값은 3이 아니다. 그것의 아스키코드 값인 51이 반환값이 된다.

따라서 내가 원하는 3으로의 형변환을 하려면 다음과 같은 로직이 추가적으로 필요하다.

string credit = "3.0"; //credit[0] = 3
double credit_num = double(credit[0]) - double('0'); //숫자0의 아스키코드 빼기
cout << credit_num; //output: 3

그런데 너무 오랜만에 사용해서 그런지 이 사실을 망각한채 외안되만 500번 생각했다.

뜬금없이 이상하게 처리하려고 하다가 까먹었던 내용 다시 알 수 있었으니까 좋긴한데 10번 다시 생각해도 왜 소수점을 굳이굳이굳이 string으로 받으려고 했을까는 의문이다...^^*

(실버니까 풀이 보기도 쫀심 상해서 알아차리는데 상당한 시간을 썼다 ♨️)


마지막으로 한 가지 더 짚고 넘어가자면, 사실 int(a), double(b) 와 같은 형변환 방식은 C++ 에서는 권장되지 않는 방법이고, static_cast<Type>(a), dynamic_cast<Type>(a) 를 쓰는 것이 좋다.

전자의 경우 잘못된 형변환일 때도 컴파일 타임에 잡아내지 못할 수 있기 때문이다.

하지만 후자의 경우 타입 간의 호환성을 컴파일 시에 확인하므로 잘못된 형변환의 경우를 컴파일 시에 막을 수 있다! 따라서 웬만하면 후자를 사용하는 것으로 습관을 들여야겠다.


❗ 이제 실버쯤은 눈 감고도 풀 수 있겠다고(과장법) 방심하고 있었는데 간만에 좀 헤매는 문제가 나와서 정리해보았다. 역시 배움엔 끝이 없고 방심하는 순간 뒤처지는 건 금방이겠구나... 생각이 들었다 ◞‸◟💧 그래도 이 문제 덕분에 코테 준비도 꾸준히 해야겠다고 다시금 다짐하게 되는 좋은 계기가 되었다!

profile
1 ^ 365 = 1 BUT 1.01 ^ 365 = 37쩜 어쩌고...

0개의 댓글