C++: أساسيات البنى

آخر تحديث: 2026-08-26

يمكن للمصفوفات تخزين قيم متعددة من نوع واحد، لكن ماذا لو احتجت إلى تخزين اسم الطالب (نص)، العمر (عدد صحيح)، الدرجة (عدد عشري)؟

هنا تأتي البنى — التي تجمع متغيرات متعددة من أنواع مختلفة في وحدة واحدة.


1. ما هي البنية؟

(1) 1.1 البنى في الحياة اليومية

مثال من الحياة اليومية المكافئ البرمجي
بطاقة عمل (الاسم، الهاتف، البريد الإلكتروني) بنية
كتاب (العنوان، المؤلف، السعر) بنية
طالب (الاسم، العمر، الدرجة) بنية

خصائص البنى:

  1. يمكن أن يكون للأعضاء أنواع مختلفة
  2. ذاكرة متجاورة (مثل المصفوفات)
  3. مقدمة للفئات (ستتعلم الفئات لاحقاً)

(2) 1.2 لماذا نحتاج البنى؟

بدون البنى (ممل):

▶ مثال 2: مثال برمجي (الصعوبة ⭐)

TEXT 📖 للعرض فقط
#include <iostream>
#include <string>

int main() {
 std::string name1 = "Alice";
 int age1 = 20;
 double score1 = 92.5;
 
 std::string name2 = "Bob";
 int age2 = 21;
 double score2 = 88.0;
 // ... ستحتاج إلى تعريف 3 × 100 متغير!
 
 return 0;
}

الخرج:

TEXT 📖 للعرض فقط
(program output)

مع البنى (موجز):

CPP
#include <iostream>
#include <string>

struct Student {
 std::string name;
 int age;
 double score;
};

int main() {
 Student s1 = {"Alice", 20, 92.5};
 Student s2 = {"Bob", 21, 88.0};
 // ... أنظف بكثير!
 
 return 0;
}


2. تعريف البنية والإعلان عنها

(1) 2.1 الإعلان عن بنية

الصياغة:

TEXT 📖 للعرض فقط
struct StructName {
 memberType1 memberName1;
 memberType2 memberName2;
 ...
};

مثال:

TEXT 📖 للعرض فقط
#include <iostream>
#include <string>

// الإعلان عن بنية
struct Student {
 std::string name;
 int age;
 double score;
}; // ⚠️ ملاحظة: الفاصلة المنقوطة مطلوبة!

int main() {
 // ...
 return 0;
}

💡 نقطة مهمة: ينتهي إعلان البنية بـ فاصلة منقوطة! هذا خطأ شائع بين المبتدئين.



3. إنشاء وتهيئة متغيرات البنية

(1) 3.1 إنشاء متغير بنية

CPP
Student s1; // إنشاء متغير s1 من نوع Student

(2) 3.2 تهيئة متغير بنية

الطريقة 1: التهيئة بترتيب الإعلان

TEXT 📖 للعرض فقط
Student s1 = {"Alice", 20, 92.5};

الطريقة 2: تهيئة الأعضاء المعينة (C++20، موصى بها)

CPP
Student s1 = {.name = "Alice", .age = 20, .score = 92.5};

الطريقة 3: تعيين القيم بشكل فردي

TEXT 📖 للعرض فقط
Student s1;
s1.name = "Alice";
s1.age = 20;
s1.score = 92.5;

💡 نصيحة: يُنصح بالطريقة 1 أو الطريقة 2 للإيجاز.



4. الوصول إلى أعضاء البنية

(1) 4.1 قراءة الأعضاء

الصياغة:

TEXT 📖 للعرض فقط
structName.memberName

مثال:

CPP
#include <iostream>
#include <string>

struct Student {
 std::string name;
 int age;
 double score;
};

int main() {
 Student s1 = {"Alice", 20, 92.5};
 
 std::cout << "Name: " << s1.name << std::endl; // Alice
 std::cout << "Age: " << s1.age << std::endl; // 20
 std::cout << "Score: " << s1.score << std::endl; // 92.5
 
 return 0;
}

(2) 4.2 تعديل الأعضاء

TEXT 📖 للعرض فقط
Student s1 = {"Alice", 20, 92.5};
s1.score = 95.0; // تعديل الدرجة
std::cout << "New score: " << s1.score << std::endl; // 95.0


