Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

الارتباطات المهيكلة

جزء من قسم Object Oriented Programming في رحلة C++ على Coddy — الدرس 88 من 104.

تسمح لك الارتباطات المهيكلة (Structured bindings)، التي تم تقديمها في C++17، بتفكيك قيم متعددة من المصفوفات (arrays)، أو الأزواج (pairs)، أو الصفوف (tuples)، أو الهياكل (structs) إلى متغيرات مسماة فردية في تصريح واحد. وهذا يجعل الكود أكثر نظافة وقابلية للقراءة عند التعامل مع البيانات المركبة.

يستخدم بناء الجملة auto مع أقواس مربعة تحتوي على أسماء المتغيرات الجديدة:

#include <iostream>
#include <map>
#include <tuple>

int main() {
    // فك حزمة زوج (pair)
    std::pair<std::string, int> person{"Alice", 25};
    auto [name, age] = person;
    std::cout << name << " is " << age << "\n";
    
    // فك حزمة صف (tuple)
    std::tuple<int, double, char> data{42, 3.14, 'X'};
    auto [num, pi, letter] = data;
    
    // فك الحزم في حلقات for المبنية على النطاق
    std::map<std::string, int> scores{{"Bob", 90}, {"Carol", 85}};
    for (const auto& [student, score] : scores) {
        std::cout << student << ": " << score << "\n";
    }
}

تعمل الارتباطات المهيكلة (Structured bindings) أيضاً مع المصفوفات والبنيات المخصصة (custom structs) التي تحتوي على أعضاء عامة:

struct Point {
    double x;
    double y;
};

Point getOrigin() { return {0.0, 0.0}; }

int main() {
    auto [x, y] = getOrigin();
    
    int arr[3] = {1, 2, 3};
    auto [a, b, c] = arr;
}

يمكنك استخدام auto& أو const auto& للربط بالمرجع، مما يتجنب عمليات النسخ ويسمح بتعديل القيم الأصلية عند الحاجة. هذه الميزة مفيدة بشكل خاص عند التكرار عبر حاويات STL أو التعامل مع الدوال التي تُرجع قيمًا متعددة.

challenge icon

التحدي

سهل

لنقم ببناء محلل لدرجات الطلاب يستعرض قوة الربط الهيكلي (structured bindings). ستقوم بإنشاء نظام يعالج سجلات الطلاب وبيانات الدورات التدريبية، باستخدام الربط الهيكلي لفك حزم الأزواج (pairs)، والصفوف (tuples)، والهياكل (structs) بأناقة في جميع أنحاء الكود الخاص بك.

ستقوم بتنظيم الكود الخاص بك عبر ثلاثة ملفات:

  • Student.h: قم بتعريف هيكل Student مع أعضاء عامة لاسم الطالب (std::string)، والمعرف (int)، والمعدل التراكمي (double). قم أيضًا بإنشاء دالة تسمى createStudent تأخذ الاسم، والمعرف، والمعدل التراكمي، وتعيد هيكل Student.
  • GradeUtils.h: قم بإنشاء دوال مساعدة لمعالجة الدرجات.

    قم بتعريف دالة getGradeInfo تأخذ درجة رقمية (عدد صحيح) وتعيد std::tuple يحتوي على ثلاث قيم: التقدير الحرفي (std::string)، ونقاط التقدير (double)، وما إذا كانت درجة نجاح (bool). استخدم مقياس الدرجات هذا:

    • 90+ : "A", 4.0, true
    • 80-89: "B", 3.0, true
    • 70-79: "C", 2.0, true
    • 60-69: "D", 1.0, true
    • أقل من 60: "F", 0.0, false

    قم أيضًا بتعريف دالة makeScorePair تأخذ اسم الدورة (std::string) والدرجة (int)، وتعيد std::pair من تلك القيم.

  • main.cpp: اقرأ أربعة مدخلات:
    1. اسم الطالب (string)
    2. معرف الطالب (integer)
    3. اسم الدورة (string)
    4. الدرجة (integer)

    استخدم الربط الهيكلي في جميع أنحاء دالتك الرئيسية:

    1. استدعِ createStudent بالاسم، والمعرف، ومعدل تراكمي مؤقت قيمته 0.0. استخدم الربط الهيكلي لفك الهيكل المعاد إلى متغيرات فردية، ثم اطبع: Student: [name] (ID: [id])
    2. استدعِ makeScorePair باسم الدورة والدرجة. استخدم الربط الهيكلي لفك الزوج، ثم اطبع: Course: [course], Score: [score]
    3. استدعِ getGradeInfo بالدرجة. استخدم الربط الهيكلي لفك جميع عناصر الصف الثلاثة، ثم اطبع:
      Grade: [letter]
      Points: [points]
      Passing: [yes/no]
      (اطبع "yes" إذا كان النجاح true، و "no" إذا كان false)

