1. median()함수를 median.cpp( or median.c or median.C) 파일을 만들어서 따로 빼어보자
마찬가지로 median.h or median.hpp로 파일을 빼서 main()에서 include해야한다.
median.h
#ifndef HAHA_median_h
#define HAHA_median_h
#include <vector>
double median(std::vector<double>);
#endif
median.cpp
#include <algorithm> // sort함수 가져옴
#include <stdexcept> // domain_error 선언을 가져옴
#include <vector> // vector 타입의 선언을 가져옴
using namespace std;
// vector<double> 타입의 가운데 값 구함
// 이함수를 호출함면 인수로 전달된 벡터 전체를 복사
double median(vector<double> vec)
{
typedef vector<double>::size_type vec_sz;
vec_sz size = vec.size();
// 과제 점수의 유무 확인
if (size == 0)
throw domain_error("median of an empty vector");
sort(vec.begin(), vec.end());
vec_sz mid = size / 2;
return size % 2 == 0 ? (vec[mid] + vec[mid - 1]) / 2 : vec[mid];
}
grade.h
#ifndef HAHA_grade_h
#define HAHA_grade_h
#include <vector>
#include "student_info.h"
using namespace std;
double grade(double, double, double);
double grade(double, double, const vector<double>&);
double grade(const Student_info&);
#endif
grade.cpp
#include <stdexcept>
#include <vector>
#include "grade.h"
#include "median.h"
#include "student_info.h"
using namespace std;
double grade(double midterm, double final, double homework)
{
return 0.2 * midterm + 0.4 * final + 0.4 * homework;
}
// 중간시험, 기말시험, 과제 점수의 벡터로 학생의 종합 점수를 구함
// 이 함수는 인수를 복사하지 않고 median 함수가 해당 작업을 진행
double grade(double midterm, double final, const vector<double>& hw)
{
if (hw.size() == 0)
throw domain_error("과제 데이터가 없습니다.");
return grade(midterm, final, median(hw));
}
double grade(const Student_info& s)
{
return grade(s.midterm, s.final, s.homework);
}
student_info.h
#ifndef HAHA_Student_info
#define HAHA_Student_info
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct Student_info {
string name;
double midterm, final;
vector<double> homework;
};
bool compare(const Student_info&, const Student_info&);
istream& read(istream&, Student_info&);
istream& read_hw(istream&, vector<double>&);
#endif
student_info.cpp
// students 구조체와 관련된 함수들의 집합
#include "student_info.h"
using std::istream; using std::vector;
bool compare(const Student_info& x, const Student_info& y)
{
return x.name < y.name;
}
istream& read(istream& is, Student_info& s)
{
// 학생의 이름, 중간, 기말 시험 점수를 저장
is >> s.name >> s.midterm >> s.final;
read_hw(is, s.homework); //학생의 모든 과제 점수를 읽어 저장
return is;
}
// 입력 스트림에서 과제 점수를 읽어서 vector<double>에 넣음
istream& read_hw(istream& in, vector<double>& hw)
{
if (in) {
// 이전 내용을 제거
hw.clear();
// 과제 점수를 읽음
double x;
while (in >> x)
hw.push_back(x);
// 다음 학생의 점수 입력 작업을 고려해 스트림을 지움
in.clear();
}
return in;
}
main.cpp
#include <algorithm>
#include <iomanip>
#include <ios>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>
#include "grade.h"
#include "student_info.h"
using namespace std;
int main()
{
vector<Student_info> students;
Student_info record;
string::size_type maxlen = 0; // 가장 긴 이름의 길이
// 학생의 모든 데이터를 읽어 저장
// 불변성:students는 지금까지 읽은 모든 학생의 정보가 있음
// maxlen은 student에서 가장 긴 이름의 길이
while (read(cin, record)) {
// 길이가 가장 긴 이름을 찾음
maxlen = max(maxlen, record.name.size());
students.push_back(record);
}
// 학생정보를 알파벳순으로 정렬
sort(students.begin(), students.end(), compare);
// 이름과 점수를 출력
for (vector<Student_info>::size_type i = 0; i != students.size(); ++i) {
// 이름과 오른쪽 공백을 포함하여 maxlen+1개의 문자를 출력
cout << students[i].name
<< string(maxlen + 1 - students[i].name.size(), ' ');
// 점수를 계산하여 출력
try {
double final_grade = grade(students[i]);
streamsize prec = cout.precision();
cout << setprecision(3) << final_grade
<< setprecision(prec);
}
catch (domain_error e) {
cout << e.what();
}
cout << endl;
}
return 0;
}
'PROGRAM > C++' 카테고리의 다른 글
열혈C++ CH06 (0) | 2021.03.09 |
---|---|
CH5. 문자열 분할 (0) | 2020.08.20 |
CH04. 프로그램 및 데이터 구조화 (0) | 2020.08.17 |
CH03. 데이터 일괄처리 (0) | 2020.08.17 |
Hello Johns! 출력하기 (0) | 2020.08.16 |