البرمجة

المكررات في C++: دليل شامل

المكررات (Iterators) في C++

تُعد المكررات (Iterators) من المفاهيم الأساسية في لغة البرمجة C++، حيث تلعب دورًا مهمًا في تسهيل عمليات التنقل بين عناصر الحاويات المختلفة مثل القوائم والمصفوفات والخرائط. وعلى الرغم من أن المفهوم قد يبدو معقدًا في البداية، إلا أنه أحد الأدوات الأساسية التي يجب على كل مبرمج C++ إتقانها لفهم كيفية التعامل مع البيانات في الحاويات المختلفة بشكل مرن وفعال.

المكررات هي عبارة عن كائنات تُستخدم للإشارة إلى موقع معين داخل حاوية (container)، مثل مصفوفة أو قائمة أو خريطة، وتسمح بالتنقل عبر هذه الحاويات بطريقة مشابهة للمؤشرات (pointers). من خلال المكررات، يمكن للمطورين الوصول إلى عناصر الحاويات بشكل متسلسل دون الحاجة إلى معرفة تفاصيل التنفيذ الداخلية لتلك الحاويات.

1. تعريف المكررات (Iterators)

المكرر هو كائن يُستخدم للإشارة إلى عناصر الحاوية. يشبه في عمله المؤشر في C، ولكنه يوفر واجهات أكثر مرونة للعمل مع الحاويات. يتم استخدام المكررات للوصول إلى العناصر وتعديلها أو التعامل معها بطرق أخرى، مثل التكرار أو البحث.

المكررات توفر نوعًا من التجريد، حيث تُمكن المبرمج من العمل مع الحاويات المختلفة (قوائم، مجموعات، خرائط، إلخ) بنفس الطريقة، دون الحاجة إلى معرفة التفاصيل الخاصة بكل حاوية على حدة.

2. أنواع المكررات في C++

في C++، هناك عدة أنواع من المكررات يتم تصنيفها بناءً على الطريقة التي يمكن بها الوصول إلى العناصر. تتنوع هذه الأنواع لتناسب احتياجات مختلفة في البرمجة:

1. المكررات العشوائية (Random Access Iterators)

تتيح هذه المكررات الوصول إلى أي عنصر في الحاوية بشكل مباشر من خلال الإزاحة (offset) كما في المصفوفات العادية. هذا يعني أنه يمكن استخدام العمليات مثل الجمع والطرح على المكرر لتحريك المكرر للأمام أو للخلف عبر الحاوية. تُستخدم هذه المكررات بشكل رئيسي في الحاويات مثل المصفوفات (arrays) و vector.

العمليات المدعومة:

  • التنقل للأمام والخلف

  • المقارنة بين المكررات

  • الوصول إلى العناصر عبر الفهرس

2. المكررات الأحادية الاتجاه (Forward Iterators)

هذه المكررات تسمح بالتحرك للأمام فقط عبر الحاوية. يمكن استخدامها فقط للوصول إلى العنصر التالي، ولا يمكن العودة إلى العناصر السابقة. تُستخدم المكررات الأحادية الاتجاه في الحاويات التي توفر وصولًا أحادي الاتجاه مثل list في C++.

العمليات المدعومة:

  • التنقل للأمام

  • التكرار من العنصر الأول إلى الأخير

3. المكررات الثنائية الاتجاه (Bidirectional Iterators)

المكررات الثنائية الاتجاه تسمح بالتنقل للأمام والخلف داخل الحاوية. يمكن استخدامها للوصول إلى العناصر سواء للأمام أو للخلف، مما يجعلها أكثر مرونة من المكررات الأحادية الاتجاه. يتم استخدامها في الحاويات مثل list، حيث يكون من الضروري التنقل عبر العناصر في كلا الاتجاهين.

العمليات المدعومة:

  • التنقل للأمام والخلف

  • التكرار من العنصر الأول إلى الأخير، والعكس