على سبيل المثال، مع المدخلات Alice، و 1001، و Math، و 85:

Student: Alice (ID: 1001)
Course: Math, Score: 85
Grade: B
Points: 3
Passing: yes

مع المدخلات Bob، و 2002، و Physics، و 55:

Student: Bob (ID: 2002)
Course: Physics, Score: 55
Grade: F
Points: 0
Passing: no

تذكر تضمين <tuple> و <utility> حيثما لزم الأمر. الفكرة الأساسية هي كيف يسمح لك الربط الهيكلي بفك الأنواع المركبة — الأزواج، والصفوف، والهياكل — إلى متغيرات مسماة في إعلان واحد مقروء.

ورقة مرجعية

تسمح الروابط المهيكلة (Structured bindings) في (C++17) بتفكيك قيم متعددة من المصفوفات، أو الأزواج (pairs)، أو المجموعات (tuples)، أو الهياكل (structs) إلى متغيرات مسماة فردية في تصريح واحد.

يستخدم بناء الجملة الأساسي auto مع الأقواس المربعة:

auto [var1, var2, ...] = composite_object;

تفكيك std::pair:

std::pair<std::string, int> person{"Alice", 25};
auto [name, age] = person;

تفكيك std::tuple:

std::tuple<int, double, char> data{42, 3.14, 'X'};
auto [num, pi, letter] = data;

استخدام الروابط المهيكلة في حلقات for المبنية على النطاق (range-based for loops) مع الحاويات مثل std::map:

std::map<std::string, int> scores{{"Bob", 90}, {"Carol", 85}};
for (const auto& [student, score] : scores) {
    std::cout << student << ": " << score << "\n";
}

تفكيك الهياكل (structs) ذات الأعضاء العامة (public members):

struct Point {
    double x;
    double y;
};

Point getOrigin() { return {0.0, 0.0}; }

auto [x, y] = getOrigin();

تفكيك المصفوفات (arrays):

int arr[3] = {1, 2, 3};
auto [a, b, c] = arr;

استخدم auto& أو const auto& للربط عن طريق المرجع (reference)، مما يتجنب النسخ ويسمح بتعديل القيم الأصلية:

auto& [x, y] = point;  // يمكن تعديل الأصل
const auto& [name, age] = person;  // مرجع للقراءة فقط

جرّب بنفسك

#include <iostream>
#include <string>
#include "Student.h"
#include "GradeUtils.h"

int main() {
    // قراءة المدخلات
    std::string studentName;
    int studentId;
    std::string courseName;
    int score;
    
    std::cin >> studentName;
    std::cin >> studentId;
    std::cin >> courseName;
    std::cin >> score;
    
    // TODO: استدعِ createStudent مع name و id و GPA مؤقت بقيمة 0.0
    // استخدم structured bindings لفك الهيكل (struct): auto [name, id, gpa] = ...
    // طباعة: Student: [name] (ID: [id])
    
    
    // TODO: استدعِ makeScorePair مع course name و score
    // استخدم structured bindings لفك الزوج (pair): auto [course, sc] = ...
    // طباعة: Course: [course], Score: [score]
    
    
    // TODO: استدعِ getGradeInfo مع score
    // استخدم structured bindings لفك الصف (tuple): auto [letter, points, passing] = ...
    // طباعة:
    // Grade: [letter]
    // Points: [points]
    // Passing: [yes/no] (اطبع "yes" إذا كان passing هو true، و "no" إذا كان false)
    
    
    return 0;
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming