見出し画像

2024-06-28 C++プログラミング練習


どうもケロッグです。
今日もC++のプログラミング練習をChatGPTくんと頑張りました。
前回同様、GPTくんに問題を作成してもらい、その要件を満たすプログラムを書いて、フィードバックをもらうという流れです。
GPTくんとのやり取りのリンクは以下です。

今回は、GPTくんの出題する問題が「学生の成績管理システム」もしくは「図書館の本管理システム」の2つしか出題しなくなったので、プロンプトを工夫しています。

プロンプト

私はC++を勉強しています。以下の条件に満たす実用的なプログラミングをつくる問題を作成してください。サンプルプログラムも提示してください。
【必須要素】
・参照渡し
・newとdelete
・ベクター
・クラス
【難易度】
エンジニア2年目
【コーディング量】
300行以上
【問題文中に以下の言葉は含んではいけません】
本、学生、学校、図書館

GPTの問題

メモリを更新しました

了解しました。以下の条件を満たす問題とサンプルプログラムを作成しますね。


問題: メンバー管理システム

あなたは会社のメンバー管理システムを作成することになりました。このシステムでは、従業員の情報を管理し、追加・削除・表示・検索などの機能を提供します。以下の要素を含むプログラムを作成してください。

  1. クラスの定義: Employee クラスを定義します。このクラスは従業員の基本情報を保持します(例: 名前、年齢、職位など)。必要に応じて、コンストラクタ、デストラクタ、メンバ関数を適切に定義してください。

  2. ベクターの利用: std::vector を使用して、複数の従業員オブジェクトを保持します。従業員の追加、削除、リスト表示などの操作を実装してください。

  3. 参照渡し: 関数の引数として、適切に参照渡しを使用してメンバー管理システムの操作を実装します。例えば、従業員を追加する関数や、特定の従業員情報を検索する関数などです。

  4. newとdeleteの使用: 動的メモリ管理の一環として、new と delete を使用して従業員オブジェクトの作成と破棄を行います。特に、オブジェクトの追加や削除時に new と delete を適切に利用してください。

以下にサンプルのクラス定義とメイン関数の一部を示します。このサンプルを基に、必要な関数や操作を追加して完全なプログラムを完成させてください。

私の回答

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

class Employee {
    int id;
    std::string name;
    std::string position;

public:
    Employee(int i, const std::string& n, const std::string& p)
        : id(i), name(n), position(p) {}

    int getId() const { return id; }
    std::string getName() const { return name; }
    std::string getPosition() const { return position; }

    ~Employee() {
        std::cout << "Destroying Employee object" << std::endl;
    }
};

class Table {
    std::vector<Employee*> employees;

public:
    void addMember(Employee* employee) {
        employees.push_back(employee);
        std::cout << "従業員を追加しました。" << std::endl;
        std::cout << "現在の従業員数: " << employees.size() << std::endl;
    }

    void deleteMember() {
        std::string name;
        std::cout << "削除する従業員の名前を入力してください: " << std::endl;
        std::cin >> name;

        employees.erase(
            std::remove_if(employees.begin(), employees.end(),
                [&name](Employee* emp) {
                    return emp->getName() == name;
                }),
            employees.end()
        );
        std::cout << "削除が完了しました。" << std::endl;
    }

    void searchMember() {
        std::string name;
        std::cout << "検索する従業員の名前を入力してください: " << std::endl;
        std::cin >> name;

        for (const auto& employee : employees) {
            if (employee->getName() == name) {
                std::cout << name << " さんのID: " << employee->getId() << std::endl;
                std::cout << name << " さんの役職: " << employee->getPosition() << std::endl;
                return;
            }
        }
        std::cout << "該当する従業員が見つかりませんでした。" << std::endl;
    }

    ~Table() {
        for (auto& employee : employees) {
            delete employee;
        }
        employees.clear();
    }
};

int main() {
    Table table;
    int num;

    std::cout << "次の選択肢から選んでください (1, 2, 3): " << std::endl;
    std::cout << "1: 従業員検索 2: 従業員追加 3: 従業員削除" << std::endl;
    std::cin >> num;

    if (num == 1) {
        table.searchMember();
    } else if (num == 2) {
        std::string name, position;
        int id;

        std::cout << "従業員のIDを入力してください: " << std::endl;
        std::cin >> id;
        std::cout << "従業員の名前を入力してください: " << std::endl;
        std::cin >> name;
        std::cout << "従業員の役職を入力してください: " << std::endl;
        std::cin >> position;

        Employee* newEmployee = new Employee(id, name, position);
        table.addMember(newEmployee);
    } else if (num == 3) {
        table.deleteMember();
    } else {
        std::cout << "1, 2, 3 のいずれかを選択してください。" << std::endl;
    }

    return 0;
}

GPTのフィードバック

  1. 要件の達成度: すべての必須要素(参照渡し、newとdelete、ベクター、クラス)を満たしています。参照渡しはメンバ関数内で使われていますが、関数の引数としての参照渡しがあまり見られなかったため、これを追加すると良いでしょう。

  2. コードの可読性: コードはわかりやすく、クラス設計や関数の使い方も明確です。変数名や関数名も適切で、コメントもあるとさらに良くなります。

  3. エラーハンドリング: ユーザー入力のエラーチェックがやや不足しています。無効な入力に対する処理を追加するとさらに良くなります。

  4. メモリ管理: newとdeleteを適切に使っており、メモリリークも防いでいます。デストラクタ内でのメモリ解放も正しく行われています。

フィードバックと改善点

  1. 参照渡しの利用: 参照渡しを関数の引数として使用する例を増やしてみましょう。例えば、addMember 関数の引数をポインタではなく参照にすることができます。

  2. 入力検証: ユーザー入力に対するエラーチェックを追加して、無効な入力に対処できるようにしましょう。

  3. 削除処理の改善: deleteMember 関数でメモリを解放する処理が抜けているため、削除前に delete を使用してメモリを解放しましょう。

  4. ループの導入: ユーザーが複数の操作を連続して行えるように、メイン関数にループを導入するとより実用的です。

プログラムの点数

90点 / 100点

  • 良い点: 指定された要件を満たしており、コードもわかりやすい。

  • 改善点: 参照渡しの利用やエラーハンドリング、ループの導入など、いくつかの改善点が残っているため、これらを修正するとさらに高得点になります。

今回の気づき、学び

GPTへのプロンプトの中で、「必須要素」としているものは、私が現在学んでいるものです。独習C++という参考書で勉強しているのですが、アウトプット量が少なく、自分の中に理論を確立していくのが厳しいと感じ、直近で学んだものや、忘れそうになっているものを必須要素として入れ込むことで、学習効率が上がっています。C++はプログラマーが考えなければならないことが多い言語だと思うので、自分のコードに何が足りてないのかを的確に教えてくれるGPTはほんとに神様のようです。GPTさん、これからもよろしくお願いします。

この記事が気に入ったらサポートをしてみませんか?