2024-06-25 C++プログラミング練習
最近「独習C++」という参考書を読んでは、マネしてコードを書いて勉強しています。
しかし、参考書だけではアウトプットが足りないと思い、ChatGPTに問題を作ってもらって、解くことにしました。これのいいところは、使いたい構文と難易度をカスタマイズできることです。インプットしたことをすぐに実践的な形でアウトプットできるので最近かなりはまってます。
それでは、実際にChatGPTとのやり取りと、自分の書いたプログラムをさらしていきます。
GPTへのプロンプト
下記の条件に合わせたプログラム作成の問題を作ってください。
【必須構文】 配列 ポインター クラス 繰り返し 条件分岐 【難易度】 初心者向け
よろしくお願いいたします
GPTの返答
プログラム作成問題
問題文
次の要件を満たすプログラムを作成してください。
学生の名前と成績を管理するクラス Student を作成します。
このクラスには、名前(文字列)、成績(整数配列)、および成績の平均を計算するメソッドを含めます。
複数の Student オブジェクトを格納するための配列を作成し、ポインターを使ってアクセスします。
ユーザーから学生の名前と成績を入力させ、配列に格納します(最大3人の学生)。
学生の成績の平均を計算し、平均が70以上なら「合格」、それ以外は「不合格」と表示します。
すべての学生の情報を表示します。
プログラムの構造
以下のガイドラインに従ってプログラムを作成してください。
Student クラスの定義:
名前: name(文字列)
成績: grades(整数配列)
平均を計算するメソッド: calculateAverage()
メイン関数:
学生オブジェクトの配列を作成(最大3人の学生)。
学生情報の入力(名前と成績)。
学生の平均成績を計算し、条件分岐で合格・不合格を判断。
すべての学生情報を表示。
私の回答
//student.cpp
#include <iostream>
class Student{
std::string m_name;
int m_grades[3];
public:
explicit Student(std::string name, const int (&grades)[3]);
double calculateAverage() const;
std::string getname() const{return m_name;};
};
Student::Student(std::string name, const int (&grades)[3]):m_name(name){
for(int i=0; i<3 ;i++){
m_grades[i]=grades[i];
}
}
double Student::calculateAverage() const{
return (m_grades[0]+m_grades[1]+m_grades[2])/3;
}
int main(){
std::string name1;
int grades1[3];
std::string name2;
int grades2[3];
std::string name3;
int grades3[3];
std::cout<<"荳莠コ逶ョ縺ョ逕溷セ偵・蜷榊燕繧貞・蜉帙@縺ヲ縺上□縺輔>縲・<<std::endl;
std::cin>>name1;
std::cout<<name1<<"縺輔s縺ョ蝗ス隱槭・轤ケ謨ー繧貞・蜉帙@縺ヲ縺上□縺輔>縲・<<std::endl;
std::cin>>grades1[0];
std::cout<<name1<<"縺輔s縺ョ謨ー蟄ヲ縺ョ轤ケ謨ー繧貞・蜉帙@縺ヲ縺上□縺輔>縲・<<std::endl;
std::cin>>grades1[1];
std::cout<<name1<<"縺輔s縺ョ闍ア隱槭・轤ケ謨ー繧貞・蜉帙@縺ヲ縺上□縺輔>縲・<<std::endl;
std::cin>>grades1[2];
std::cout<<"莠御ココ逶ョ縺ョ逕溷セ偵・蜷榊燕繧貞・蜉帙@縺ヲ縺上□縺輔>縲・<<std::endl;
std::cin>>name2;
std::cout<<name2<<"縺輔s縺ョ蝗ス隱槭・轤ケ謨ー繧貞・蜉帙@縺ヲ縺上□縺輔>縲・<<std::endl;
std::cin>>grades2[0];
std::cout<<name2<<"縺輔s縺ョ謨ー蟄ヲ縺ョ轤ケ謨ー繧貞・蜉帙@縺ヲ縺上□縺輔>縲・<<std::endl;
std::cin>>grades2[1];
std::cout<<name2<<"縺輔s縺ョ闍ア隱槭・轤ケ謨ー繧貞・蜉帙@縺ヲ縺上□縺輔>縲・<<std::endl;
std::cin>>grades2[2];
std::cout<<"荳我ココ逶ョ縺ョ逕溷セ偵・蜷榊燕繧貞・蜉帙@縺ヲ縺上□縺輔>縲・<<std::endl;
std::cin>>name3;
std::cout<<name3<<"縺輔s縺ョ蝗ス隱槭・轤ケ謨ー繧貞・蜉帙@縺ヲ縺上□縺輔>縲・<<std::endl;
std::cin>>grades3[0];
std::cout<<name3<<"縺輔s縺ョ謨ー蟄ヲ縺ョ轤ケ謨ー繧貞・蜉帙@縺ヲ縺上□縺輔>縲・<<std::endl;
std::cin>>grades3[1];
std::cout<<name3<<"縺輔s縺ョ闍ア隱槭・轤ケ謨ー繧貞・蜉帙@縺ヲ縺上□縺輔>縲・<<std::endl;
std::cin>>grades3[2];
Student students[]={
Student{name1,grades1},
Student{name2,grades2},
Student{name3,grades3},
};
for (auto& stu : students){
std::cout<<stu.getname()<<"縺輔s縺ョ蟷ウ蝮・せ縺ッ"<<stu.calculateAverage()<<"縺ァ縺吶・<<std::endl;
if(70<=stu.calculateAverage()){
std::cout<<stu.getname()<<"縺輔s縺ッ蜷域シ縺ァ縺吶・<<std::endl;
}
else{
std::cout<<stu.getname()<<"縺輔s縺ッ荳榊粋譬シ縺ァ縺吶・<<std::endl;
}
}
return 0;
}
GPTからのフィードバック
評価基準
要件の達成度(40点)
コードの正確さ(30点)
コードの効率性(10点)
コードの読みやすさとスタイル(10点)
メモリ管理とクリーンアップ(10点)
評価
要件の達成度(40点満点中40点)
必須構文(配列、ポインター、クラス、繰り返し、条件分岐)をすべて使用しており、要件を完全に満たしています。
コードの正確さ(30点満点中25点)
平均計算における整数除算による誤りがありましたが、これは簡単に修正可能です。その他は正しく機能しています。
コードの効率性(10点満点中9点)
繰り返し処理や配列の扱いが効率的ですが、入力処理をループでまとめることでさらに効率化が可能です。
コードの読みやすさとスタイル(10点満点中9点)
コードは比較的読みやすいですが、入力部分の重複を減らすとさらに良くなります。コメントがもう少し多いと初心者にもわかりやすいです。
メモリ管理とクリーンアップ(10点満点中9点)
動的メモリを使用していますが、適切に解放されています。ただし、静的配列を使用しても良い場合にはその方が簡潔です。
合計
40点 + 25点 + 9点 + 9点 + 9点 = 92点
総評
プログラムは非常によく書かれており、初心者向けの要件をすべて満たしています。いくつかの小さな改善点(平均計算の修正や入力処理の効率化)を除けば、ほぼ完璧な出来です。このレベルであれば、初心者のプログラマーとして非常に優れています。今後は、さらに効率的で読みやすいコードを書くことを目指し、より高度なメモリ管理やアルゴリズムに挑戦してみてください。
所感
オブジェクトの配列やクラスを学んだばかりだったため、構文に使用しました。また、ifやforを使うことで少し複雑なプログラムを書くことを目的にしました。
92点とおおむね良いプログラムが書けたのではないかと思います。
しかし、計算に用いた変数の型や、for文の使い方、動的メモリの処理など、課題はあるので、それらを意識して今後は書いていきます。