4. المكررات فقط للقراءة (Const Iterators)

المكررات التي يمكن استخدامها للقراءة فقط. لا يمكن تعديل العناصر عبر هذه المكررات، ولكن يمكن استخدامها للتنقل عبر الحاوية وقراءة العناصر. تُستخدم هذه المكررات عندما يرغب المطور في ضمان عدم تعديل البيانات أثناء التكرار عليها.

العمليات المدعومة:

  • التنقل للأمام والخلف

  • الوصول إلى العناصر للقراءة فقط

3. كيفية استخدام المكررات في C++

تُستخدم المكررات بشكل أساسي من خلال الحاويات مثل vector، list، map، وغيرها. يمكننا توضيح كيفية استخدام المكررات من خلال بعض الأمثلة البسيطة.

مثال 1: استخدام المكرر مع vector

cpp
#include #include int main() { std::vector<int> vec = {10, 20, 30, 40, 50}; // مكرر يشير إلى أول عنصر في الـ vector std::vector<int>::iterator it = vec.begin(); // التكرار عبر العناصر while (it != vec.end()) { std::cout << *it << " "; // طباعة العنصر المشار إليه ++it; // الانتقال إلى العنصر التالي } return 0; }

في المثال السابق، استخدمنا مكررًا للتنقل عبر عناصر الـ vector وطباعتها. المكرر يبدأ من begin() ويستمر حتى يصل إلى end()، الذي يشير إلى موقع بعد آخر عنصر في الحاوية.

مثال 2: استخدام المكرر مع list

cpp
#include #include int main() { std::list<int> lst = {1, 2, 3, 4, 5}; // مكرر يشير إلى أول عنصر في الـ list std::list<int>::iterator it = lst.begin(); // التكرار عبر العناصر while (it != lst.end()) { std::cout << *it << " "; // طباعة العنصر المشار إليه ++it; // الانتقال إلى العنصر التالي } return 0; }

في هذا المثال، تم استخدام المكرر في list للتنقل عبر العناصر، ووجدنا أن العمليات مشابهة لاستخدام المكررات مع vector، ولكن مع حاويات مختلفة.

4. استخدام المكررات في الحاويات المتقدمة

1. المكررات في map و unordered_map

المكررات في الحاويات مثل map و unordered_map تسمح بالتنقل بين الأزواج (key, value). يتم استخدام هذه المكررات بشكل شائع للوصول إلى المفاتيح والقيم في الحاوية.

cpp
#include #include int main() { std::map<int, std::string> map = {{1, "one"}, {2, "two"}, {3, "three"}}; // مكرر يشير إلى أول عنصر في الـ map std::map<int, std::string>::iterator it = map.begin(); // التكرار عبر الأزواج (key, value) while (it != map.end()) { std::cout << it->first << ": " << it->second << std::endl; ++it; } return 0; }

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

من المهم أن نميز بين المكررات القابلة للتعديل (modifiable iterators) والمكررات الثابتة (const iterators). في المكررات القابلة للتعديل، يمكن للمطورين تعديل العناصر التي يشيرون إليها، بينما في المكررات الثابتة لا يمكن تعديل العناصر ولكن يمكن قراءتها فقط. يتم استخدام المكررات الثابتة لضمان عدم التلاعب بالبيانات بشكل غير مقصود أثناء التكرار عبر الحاويات.

6. الخاتمة

المكررات هي من الأدوات الأساسية في C++ التي تتيح للمطورين التنقل بسهولة بين عناصر الحاويات المختلفة، سواء كانت قوائم أو مصفوفات أو خرائط. من خلال استخدام المكررات، يمكن التعامل مع هذه الحاويات بطرق مرنة وفعالة دون الحاجة إلى معرفة التفاصيل الداخلية لكيفية تخزين هذه العناصر. إن فهم كيفية استخدام المكررات بشكل صحيح يعزز من قدرة المطور على بناء برامج أكثر كفاءة وتنظيمًا.