تخطَّ إلى المحتوى

المصفوفات و vector في C++‎

الدرس 6 من 11 · C++

في C تعلمت المصفوفات التقليدية: ثابتة الحجم، ولا تعرف حجمها، ولا تحميك من تجاوز حدودها. C++‎ تحتفظ بها، لكنها تقدم بديلاً أذكى بكثير يستخدمه المبرمجون في الأغلبية العظمى من الحالات: vector. في هذا الدرس ستتعرف على الاثنين، ومعهما أدوات جاهزة للترتيب والبحث والجمع.

int scores[4] = {85, 92, 78, 64};
cout << scores[0] << endl;
cout << size(scores) << endl;
الناتج
85
4

نفس المصفوفة التي عرفتها في C: الترقيم من صفر، والحجم ثابت. و size() (من C++17) تعطيك عدد العناصر بسهولة بدلاً من حيلة sizeof.

#include <vector>
vector<int> marks = {85, 92, 78};
marks.push_back(64);
marks[1] = 95;
cout << marks.size() << endl;
for (int m : marks) cout << m << " ";
cout << endl;
الناتج
4
85 95 78 64
  • vector<int>: قائمة من الأعداد الصحيحة، ونوع العناصر بين < >.
  • push_back: إضافة عنصر في النهاية، فيكبر الـ vector تلقائياً.
  • size(): عدد العناصر.
  • [ ]: الوصول للعناصر كالمصفوفة تماماً.

تخيّل المصفوفة التقليدية مثل علبة بيض بعدد ثابت من الأماكن، و vector مثل حقيبة قابلة للتمدد: تكبر كلما أضفت إليها، وتدير مساحتها بنفسها.

marks.pop_back();
cout << marks.size() << " " << marks.back() << endl;
cout << marks.front() << endl;
الناتج
3 78
85
الدالة وظيفتها
push_back(x) إضافة في النهاية
pop_back() حذف آخر عنصر
front() و back() أول وآخر عنصر
size() و empty() العدد، وهل هو فارغ
erase(v.begin() + i) حذف العنصر رقم i
at(i) الوصول الآمن للعنصر
try {
cout << marks.at(10) << endl;
} catch (const out_of_range& e) {
cout << "خطأ: رقم خارج الحدود" << endl;
}
الناتج
خطأ: رقم خارج الحدود

مع [ ]، تجاوز الحدود سلوك غير محدد خطير كما في C. أما at() فتفحص الحدود، وترمي استثناءً يمكن التقاطه بـ try و catch. استخدمها عندما لا تكون متأكداً من الرقم، مثل رقم أدخله المستخدم.

C++‎ تأتي مع مكتبة ضخمة من الخوارزميات الجاهزة:

#include <algorithm>
#include <numeric>
vector<int> nums = {5, 3, 9, 1};
sort(nums.begin(), nums.end());
for (int x : nums) cout << x << " ";
cout << endl;
cout << accumulate(nums.begin(), nums.end(), 0) << endl;
cout << *max_element(nums.begin(), nums.end()) << endl;
الناتج
1 3 5 9
18
9
  • sort: ترتيب تصاعدي.
  • accumulate: المجموع، بدءاً من القيمة 0.
  • max_element: يُرجع مكان أكبر عنصر، والنجمة * تعطينا قيمته.
  • begin() و end() تحددان النطاق: من أول عنصر حتى ما بعد آخر عنصر. وهي طريقة المكتبة القياسية في التعامل مع أي مجموعة.

ومع الـ Lambda التي تعلمتها في الدرس السابق:

vector<int> grades = {85, 92, 78, 64, 50};
int passed = count_if(grades.begin(), grades.end(), [](int g) { return g >= 75; });
cout << passed << endl;
الناتج
3

count_if تعد العناصر التي تحقق شرطاً تعطيه لها كـ Lambda.

vector<vector<int>> grid = {{1, 2, 3}, {4, 5, 6}};
cout << grid[1][2] << endl;
for (const auto& row : grid) {
for (int v : row) cout << v << " ";
cout << endl;
}
الناتج
6
1 2 3
4 5 6

vector كل عنصر فيه vector: جدول بصفوف وأعمدة. و auto هنا توفر عليك كتابة النوع الطويل vector<int>.

array: الحجم الثابت الحديث

Section titled “array: الحجم الثابت الحديث”

إذا كان الحجم ثابتاً فعلاً ومعروفاً، هناك array من المكتبة القياسية:

#include <array>
array<int, 3> fixedArr = {7, 8, 9};
cout << fixedArr.size() << endl;
الناتج
3

مثل المصفوفة التقليدية في السرعة، لكنها تعرف حجمها، وتدعم at() وكل دوال algorithm.

  1. أنشئ vector<string> لقائمة مهام، أضف 4 مهام بـ push_back، واحذف الأولى بـ erase، واطبع الباقي.
  2. أنشئ vector بدرجات 6 طلاب، ورتبها، واطبع أعلى وأقل درجة والمتوسط.
  3. استخدم count_if لعد الدرجات الأقل من 50.
  4. تحدٍّ: اطلب من المستخدم أرقاماً بـ cin حتى يدخل صفراً، وخزنها في vector، ثم اطبع مجموعها مرتبة.
  • تجاوز الحدود بـ [ ]: لا تحذير ولا خطأ واضح. استخدم at() عند الشك.
  • نسيان #include: vector تحتاج <vector>، و sort تحتاج <algorithm>، و accumulate تحتاج <numeric>.
  • حذف عناصر أثناء المرور عليها بحلقة range-for: يسبب أخطاء خطيرة. اجمع ما تريد حذفه أولاً، أو استخدم دوال المكتبة المخصصة لذلك.

سؤال

ما الفرق بين v[10] و v.at(10) إذا كان الـ vector فيه 4 عناصر؟

سؤال

أي دالة تضيف عنصراً في نهاية vector؟

  • المصفوفة التقليدية ثابتة الحجم، و size() تعطي عدد عناصرها.
  • vector مصفوفة مرنة: push_back و pop_back و size و front و back.
  • at() للوصول الآمن مع فحص الحدود.
  • algorithm و numeric فيهما sort و accumulate و max_element و count_if.
  • vector<vector<int>> للجداول، و array للحجم الثابت الحديث.