C++を用いたコンテスト参加者情報管理システムの実装

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;
}

質問回答

  1. std::ostreamは出力ストリームの基底クラスであり、std::coutとstd::ofstreamの両方にポリモーフィズムで対応可能です。write()関数の拡張性により、フォーマット変更は不要です。
  2. ファイル操作時のエラー処理は二箇所に存在します:
    • 保存時の例外:ファイルオープン失敗時にruntime_errorをスローし、main処理で捕捉してエラー出力
    • 読み込み時の例外:同様に捕捉して処理を中断します
  3. ソート条件のラムダ式実装は可能ですが、明示的な関数の方が可読性に優れます。このケースでは関数ポインタの使用が適切です。
  4. 出力結果のフォーマットは以下の通り:
    12345      Tanaka     ComputerScience    5    320
    67890      Sato       Mathematics        4    280
    

タグ: C++ STL ファイル入出力 例外処理 ソートアルゴリズム

5月20日 04:33 投稿