C++

온라인 학습 관리 시스템 구현해보기

kdi6316 2025. 2. 7. 21:34

문제


어떤 온라인 학습 플랫폼에서 학생들의 성적을 관리하는 시스템을 만든다고 가정한다. 이 시스템은 다음과 같은 기능을 포함해야 한다.

  1. 학생 성적 추가 기능
    • 학생 ID(int)와 과목 이름(string), 점수(int)를 저장한다.
    • 한 학생은 여러 과목을 수강할 수 있다.
      • (예: "1001번 학생이 'C++' 과목에서 85점, '알고리즘'에서 90점을 받음")
    • 동일 학생의 동일 과목을 입력하는 경우엔 최신 점수로 갱신을 한다.
    • 점수는 0 ~ 100점까지만 유효한 범위
  2. 학생의 전체 성적 조회 기능
    • 특정 학생의 모든 과목 성적을 출력한다.
      • (예: "1001번 학생: C++(85점), 알고리즘(90점)")
    • 과목명은 알파벳 순으로 정렬하여 출력한다.
    • 또한, 존재하지 않는 학생 ID 입력 시 예외 처리를 하도록 한다.
  3. 전체 학생의 평균 점수 출력 기능
    • 전체 학생들의 각 과목별 평균 점수를 출력한다.
    • 평균 점수는 소수점 둘째 자리까지 표시한다.
      • (예: "C++ 과목 평균 점수: 87.5, 알고리즘 과목 평균 점수: 92.3")
  4. 과목별 최고 점수 학생 조회 기능
    • 특정 과목에서 가장 높은 점수를 받은 학생들을 찾는다.
    • 동점자가 있을 경우 학생 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