مشروع: نظام درجات الطلاب — أساسيات C++
مشروع: نظام درجات الطلاب
برنامج يجمع كل ما تعلمته في الدورة: المتغيرات، النصوص، الشروط، الحلقات، vector، الدوال، والمراجع.
المتطلبات
- تخزين طلاب لكل منهم اسم ودرجة.
- إضافة طالب، وعرض الجميع بجدول منسق، وإحصائيات (متوسط، أعلى، أقل، عدد الناجحين).
- عرض الطلاب مرتبين حسب الدرجة.
- عدم التوقف أو الدوران للأبد عند إدخال خاطئ.
struct: تجميع بيانات الطالب
struct Student {
string name;
int score;
};
vector<Student> students;
students.push_back({"Mona", 95});
cout << students[0].name;struct تجمع عدة متغيرات مرتبطة في نوع واحد. (في دورة البرمجة الكائنية ستتعلم class التي تضيف التغليف والدوال.)
تقسيم البرنامج
| الدالة | التمرير |
|---|---|
| string letterGrade(int score) | بالقيمة (int صغير) |
| void printTable(const vector<Student>&) | const& (قراءة فقط) |
| void printStats(const vector<Student>&) | const& |
| bool readStudent(Student&) | مرجع: تملأ بيانات المستدعي وترجع نجاح القراءة |
الترتيب حسب حقل
struct Student { string name; int score; };
vector<Student> sorted = {{"سارة", 91}, {"عمر", 78}, {"ليلى", 85}};
sort(sorted.begin(), sorted.end(), [](const Student& a, const Student& b) {
return a.score > b.score;
});التعبير [](...) { ... } دالة صغيرة بلا اسم (lambda) تحدد طريقة المقارنة. ستتعمق فيها في دورة C++ المتقدمة.
الإدخال الآمن
readStudent تتحقق من نجاح cin، ومن أن الدرجة بين 0 و 100. إذا فشل الإدخال، يتوقف البرنامج عن طلب المزيد بدل الدوران.
حالات يجب اختبارها
- قائمة فارغة (لا قسمة على صفر في المتوسط).
- درجة خارج المدى.
- إدخال حروف بدل الدرجة.
أفكار للتوسعة
- عدة مواد لكل طالب (vector<int> scores داخل struct).
- البحث عن طالب بالاسم.
- حفظ البيانات في ملف (ستتعلم fstream في الدورة المتقدمة).
بعد هذه الدورة
الدورة التالية "المؤشرات وإدارة الذاكرة" تشرح كيف تعمل الذاكرة فعلاً، وهي المهارة التي تميّز C++ عن معظم اللغات.
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct Student {
string name;
int score;
};
string letterGrade(int score) {
if (score >= 90) return "Excellent";
if (score >= 75) return "Very good";
if (score >= 50) return "Pass";
return "Fail";
}
void printTable(const vector<Student>& students) {
cout << left << setw(10) << "Name" << setw(7) << "Score" << "Grade" << endl;
for (const Student& s : students) {
cout << left << setw(10) << s.name << setw(7) << s.score << letterGrade(s.score) << endl;
}
}
void printStats(const vector<Student>& students) {
if (students.empty()) {
cout << "No students yet" << endl;
return;
}
int total = 0, passed = 0;
int best = students[0].score, worst = students[0].score;
for (const Student& s : students) {
total += s.score;
if (s.score >= 50) passed++;
best = max(best, s.score);
worst = min(worst, s.score);
}
cout << fixed << setprecision(1)
<< "Average: " << static_cast<double>(total) / students.size()
<< " | Best: " << best << " | Worst: " << worst
<< " | Passed: " << passed << "/" << students.size() << endl;
}
// تملأ student وترجع false إذا فشل الإدخال
bool readStudent(Student& student) {
cout << "Name and score (e.g. Sara 82): ";
if (!(cin >> student.name >> student.score)) return false;
if (student.score < 0 || student.score > 100) {
cout << "Score must be 0-100, skipped" << endl;
student.score = -1;
}
return true;
}
int main() {
vector<Student> students = {{"Mona", 95}, {"Ali", 47}, {"Zaid", 81}};
Student s;
for (int i = 0; i < 2 && readStudent(s); i++) {
if (s.score >= 0) students.push_back(s);
}
printTable(students);
printStats(students);
vector<Student> ranked = students;
sort(ranked.begin(), ranked.end(), [](const Student& a, const Student& b) {
return a.score > b.score;
});
cout << "\nRanking:" << endl;
for (size_t i = 0; i < ranked.size(); i++) {
cout << i + 1 << ". " << ranked[i].name << " (" << ranked[i].score << ")" << endl;
}
return 0;
}
اختبر فهمك