5. تمرير البنى كمعاملات دالة

(1) 5.1 التمرير بالقيمة (غير موصى به)

CPP
void printStudent(Student s) { // ❌ تمرير بالقيمة: ينسخ البنية بالكامل، مكلف
 std::cout << "Name: " << s.name << std::endl;
}

(2) 5.2 التمرير بالمرجع (موصى به)

TEXT 📖 للعرض فقط
void printStudent(const Student& s) { // ✅ تمرير بالمرجع: لا نسخ، ولا يمكن التعديل
 std::cout << "Name: " << s.name << std::endl;
 std::cout << "Age: " << s.age << std::endl;
 std::cout << "Score: " << s.score << std::endl;
}

💡 القاعدة الذهبية: عند تمرير بنية كمعامل، يُفضّل المرجع const — فهو يتجنب تكلفة النسخ ويمنع التعديل العرضي.



6. مصفوفات البنى

يمكن أيضاً تنظيم البنى في مصفوفات!

مثال: مصفوفة الطلاب (الصعوبة ⭐⭐)

CPP
#include <iostream>
#include <string>

struct Student {
 std::string name;
 int age;
 double score;
};

int main() {
 Student students[3] = {
 {"Alice", 20, 92.5},
 {"Bob", 21, 88.0},
 {"Charlie", 19, 95.0}
 };
 
 // المرور على مصفوفة البنى
 for (int i = 0; i < 3; i++) {
 std::cout << "========== Student " << i + 1 << " ==========" << std::endl;
 std::cout << "Name: " << students[i].name << std::endl;
 std::cout << "Age: " << students[i].age << std::endl;
 std::cout << "Score: " << students[i].score << std::endl;
 std::cout << std::endl;
 }
 
 return 0;
}


7. تطبيق: إدارة درجات الطلاب (نسخة البنى)

▶ مثال 1: إدارة درجات الطلاب الكاملة (الصعوبة ⭐⭐⭐)

TEXT 📖 للعرض فقط
#include <iostream>
#include <string>
#include <vector> // سنتعلم vector لاحقاً، نستخدم المصفوفة حالياً

struct Student {
 std::string name;
 int age;
 double score;
};

// إعلان الدوال
void addStudent(Student students, int& count);
void printStudents(const Student students, int count);
double calculateAverage(const Student students, int count);

int main() {
 const int MAX_STUDENTS = 100;
 Student students[MAX_STUDENTS];
 int count = 0;
 
 int choice;
 do {
 std::cout << "========== Student Score Management ==========" << std::endl;
 std::cout << "1. Add student" << std::endl;
 std::cout << "2. Display all students" << std::endl;
 std::cout << "3. CalculateAverage" << std::endl;
 std::cout << "4. Exit" << std::endl;
 std::cout << "Please select (1-4): ";
 std::cin >> choice;
 
 if (choice == 1) {
 addStudent(students, count);
 } else if (choice == 2) {
 printStudents(students, count);
 } else if (choice == 3) {
 if (count == 0) {
 std::cout << "No student data!" << std::endl;
 } else {
 std::cout << "Average: " << calculateAverage(students, count) << std::endl;
 }
 } else if (choice == 4) {
 std::cout << "Goodbye!" << std::endl;
 } else {
 std::cout << "Error: Please enter 1-4 a number between 1-4!" << std::endl;
 }
 
 std::cout << std::endl;
 
 } while (choice != 4);
 
 return 0;
}

// تعريف الدوال
void addStudent(Student students, int& count) {
 if (count >= 100) {
 std::cout << "Maximum number of students reached!" << std::endl;
 return;
 }
 
 std::cout << "Please enter your name: ";
 std::cin.ignore();
 std::getline(std::cin, students[count].name);
 
 std::cout << "Please enter your age: ";
 std::cin >> students[count].age;
 
 std::cout << "Please enter score: ";
 std::cin >> students[count].score;
 
 count++;
 std::cout << "Added successfully!" << std::endl;
}

