C#: المصفوفات
1. إعلان وتهيئة المصفوفة أحادية البعد
المصفوفات في لغة C# هي أنواع مرجعية يتم تخزينها في الـ«هياب». يُعلن عن المصفوفة باستخدام النوع متبوعًا بأقواس مربعة، مع ترقيم الفهرس بدءًا من الصفر.
▶ مثال
int[] nums1 = new int[5];
int[] nums2 = new int[5] { 10, 20, 30, 40, 50 };
int[] nums3 = { 1, 2, 3, 4, 5 };
string[] names = { "Alice", "Bob", "Carol" };
Console.WriteLine(nums1[0]);
Console.WriteLine(nums2[2]);
Console.WriteLine(nums3.Length);
Console.WriteLine(names[1]);
0
30
5
Bob
تحذير: تقوم الدالة new int[5] بإنشاء مصفوفة يتم تهيئة عناصرها تلقائيًا بالقيم الافتراضية (0 لنوع int، وnull لنوع string).
2. الوصول إلى الفهرس والتحقق من الحدود
يتم الوصول إلى المصفوفات في لغة C# عن طريق الفهرس، ويقوم محرك التشغيل بفحص حدود المصفوفة. ويؤدي استخدام فهرس خارج النطاق إلى إثارة استثناء IndexOutOfRangeException، على عكس السلوك غير المحدد في لغة C.
▶ مثال
int[] nums = { 10, 20, 30, 40, 50 };
nums[0] = 99;
Console.WriteLine(nums[0]);
Console.WriteLine(nums[nums.Length - 1]);
try
{
int val = nums[5];
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("Index out of range!");
}
99
50
Index out of range!
نصيحة: استخدم الخاصية Length للحصول على طول المصفوفة، بدلاً من sizeof كما هو الحال في لغة C.
3. الطرق الشائعة لفئة المصفوفات
توفر فئة Array طرقًا ثابتة للفرز، والعكس، والبحث، والنسخ، وغيرها.
▶ مثال
int[] nums = { 5, 3, 8, 1, 9, 2 };
Array.Sort(nums);
Console.WriteLine(string.Join(", ", nums));
Array.Reverse(nums);
Console.WriteLine(string.Join(", ", nums));
int idx = Array.IndexOf(nums, 8);
Console.WriteLine(idx);
int[] copy = new int[3];
Array.Copy(nums, copy, 3);
Console.WriteLine(string.Join(", ", copy));
Array.Clear(nums, 0, 2);
Console.WriteLine(string.Join(", ", nums));
Array.Resize(ref nums, 8);
Console.WriteLine(nums.Length);
1, 2, 3, 5, 8, 9
9, 8, 5, 3, 2, 1
1
9, 8, 5
0, 0, 5, 3, 2, 1
8
نصيحة: تعمل Clear على إعادة تعيين العناصر الموجودة في النطاق المحدد إلى قيمها الافتراضية بدلاً من إزالتها. أما Resize فتعمل على تغيير طول المصفوفة.
4. المصفوفات متعددة الأبعاد (المصفوفات المستطيلة)
تتميز المصفوفات متعددة الأبعاد، التي تُعرف أيضًا بالمصفوفات المستطيلة، بأن كل صف فيها له نفس الطول. استخدم الفواصل لفصل الأبعاد في الإعلان، على سبيل المثال int[,] لمصفوفة ثنائية الأبعاد.
▶ مثال
int[,] matrix = new int[3, 4];
matrix[0, 0] = 1;
matrix[1, 2] = 5;
matrix[2, 3] = 9;
int[,] grid = {
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 }
};
Console.WriteLine(grid[0, 1]);
Console.WriteLine(grid[2, 0]);
Console.WriteLine(grid.Length);
Console.WriteLine(grid.Rank);
2
7
9
2
نصيحة: يُرجع Rank عدد الأبعاد، بينما يُرجع Length العدد الإجمالي للعناصر (حاصل ضرب جميع الأبعاد).
5. المصفوفات المتقطعة
المصفوفة المتقطعة هي مصفوفة من المصفوفات، حيث يمكن أن يكون لكل صف طول مختلف. يتم تعريفها باستخدام عدة مجموعات من الأقواس المربعة.
▶ مثال
int[][] jagged = new int[3][];
jagged[0] = new int[] { 1, 2 };
jagged[1] = new int[] { 3, 4, 5, 6 };
jagged[2] = new int[] { 7, 8, 9 };
Console.WriteLine(jagged[0].Length);
Console.WriteLine(jagged[1][2]);
Console.WriteLine(jagged[2][0]);
int[][] scores = {
new int[] { 90, 85 },
new int[] { 78, 92, 88 },
new int[] { 95 }
};
Console.WriteLine(scores[1][1]);
2
5
7
92
تحذير: تختلف المصفوفات غير المتجاورة عن المصفوفات المستطيلة: فـ int[,] هي مصفوفة ثنائية الأبعاد متجاورة في الذاكرة، بينما int[][] هي مصفوفة أحادية البعد تتكون عناصرها من مصفوفات مستقلة.
6. تكرار المصفوفات باستخدام foreach
يعمل البيان foreach على تبسيط عملية مسح المصفوفة من خلال التخلص من الحاجة إلى إدارة الفهارس يدويًّا. وهو مناسب للتكرار في وضع القراءة فقط.
▶ مثال
string[] fruits = { "Apple", "Banana", "Orange", "Grape" };
foreach (string fruit in fruits)
{
Console.WriteLine(fruit);
}
int[,] matrix = {
{ 1, 2, 3 },
{ 4, 5, 6 }
};
foreach (int val in matrix)
{
Console.Write(val + " ");
}
Console.WriteLine();
Apple
Banana
Orange
Grape
1 2 3 4 5 6
نصيحة: لا يمكنك تعديل عناصر المصفوفة داخل حلقة foreach. استخدم حلقة for إذا كنت بحاجة إلى تغيير القيم.
7. المصفوفات كمعلمات للطرق
المصفوفات هي أنواع مرجعية، لذا فإن تمرير مصفوفة إلى دالة يعني تمرير المرجع. وتؤثر التعديلات التي تُجرى على عناصر المصفوفة داخل الدالة على المصفوفة الأصلية.
▶ مثال
void PrintArray(int[] arr)
{
foreach (int n in arr)
{
Console.Write(n + " ");
}
Console.WriteLine();
}
void DoubleValues(int[] arr)
{
for (int i = 0; i < arr.Length; i++)
{
arr[i] *= 2;
}
}
int[] nums = { 1, 2, 3, 4, 5 };
PrintArray(nums);
DoubleValues(nums);
PrintArray(nums);
int Sum(int[] arr)
{
int total = 0;
foreach (int n in arr)
{
total += n;
}
return total;
}
Console.WriteLine(Sum(nums));
1 2 3 4 5
2 4 6 8 10
30
تحذير: نظرًا لأن المصفوفات تُمرَّر بالرجوع، فإن التغييرات التي أجراها DoubleValues تنعكس مباشرةً على مصفوفة المُستدعي.
❓ أسئلة شائعة
📖 ملخص
- المصفوفات في لغة C# هي أنواع مرجعية تُعلن باستخدام
Type[]، مع ترقيم يبدأ من الصفر - تُرجع
Lengthعدد العناصر؛ ويؤدي فحص الحدود أثناء التشغيل إلى إلقاء استثناءIndexOutOfRangeExceptionفي حالة الوصول إلى قيم خارج النطاق - توفر الفئة
Arrayطرقًا ثابتة مثلSortوReverseوIndexOfوCopyوClearوResize - المصفوفات متعددة الأبعاد
int[,]تتساوى أطوال صفوفها؛ أما المصفوفات غير المنتظمةint[][]فتسمح بأطوال صفوف متفاوتة - يُعد
foreachخيارًا مثاليًّا للتكرار للقراءة فقط، بما في ذلك المصفوفات متعددة الأبعاد - يتم تمرير المصفوفات إلى الدوال بالرجوع، لذا فإن التعديلات التي تُجرى داخل الدالة تؤثر على المصفوفة الأصلية
📝 تمارين
- قم بتعريف مصفوفة مكونة من 10 أعداد صحيحة، وقم بتعيين القيم من 1 إلى 10 باستخدام حلقة، ثم اطبع جميع العناصر بترتيب عكسي
- استخدم
Array.Sortلترتيب مصفوفة سلاسل أبجديًّا، ثم اطبع النتيجة - أنشئ مصفوفة ثنائية الأبعاد من الأعداد الصحيحة بحجم 3×3، واحسب مجموع العناصر الموجودة على القطر واطبع النتيجة
- أنشئ مصفوفة غير منتظمة تخزن درجات 3 طلاب (لكل منهم عدد مختلف من المواد)، ثم احسب متوسط الدرجات لكل طالب
- اكتب دالة
int FindMax(int[] arr)تقبل مصفوفة وتُرجع القيمة الأقصى