문제
어떤 온라인 학습 플랫폼에서 학생들의 성적을 관리하는 시스템을 만든다고 가정한다. 이 시스템은 다음과 같은 기능을 포함해야 한다.
- 학생 성적 추가 기능
- 학생 ID(int)와 과목 이름(string), 점수(int)를 저장한다.
- 한 학생은 여러 과목을 수강할 수 있다.
- (예: "1001번 학생이 'C++' 과목에서 85점, '알고리즘'에서 90점을 받음")
- 동일 학생의 동일 과목을 입력하는 경우엔 최신 점수로 갱신을 한다.
- 점수는 0 ~ 100점까지만 유효한 범위
- 학생의 전체 성적 조회 기능
- 특정 학생의 모든 과목 성적을 출력한다.
- (예: "1001번 학생: C++(85점), 알고리즘(90점)")
- 과목명은 알파벳 순으로 정렬하여 출력한다.
- 또한, 존재하지 않는 학생 ID 입력 시 예외 처리를 하도록 한다.
- 특정 학생의 모든 과목 성적을 출력한다.
- 전체 학생의 평균 점수 출력 기능
- 전체 학생들의 각 과목별 평균 점수를 출력한다.
- 평균 점수는 소수점 둘째 자리까지 표시한다.
- (예: "C++ 과목 평균 점수: 87.5, 알고리즘 과목 평균 점수: 92.3")
- 과목별 최고 점수 학생 조회 기능
- 특정 과목에서 가장 높은 점수를 받은 학생들을 찾는다.
- 동점자가 있을 경우 학생 ID를 오름차순으로 정렬해서 모두 출력한다.
- (예: "알고리즘 최고 점수: 95점 (학생 ID: 1003, 1005)"
#include <iostream>
#include <list>
#include <map>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class Student
{
private:
int ID;
map<string, int> subjects;
public:
void AddStudent(int id,string subject,int grade) //학생 추가및 동일 학생 입력시 과목추가 / 동일 과목 입력시 최신 점수로 갱신
{
ID = id;
if (subjects.find(subject) != subjects.end()) //해당 과목에대한 성적을 가지고 있는지 확인
{
subjects[subject] = grade;
}
else // 해당 과목이 추가되지 않았다면
{
subjects.insert({ subject,grade });
}
}
void ShowStudent() // 특정 학생의 모든 과목 성적을 출력 / 존재하지 않은 학생 ID입력시 예외처리
{
cout << ID << "번학생의 점수 : ";
map<string, int>::iterator iter;
for (iter = subjects.begin(); iter != subjects.end(); iter++) //인덱스 기반 iterator을 활용하여 처음부터 끝까지
{
cout <<iter->first << "(" << iter->second <<"점),";
}
cout << endl;
}
int GetID()
{
return ID;
}
map<string, int> GetSubjects()
{
return subjects;
}
};
class LearningManager
{
private:
list<Student> studentlist;
public:
void ShowMenu() //메뉴창을 통해서 입력받기
{
int input;
int id, score;
string subject;
while (true)
{
cout << "1.학생 성적 추가" << endl;
cout << "2.학생 성적 조회" << endl;
cout << "3.전체 평균 점수 출력" << endl;
cout << "4.과목별 최고 점수 학생 조회" << endl;
cout << "5.종료" << endl;
cin >> input;
if (input == 5)
break;
switch (input)
{
case 1:
cout << "학생 번호 입력 : ";
cin >> id;
cout << "과목입력 : ";
cin >> subject;
cout << "점수입력 : ";
cin >> score;
Addstudent(id, subject, score);
break;
case 2:
cout << "학생 번호 입력 : ";
cin >> id;
ShowStudent(id);
break;
case 3:
ShowAverage();
break;
case 4:
cout << "과목입력 : ";
cin >> subject;
ShowHigh(subject);
break;
default:
break;
}
}
}
void Addstudent(int id, string subject, int grade) // 0~100점 사이의 점수만 입력받도록하며 id를 기준으로 해당id가 존재하지 않을시 새로 객체를 생성한다
{
if (grade > 100 && grade < 0)
{
cout << "잘못된 점수 입력입니다." << endl;
return;
}
for (Student& s : studentlist) //foreach문으로 현재 학생list에 같은 id의 학생이 있는지 탐색
{
if (s.GetID() == id)
{
s.AddStudent(id, subject, grade); //존재한다면 과목과 점수를 추가 해준다
return;
}
}
Student st; //없을시 새로 만들어준다
st.AddStudent(id, subject, grade);
studentlist.push_back(st);
}
void ShowStudent(int id) // 원하는 id의 과목별 점수를 보여준다
{
for (Student& st : studentlist)
{
if (st.GetID() == id) //현재 list에 학생이 존재한다면 그학생의 과목별 점수를 표시하는 ShowStudent함수를 불러온다
{
st.ShowStudent();
return;
}
}
cout << id << "는 존재하지 않는 학생입니다.";
}
void ShowAverage() // 과목별 평균점수를 보여준다
{
map<string, int> averagecnt; //<과목명,해당과목점수를 보유한 학생수>
map<string, float> average; // <과목명,해당과목 평균>
for (Student st : studentlist) //foreach문을 통해 list에 담긴 학생정보를 순회한다
{
map<string, int> student = st.GetSubjects(); //학생들의 과목명과 점수가 담긴 map을 불러온다
for (auto iter = student.begin(); iter != student.end(); iter++) // iterator를 통해서 map의 처음부터 끝까지 순회한다
{
if (averagecnt.find(iter->first) != averagecnt.end()) // 과목명이 이미 averagecnt에 들어있다면
{
averagecnt[iter->first]++; //해당과목명의 count를 늘려준다
average[iter->first] = (average[iter->first] + iter->second)/ averagecnt[iter->first]++; //해당과목의 평균점수를 계산해준다
}
else //들어있지 않다면
{
averagecnt.insert({ iter->first,1.0f});
average.insert({ iter->first,iter->second });
}
}
}
for (auto iter = average.begin(); iter != average.end(); iter++) //인덱스 기반 iterator을 활용하여 처음부터 끝까지
{
cout << fixed;
cout.precision(2); //소수점 2자리까지 출력
cout << iter->first << "과목 평균점수 : " << iter->second << ",";
}
cout << endl;
}
void ShowHigh(string subjects) // 원하는 과목의 제일 높은 점수와 학생을 보여준다
{
vector<int> scores;
vector<int> highStudent;
for (Student st : studentlist)
{
map<string, int> student = st.GetSubjects();
for (auto iter = student.begin(); iter != student.end(); iter++)
{
if(iter->first == subjects)
scores.push_back(iter->second);
}
}
int max = *max_element(scores.begin(), scores.end());
for (Student st : studentlist)
{
map<string, int> student = st.GetSubjects();
if (st.GetSubjects()[subjects] == max)
{
highStudent.push_back(st.GetID());
}
}
sort(highStudent.begin(), highStudent.end());
cout << subjects << "최고점수 : " << max << "점 (학생ID : ";
for (auto iter = highStudent.begin(); iter != highStudent.end(); iter++)
{
cout << *iter << ",";
}
cout << ")"<<endl;
}
};
int main(void)
{
LearningManager learn;
learn.ShowMenu();
return 0;
}
사용 자료구조 : map,list,vector
1. 학생 성적 추가 기능
map을 사용하여 과목명을 key값으로 받아서 과목별로 점수를 추가할수있게 구현하였다.
void AddStudent(int id,string subject,int grade) //학생 추가및 동일 학생 입력시 과목추가 / 동일 과목 입력시 최신 점수로 갱신
{
ID = id;
if (subjects.find(subject) != subjects.end()) //해당 과목에대한 성적을 가지고 있는지 확인
{
subjects[subject] = grade;
}
else // 해당 과목이 추가되지 않았다면
{
subjects.insert({ subject,grade });
}
}
2. 학생 전체 성적조회
iterator를 사용하여 map에 있는 <key,value> / <과목명,성적>을 전부 출력할수 있게 구현하였다.
void ShowStudent() // 특정 학생의 모든 과목 성적을 출력 / 존재하지 않은 학생 ID입력시 예외처리
{
cout << ID << "번학생의 점수 : ";
map<string, int>::iterator iter;
for (iter = subjects.begin(); iter != subjects.end(); iter++) //인덱스 기반 iterator을 활용하여 처음부터 끝까지
{
cout <<iter->first << "(" << iter->second <<"점),";
}
cout << endl;
}
3.전체 학생의 각 과목별 평균조회 기능
반복자를 통해 가지고 있는 학생 list를 순회하고 학생이 가지고 있는map을 받아서 평균을 계산해서 출력할수 있게 구현하였다.
void ShowAverage() // 과목별 평균점수를 보여준다
{
map<string, int> averagecnt; //<과목명,해당과목점수를 보유한 학생수>
map<string, float> average; // <과목명,해당과목 평균>
for (Student st : studentlist) //foreach문을 통해 list에 담긴 학생정보를 순회한다
{
map<string, int> student = st.GetSubjects(); //학생들의 과목명과 점수가 담긴 map을 불러온다
for (auto iter = student.begin(); iter != student.end(); iter++) // iterator를 통해서 map의 처음부터 끝까지 순회한다
{
if (averagecnt.find(iter->first) != averagecnt.end()) // 과목명이 이미 averagecnt에 들어있다면
{
averagecnt[iter->first]++; //해당과목명의 count를 늘려준다
average[iter->first] = (average[iter->first] + iter->second)/ averagecnt[iter->first]++; //해당과목의 평균점수를 계산해준다
}
else //들어있지 않다면
{
averagecnt.insert({ iter->first,1.0f});
average.insert({ iter->first,iter->second });
}
}
}
for (auto iter = average.begin(); iter != average.end(); iter++) //인덱스 기반 iterator을 활용하여 처음부터 끝까지
{
cout << fixed;
cout.precision(2); //소수점 2자리까지 출력
cout << iter->first << "과목 평균점수 : " << iter->second << ",";
}
cout << endl;
}
4.과목별 최고점수
map에 value값으로 저장되어있는 점수를 vector로 받아 max_element를 통해서 최대값을 구하였다.
그후 학생이 가지고있는 과목과 점수에 대입하여 최고점수를 가지고 있는 학생을 vector에 넣은후 sort함수를 통해서 오름차순으로 정리 하였다
void ShowHigh(string subjects) // 원하는 과목의 제일 높은 점수와 학생을 보여준다
{
vector<int> scores;
vector<int> highStudent;
for (Student st : studentlist)
{
map<string, int> student = st.GetSubjects();
for (auto iter = student.begin(); iter != student.end(); iter++)
{
if(iter->first == subjects)
scores.push_back(iter->second);
}
}
int max = *max_element(scores.begin(), scores.end());
for (Student st : studentlist)
{
map<string, int> student = st.GetSubjects();
if (st.GetSubjects()[subjects] == max)
{
highStudent.push_back(st.GetID());
}
}
sort(highStudent.begin(), highStudent.end());
cout << subjects << "최고점수 : " << max << "점 (학생ID : ";
for (auto iter = highStudent.begin(); iter != highStudent.end(); iter++)
{
cout << *iter << ",";
}
cout << ")"<<endl;
}'C++' 카테고리의 다른 글
| 이진탐색 트리&레드-블랙 트리 (0) | 2025.02.18 |
|---|---|
| [STL]map과 set (0) | 2025.02.10 |
| 반복자 (1) | 2025.02.05 |
| STL[컨테이너] (1) | 2025.02.03 |
| OOP 단계별 프로젝트2 (0) | 2025.01.23 |