void printStudents(const Student students, int count) {
 if (count == 0) {
 std::cout << "No student data!" << std::endl;
 return;
 }
 
 std::cout << "\n========== Student List ==========" << std::endl;
 for (int i = 0; i < count; i++) {
 std::cout << i + 1 << ". Name: " << students[i].name 
 << ",Age: " << students[i].age 
 << ",Score: " << students[i].score << std::endl;
 }
 std::cout << "================================\n\n";
}

double calculateAverage(const Student students, int count) {
 if (count == 0) {
 return 0.0;
 }
 
 double sum = 0.0;
 for (int i = 0; i < count; i++) {
 sum += students[i].score;
 }
 
 return sum / count;
}

الخرج:

TEXT 📖 للعرض فقط
========== Student Score Management ==========
1. Add student
2. Display all students
3. CalculateAverage
4. Exit
Please select (1-4): 
No student data!
Average: 
Goodbye!
Error: Please enter 1-4 a number between 1-4!
Maximum number of students reached!
Please enter your name: 
Please enter your age: 
Please enter score: 
Added successfully!
No student data!

========== Student List ==========
. Name: 
==============================



▶ مثال 3: البنية كقيمة إرجاع لدالة (الصعوبة ⭐)

CPP
#include <iostream>
#include <string>

struct Student {
    std::string name;
    int age;
    double score;
};

// دالة تُرجع بنية
Student createStudent(std::string n, int a, double s) {
    Student stu;
    stu.name = n;
    stu.age = a;
    stu.score = s;
    return stu;
}

int main() {
    Student s1 = createStudent("Zhang San", 20, 92.5);
    
    std::cout << "Name: " << s1.name << std::endl;
    std::cout << "Age: " << s1.age << std::endl;
    std::cout << "Score: " << s1.score << std::endl;
    
    return 0;
}
▶ جرّب الكود

الخرج:

TEXT 📖 للعرض فقط
Name: 
Age: 
Score: 
💡 نصيحة: يمكن استخدام البنى كقيم إرجاع لدالات لإنشاء وتهيئة كائنات البنى.


8. الأخطاء الشائعة

(1) 8.1 نسيان الفاصلة المنقوطة

مثال خاطئ:

TEXT 📖 للعرض فقط
struct Student { // ❌ نسيت الفاصلة المنقوطة
 std::string name;
 int age;
 } // ❌ يجب أن تكون فاصلة منقوطة هنا

int main() {
 // ...
}

رسالة خطأ المترجم:

TEXT 📖 للعرض فقط
error: expected ';' after struct definition

(2) 8.2 الوصول إلى عضو غير موجود

مثال خاطئ:

CPP
struct Student {
 std::string name;
 int age;
};

int main() {
 Student s1;
 s1.score = 92.5; // ❌ خطأ: Student لا يملك عضو score
 return 0;
}

❓ أسئلة شائعة

س ما الفرق بين البنية والفئة؟
ج سنتناول الفئات بالتفصيل لاحقاً، لكن باختصار: > - يحتوي struct على وصول افتراضي public > - يحتوي class على وصول افتراضي private

س: ما أهم شيء في أساسيات البنى؟ ج: افهم المفاهيم الأساسية أولاً، ثم عززها من خلال أمثلة التطبيق.

📖 ملخص


📝 تمارين

  1. أساسي (الصعوبة ⭐): عرّف بنية Book بثلاثة أعضاء: العنوان، المؤلف، والسعر. أنشئ متغيرين Book وأخرجهما.

  2. متوسط (الصعوبة ⭐⭐): عرّف بنية Rectangle بعضوين: العرض والارتفاع.

  3. اكتب دالة double calculateArea(const Rectangle& r) لحساب المساحة

  4. اكتب دالة double calculatePerimeter(const Rectangle& r) لحساب المحيط

  5. اختبر في main

  6. متقدم (الصعوبة ⭐⭐⭐): عرّف بنية Date (السنة، الشهر، اليوم)، واكتب دالة للتحقق مما إذا كان التاريخ صالحاً (مثلاً 2024-02-29 صالح، 2023-02-29 غير صالح).


9. 🚀 الخطوات التالية

الآن بعد أن تعلمت البنى، لننتقل إلى المرحلة 4 (المؤشرات والمراجع) — الجزء الأصعب والأهم في C++، لكن إتقانه سيتيح لك كتابة كود أكثر كفاءة!

Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%