الـ Range-Based For Loop
جزء من قسم Logic & Flow في رحلة C++ على Coddy — الدرس 15 من 56.
بينما تعمل حلقات for التقليدية باستخدام الفهارس بشكل جيد للتكرار عبر المتجهات (vectors)، تقدم لغة C++ حلاً أكثر أناقة: حلقة for المبنية على النطاق (range-based for loop). يلغي هذا النحو البرمجي الحديث الحاجة إلى إدارة الفهارس يدوياً ويجعل الكود الخاص بك أكثر نظافة وأسهل في القراءة.
تتعامل حلقة for المبنية على النطاق (range-based for loop) مع تفاصيل التكرار تلقائيًا نيابةً عنك. بدلاً من إدارة متغير الفهرس (index variable)، يمكنك ببساطة تحديد ما تريد القيام به مع كل عنصر:
std::vector<std::string> names = {"Alice", "Bob", "Charlie"};
for (const std::string& name : names) {
std::cout << name << std::endl;
}تقوم هذه الحلقة بنفس ما يفعله النهج التقليدي القائم على الفهرس تماماً، ولكن بصيغة برمجية أبسط بكثير. يأخذ المتغير name تلقائياً قيمة كل عنصر في المتجه، واحداً تلو الآخر.
قد تلاحظ الرمز & في إعلان الحلقة — const std::string& name. في هذا السياق، & لا يعني "عنوان" (address of) كما قد تكون رأيت من قبل. هنا يقوم بالإعلان عن name كـ مرجع (reference) (اسم مستعار) مباشرة لكل عنصر في الـ vector، بدلاً من إنشاء نسخة منه. فكر في الأمر كإعطاء اسم جديد لنفس قطعة البيانات — على غرار استخدام مؤشر (pointer) للعنصر، ولكن دون الحاجة إلى إلغاء المرجعية (dereference) داخل جسم الحلقة.
تُعد الكلمة المفتاحية const إجراءً وقائيًا: فهي تمنعك من تعديل العنصر عن طريق الخطأ من خلال الاسم المستعار (alias) داخل جسم الحلقة. الاسم المستعار نفسه لا يزال ينتقل إلى كل عنصر جديد مع كل تكرار — إن المحتوى الذي تصل إليه من خلال الاسم المستعار هو الذي يبقى ثابتًا، وليس تقدم الحلقة.
إن حلقة for المبنية على النطاق (range-based for loop) ليست فقط أكثر قابلية للقراءة ولكنها أيضًا أكثر أمانًا - فلا يوجد خطر من حدوث أخطاء في الفهرسة (index errors) لأنك لا تقوم بإدارة الفهارس يدويًا. وهي تعمل مع أي حاوية (container) تدعم التكرار (iteration)، مما يجعلها أداة متعددة الاستخدامات لمعالجة مجموعات البيانات في لغة C++.
التحدي
سهلقم بإنشاء برنامج يوضح حلقة for المبنية على النطاق (range-based for loop) من خلال معالجة مجموعة من أسماء المدن وعرضها مع عدد أحرفها.
سيتم توفير المدخلات التالية:
- عدد صحيح
nيمثل عدد المدن - ثم
nمن السلاسل النصية (strings) التي تمثل أسماء المدن
يجب على برنامجك القيام بما يلي:
- إنشاء
std::vector<std::string>باسمcities - استخدام
push_back()لإضافة كل اسم من أسماء المدن الـnإلى المتجه (vector) - استخدام حلقة for مبنية على النطاق للتكرار عبر المتجه
- لكل مدينة في الحلقة، اطبع اسم المدينة متبوعاً بطولها باستخدام طريقة
.length() - بعد الحلقة، اطبع العدد الإجمالي للمدن التي تمت معالجتها باستخدام طريقة
.size()الخاصة بالمتجه
استخدم تنسيق المخرجات الدقيق التالي:
City: [city name] (Length: [number of characters])\nCity: [city name] (Length: [number of characters])\n...\nTotal cities processed: [total count]يجب أن تستخدم حلقة for المبنية على النطاق الصيغة for (const std::string& city : cities) للتكرار عبر كل عنصر في المتجه. استخدم city.length() للحصول على عدد الأحرف في اسم كل مدينة.
جرّب بنفسك
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
// قراءة عدد المدن
int n;
cin >> n;
// إنشاء متجه (vector) لتخزين أسماء المدن
vector<string> cities;
// قراءة أسماء المدن وإضافتها إلى المتجه
for (int i = 0; i < n; i++) {
string city;
cin >> city;
cities.push_back(city);
}
// TODO: اكتب كودك أدناه
// استخدم حلقة for المبنية على النطاق (range-based) للمرور عبر متجه المدن
// اطبع كل مدينة مع طولها باستخدام التنسيق المحدد
// بعد الحلقة، اطبع إجمالي عدد المدن التي تمت معالجتها
return 0;
}يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Logic & Flow
1المؤشرات والذاكرة
ما هو المؤشر؟معامل العنوان (Address-Of)معامل الوصول للقيمة (Dereference)المؤشرات الفارغة (Null Pointers)المؤشرات والمصفوفاتالذاكرة الديناميكية باستخدام 'new'تحرير الذاكرة باستخدام 'delete'مراجعة - تمارين على المؤشرات2المتجهات (المصفوفات الديناميكية)
مقدمة إلى std::vectorإنشاء Vectorإضافة العناصرالوصول إلى العناصرحجم الـ Vectorالتكرار باستخدام For Loopالـ Range-Based For Loopإزالة العناصرملخص - عمليات الـ Vector