contestant.hpp
#pragma once
#include <iomanip>
#include <iostream>
#include <string>
struct Participant {
long studentId;
std::string fullName;
std::string department;
int problemCount;
int totalTime;
};
std::ostream& operator<<(std::ostream& out, const Participant& p) {
out << std::left;
out << std::setw(12) << p.studentId
<< std::setw(15) << p.fullName
<< std::setw(15) << p.department
<< std::setw(8) << p.problemCount
<< std::setw(8) << p.totalTime;
return out;
}
std::istream& operator>>(std::istream& in, Participant& p) {
in >> p.studentId >> p.fullName >> p.department >> p.problemCount >> p.totalTime;
return in;
}
utility.cpp
#include <fstream>
#include <vector>
#include "contestant.hpp"
bool compareRule(const Participant& a, const Participant& b) {
if(a.problemCount != b.problemCount) {
return a.problemCount > b.problemCount;
}
return a.totalTime < b.totalTime;
}
void outputToStream(std::ostream& os, const std::vector<Participant>& v) {
for (const auto& entry : v) {
os << entry << std::endl;
}
}
void displayResult(const std::vector<Participant>& v) {
outputToStream(std::cout, v);
}
void saveToFile(const std::string& filename, const std::vector<Participant>& v) {
std::ofstream fileWriter(filename);
if (!fileWriter) {
throw std::runtime_error("File open error: " + filename);
}
outputToStream(fileWriter, v);
}
std::vector<Participant> loadFromFile(const std::string& filename) {
std::ifstream fileReader(filename);
if (!fileReader) {
throw std::runtime_error("File not found: " + filename);
}
std::string header;
std::getline(fileReader, header);
std::vector<Participant> result;
Participant temp;
int sequence;
while (fileReader >> sequence >> temp) {
result.push_back(temp);
}
return result;
}
operation.cpp
#include <algorithm>
#include "contestant.hpp"
#include "utility.cpp"
const std::string INPUT_FILE = "contest_data.txt";
const std::string OUTPUT_FILE = "ranking_result.txt";
void executeProcess() {
try {
auto participants = loadFromFile(INPUT_FILE);
std::sort(participants.begin(), participants.end(), compareRule);
displayResult(participants);
saveToFile(OUTPUT_FILE, participants);
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
}
int main() {
executeProcess();
return 0;
}
質問回答
- std::ostreamは出力ストリームの基底クラスであり、std::coutとstd::ofstreamの両方にポリモーフィズムで対応可能です。write()関数の拡張性により、フォーマット変更は不要です。
- ファイル操作時のエラー処理は二箇所に存在します:
- 保存時の例外:ファイルオープン失敗時にruntime_errorをスローし、main処理で捕捉してエラー出力
- 読み込み時の例外:同様に捕捉して処理を中断します
- ソート条件のラムダ式実装は可能ですが、明示的な関数の方が可読性に優れます。このケースでは関数ポインタの使用が適切です。
- 出力結果のフォーマットは以下の通り:
12345 Tanaka ComputerScience 5 320
67890 Sato Mathematics 4 280