اذهب إلى المحتوى

المصفوفات (Arrays) في لغة سي شارب #C


حسام برهان

تعتبر المصفوفات من بنى المعطيات المهمّة في أيّ لغة برمجة. سيفترض هذا الدرس أنّه لديك خبرة مسبقة عن مفهوم المصفوفة. المصفوفات في سي شارب هي عبارة عن نوع مرجعيّ reference type، وهي ترث من الصنف الأب System.Array. تقدّم لنا سي شارب المصفوفات بأسلوب مبسّط وواضح.

learn-csharp-arrays.png

فلتعريف مصفوفة يمكنها استيعاب 10 عناصر من النوع int مثلًا يكفي أن نكتب ما يلي:

int[] arrIntegers = new int[10];

للعبارة السابقة في الواقع وظيفتان: الأولى هي التصريح عن المتغيّر arrIntegers على أنّه مصفوفة عناصرها من النوع int وذلك عن طريق كتابة []int أوّل العبارة. والثانية هي إنشاء كائن المصفوفة وحجز 10 أماكن في الذاكرة بحيث يستطيع كلّ مكان منها استيعاب قيمة من النوع int وذلك عن طريق التعبير [new int[10 ومن ثمّ إسناد المرجع لهذا الكائن إلى المتغير arrIntegers. ويمكن كما نعلم أن نجري هذه العمليّة على شكل عبارتين منفصلتين.

يمكننا إنشاء أيّ نوع من المصفوفات نرغبه. فيمكننا إنشاء مصفوفات عناصرها نصوص []string، ومصفوفات عناصرها أعداد ذوات فاصلة عائمة مثل []float، وحتى يمكننا إنشاء مصفوفات عناصرها كائنات من أصناف ننشئها نحن بأنفسنا. فمثلًا إذا أنشأنا الصنف Car فيمكننا إنشاء مصفوفة من العناصر التي يقبل كل عنصر منها أن يخزّن مرجع لكائن من الصنف Car وذلك على الشكل التالي:

Car[] arrCars = new Car[5];

تُنشئ العبارة السابقة المصفوفة arrCars والتي تحوي 5 عناصر يمكنها تخزين مراجع لكائنات من الصنف Car.

استخدام المصفوفات مع أنواع مضمنة

لكلّ عنصر في مصفوفة دليل index، ويُعبّر عن ترتيب هذا العنصر ضمن المصفوفة. يبدأ ترقيم الأدلّة في أيّ مصفوفة بالصفر. أي أنّ دليل العنصر الأوّل هو الصفر. فالمصفوفة arrCars التي صرّحنا عنها قبل قليل تحتوي على خمسة عناصر، دليل العنصر الأوّل هو 0، أمّا دليل العنصر الأخير فهو 4 كما هو واضح.

يمكن المرور على عناصر أيّ مصفوفة باستخدام الدليل. فمثلًا يمكننا الوصول إلى العنصر الثاني في المصفوفة arrCars عن طريق كتابة [arrCars[1.

يطلب البرنامج Lesson09_01 التالي من المستخدم إدخال درجات 5 طلاب في إحدى المواد الدراسيّة ومن ثمّ يحسب معدّل هؤلاء الطلبة في هذه المادّة، على افتراض أنّ الدرجة العظمى هي 100. ومن ثمّ يطبع المعدّل مع أسماء الطلاب ودرجاتهم على الشاشة:

1   using System;
2
3   namespace Lesson09_01
4   {
5       class Program
6       {
7           static void Main(string[] args)
8           {
9               int[] arrMarks = new int[5];
10              string[] arrNames = new string[5];
11              int sum = 0;
12 
13              Console.WriteLine("Input Students Marks");
14              Console.WriteLine("=====================");
15
16              //input loop.
17              for(int i = 0; i < arrMarks.Length; i++)
18              {
19                  Console.Write("Input student {0} th name: ", i + 1);
20                  arrNames[i] = Console.ReadLine();
21
22                  Console.Write("Input student {0} th mark: ", i + 1);
23                  string tmpMark = Console.ReadLine();
24                  arrMarks[i] = int.Parse(tmpMark);
25
26                  Console.WriteLine();
27              }
28
29              Console.WriteLine();
30              Console.WriteLine("Students Marks Table");
31              Console.WriteLine("====================");
32              Console.WriteLine("No\tName\tMark");
33             
34              //calculating sum and display output loop.
35              for (int i = 0; i < arrMarks.Length; i++)
36              {
37                  sum += arrMarks[i];
38                  Console.WriteLine("{0}\t{1}\t{2}", i + 1, arrNames[i], arrMarks[i]);
39              }
40  
41              Console.WriteLine("-------------------");
42              Console.WriteLine("Sum\t\t{0}", sum);
43              Console.WriteLine("Average\t\t{0}", sum/(double)arrMarks.Length);
44              Console.WriteLine();
45          }
46      }
47  }

يبدأ البرنامج السابق بالتصريح عن المصفوفتين arrMarks لتخزين علامات الطلّاب و arrNames لتخزين أسمائهم. كما يصرّح عن المتغيّر sum لتخزين مجموع الدرجات. يعرض البرنامج عبارتين توضيحيّتين في السطرين 13 و 14، ثمّ تبدأ حلقة for في السطر 17 بجمع أسماء ودرجات الطلّاب في هذه المادّة. لاحظ كيف أنّنا وضعنا شرط استمرار الحلقة i < arrMarks.Length (السطر 17). تعطينا الخاصيّة Length للمصفوفة arrMarks عدد العناصر ضمن هذه المصفوفة (عددها 5 في مثالنا). سيضمن ذلك تنفيذ حلقة for لخمسة مرّات فقط. نبدأ اعتبارًا من السطر 29 بالتجهيز لعرض النتائج، حيث سنظهرها على شكل جدول يضم ثلاثة أعمدة الرقم المتسلسل للطالب No والاسم Name والدرجة Mark. يطبع السطر 32 ترويسة هذا الجدول من خلال النص "No\tName\tMark" نستخدم المحرف t\ في النص السابق لترك مسافة جدولة tab تفصل بين كل عمودين. يدخل البرنامج بعد ذلك إلى حلقة إظهار النتائج اعتبارًا من السطر 35. لاحظ النص التنسيقيّ "{0}\t{1}\t{2}" في السطر 38، وظيفته أيضًا ترك مسافة جدولة بين كل عمودين. بعد الانتهاء من الحلقة نُظهر المجموع Sum والمعدّل Average بقسمة المجموع Sum على عدد الطلاب.

أمر أخير تجدر ملاحظته، في السطر 43 عند حساب المعدّل استخدمنا التعبير التالي: sum/(double)arrMarks.Length، ويعود سبب وجود عامل التحويل (double) أمام arrMarks.Length إلى جعل القسمة تجري بين قيمة من نوع int (قيمة sum) وقيمة من نوع double لكي يصبح الناتج من نوع double. لأنّه بدون عامل التحويل هذا، ستجري عمليّة القسمة بين قيمتين من نوع int (الخاصيّة Length هي من نوع int) وبالتالي سيكون الناتج من نوع int وتُهمل أي أجزاء عشريّة وهذا أمر غير مرغوب. لقد نفّذت البرنامج وقمت بتزويده ببعض البيانات، وحصلت عل الخرج التالي:

fig01.png

استخدام المصفوفات مع أنواع من إنشاءنا

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

سننشئ لهذا الغرض صنف جديد اسمه Student، يحتوي هذا الصنف على خاصّتين: الاسم Name والدرجة Mark. سنصرّح بعد ذلك عن المتغيّر arrStudents ليكون مصفوفة من النوع []Student. سيسلك هذا البرنامج نفس سلوك البرنامج Lesson09_01 تمامًا، أي سيطلب درجات خمسة طلاب ليعرضهم ويحسب مجموع درجاتهم ومعدّلهم. انظر البرنامج Lesson09_02:

1   using System;
2
3   namespace Lesson09_02
4   {
5       class Student
6       {
7           public string Name { get; set; }
8           public int Mark { get; set; }
9       }
10
11      class Program
12      {
13          static void Main(string[] args)
14          {
15              Student[] arrStudents = new Student[5];
16              int sum = 0;
17
18              Console.WriteLine("Input Students Marks");
19              Console.WriteLine("=====================");
20
21              //input loop.
22              for (int i = 0; i < arrStudents.Length; i++)
23              {
24                  arrStudents[i] = new Student();
25
26                  Console.Write("Input student {0} th name: ", i + 1);
27                  arrStudents[i].Name = Console.ReadLine();
28
29                  Console.Write("Input student {0} th mark: ", i + 1);
30                  string tmpMark = Console.ReadLine();
31                  arrStudents[i].Mark = int.Parse(tmpMark);
32
33                  Console.WriteLine();
34              }
35
36              Console.WriteLine();
37              Console.WriteLine("Students Marks Table");
38              Console.WriteLine("====================");
39              Console.WriteLine("No\tName\tMark");
40
41              //calculating sum and display output loop.
42              for (int i = 0; i < arrStudents.Length; i++)
43              {
44                  sum += arrStudents[i].Mark;
45                  Console.WriteLine("{0}\t{1}\t{2}", i + 1, arrStudents[i].Name, arrStudents[i].Mark);
46              }
47
48              Console.WriteLine("-------------------");
49              Console.WriteLine("Sum\t\t{0}", sum);
50              Console.WriteLine("Average\t\t{0}", sum / (double)arrStudents.Length);
51              Console.WriteLine();
52          }
53      }
54  }

كلّ من البرنامجين Lesson09_01 و Lesson09_02 متشابهان من حيث الخرج. ولكن يتعامل البرنامج Lesson09_02 مع المصفوفة arrStudents التي عناصرها من النوع Student. الصنف Student مصرّح عنه في الأسطر من 5 إلى 9. والمصفوفة arrStudents مصرّح عنها في السطر 15. يُعتبر السطر 24 مهمًا جدًا وفيه يتم إنشاء كائن جديد من الصنف Student وإسناده إلى كل عنصر من عناصر المصفوفة arrStudents في كل دورة من دورات حلقة for. إذا حاولت إزالة عبارة إنشاء الكائن من الصنف Student في السطر 24 فسيعمل البرنامج ولكنّه سيتوقّف عن التنفيذ ويصدر خطأ عندما يصل التنفيذ إلى السطر 27. لأنّه عندما نصرّح عن مصفوفة عناصرها من أنواع ليست مضمّنة، فنحن في الحقيقة نصرّح عن متغيّرات فقط دون إنشاء كائنات ضمن هذه العناصر (المتغيّرات). وبالتالي لا يحق لنا الوصول إلى أعضاء كائن غير مُنشَأ أصلًا، فالتعبير arrStudents.Name سيولّد خطأً مالم يكن هناك كائن فعلي ضمن العنصر [arrStudents[i (أي عنصر المصفوفة ذو الدليل i).

حلقة foreach التكرارية

حلقة foreach من الحلقات التكراريّة المفيدة والتي تتسم بأسلوب عمل أقرب إلى المألوف. يمكن استخدام حلقة foreach على المصفوفات والمجموعات كما سنرى لاحقًا. طريقة استخدام foreach بسيطة سنتناولها من خلال البرنامج Lesson09_03 التالي:

1   using System;
2
3   namespace Lesson09_03
4   {
5       class Program
6       {
7           static void Main(string[] args)
8           {
9               int[] arrNumbers = new int[10];
10              Random random = new Random();
11
12              for(int i = 0; i < arrNumbers.Length; i++)
13              {
14                  arrNumbers[i] = random.Next(100);
15              }
16
17              foreach(int n in arrNumbers)
18              {
19                  Console.WriteLine(n);
20              }
21          }
22      }
23  }

ملاحظةالبرنامج السابق بسيط، حيث يصرّح عن المصفوفة arrNumbers بعشرة عناصر، ويعمل على تعبئة عناصرها بقيم عشوائيّة يحصل عليها من كائن من النوع Random. صرّحنا عن المتغيّر random وأسندنا إليه مرجع لكائن من الصنف Random وذلك في السطر 10. في حلقة for (الأسطر من 12 إلى 15) قمنا بتوليد أرقام عشوائيّة عن الطريق التابع (Next(100 من الكائن random والذي يولّد أرقامًا عشوائيّة صحيحة غير سالبة أقل من 100. بعد ذلك سنطبع هذه الأرقام العشوائيّة على الشاشة عن طريق حلقة foreach. مبدأ هذه الحلقة بسيط، منطق عملها يتلخّص على النحو التالي: "من أجل كل عنصر n موجود ضمن المصفوفة arrNumbers نفّذ الشيفرة الموجودة في حاضنة foreach". في مثالنا هذا تحتوي الحاضنة على عبارة برمجيّة واحدة (السطر 19).

في البرنامج Lesson09_03 السابق المتغيّر n المصرّح عنه في السطر 17 والذي سيحمل قيمة مختلفة من عناصر المصفوفة arrNumbers في كل دورة للحلقة، هو متغيّر للقراءة فقط read-only لا يمكن تغيير قيمته ضمن حاضنة foreach.

تمارين داعمة

تمرين 1

اكتب برنامجًا يعرّف مصفوفة من نوع int بعشرة عناصر. ثم يطلب من المستخدم إدخال قيم لهذه العناصر. بعد ذلك يعمل البرنامج على ترتيب عناصر هذه المصفوفة تصاعديًّا.

تلميح: تمتلك سي شارب أساليب جاهزة وسريعة لمثل عمليّات الترتيب هذه، ولكنّنا نريد في هذا المثال التدرُّب على الحلقات والمصفوفات.

تمرين 2

عدّل البرنامج Lesson09_02 السابق لكي يسمح للمستخدم بإدخال بيانات عدد كيفي من الطلّاب.

تلميح: ستحتاج لأن تطلب من المستخدم إدخال عدد الطلاب المراد إدخال بياناتهم أولًا، ومن ثمّ تصرّح عن المصفوفة arrStudents بالعدد المطلوب.

الخلاصة

تعرّفنا في هذا الدرس على المصفوفات وطرق استخدامها. توجد في الحقيقة مزايا أخرى تتمتّع بها المصفوفات مثل إمكانيّة نسخ مصفوفة إلى مصفوفة أخرى، وغيرها من المزايا الأخرى التي سنتناولها في الدروس والسلاسل القادمة. كما تعرّفنا أيضًا على الحلقة التكراريّة foreach التي يُعتبر أسلوب عملها مألوفًا، وهي مفيدة جدًا عند استخدامها مع المجموعات كما سنرى لاحقًا.


تفاعل الأعضاء

أفضل التعليقات

السلام عليكم 

اخي ممكن برنامج في الي شارب يقوم بترتيب عناصر مصفوفة

 (اعداد) تصاعديا او تنازليا بطريقة bubble sort  وشكرا

 

تم التعديل في بواسطة ahmed yoosef
رابط هذا التعليق
شارك على الشبكات الإجتماعية

السلام عليكم 
ممكن حل للسؤال بلا زحمه 

 برنامج في الجافا يدخل 10 اسماء للطلاب في ملف مع 5 درجات لكل طالب وكذلك كتابة أسماء الطلاب نفسهم في ملف ثاني مع المعدل لكل طالب

رابط هذا التعليق
شارك على الشبكات الإجتماعية

بتاريخ 19 ساعات قال Jannat Jk:

كيف يمكن ترتيب العناصر مصفوفة تصاعدي sort

يمكننا استخدام الصنف المساعد Array الدالة sort 

int[] numbers = { 40, 5, 3, 22, 1, 18 };
Array.Sort(numbers);

foreach(int i in numbers) {
	Console.Write(i + " ");
}

يمكنك استعامل هذه الطريقة مع أي نوع من المصفوفات رقمية أو نصية

رابط هذا التعليق
شارك على الشبكات الإجتماعية

بتاريخ 18 ساعات قال Ali Rashed:

السلام عليكم

انا استخدم مصفوفه ثنائيه من نوع تايم سبان 

واريد المخرجات تظهر في داتا جريد فيو  وارجو المساعده  واعطائي كود وشكرا 

مرحباً علي،

للقيام بذلك علينا استعمال الحشو، أي نقوم بإنشاء جدول وهمي، عن طريق الحشو بفراغات.

في البداية علينا تحديد ما هو العرض الأقل، ثم نقوم بالحشو على أساس هذا العرض باستعمال التابع PadRight و الذي نطبقه على سلسلة نصية و يقوم بالحشو إلى اليمين، بما يلزم لجعل طول السلسلة النصية مساو للرقم الذي مررناه له.

أي مثلاً في حال لدي سلسلة نصية طولها 8 و قمت بتمرير 10 لهذا التابع فسيقوم بإضافة فراغين إلى اليمين.

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

الكود كما يلي:

using System;

public class Test
{
	public static void Main()
	{
		TimeSpan[,] timeTable = new TimeSpan[5, 3];
		int minWidth = 10;
		for (int i = 0 ; i < 5 ; ++i){
			for(int j = 0 ; j < 3 ; ++j){
				string t = timeTable[i, j].ToString();
				t = t.PadRight(minWidth);
				Console.Write(t);
			}
			Console.WriteLine();
		}
	}
}

هنا في البداية قمت بإنشاء مصفوفة فارغة من النمط TimeSpan (فقط لأجل المثال، أنت عليك استعمال المصفوفة الخاصة بك).

بعدها قمت بتحديد العرض الأصغر على أنه 10 ( عليك تجريب قيم مختلفة و اختيار القيمة التي تناسبك).

في الخطوة التالية نقوم بالمرور على عناصر المصفوفة سطراً سطراً، في كل مرة نقوم بتحويل العنصر إلى سلسلة نصية عن طريق الدالة ToString ثم نقوم بإضافة حشو إلى اليمين عن طريق الدالة PadRight، لاحظ أن الدالة لا تعدل على السلسلة النصية الأصلية، بل تعيد سلسلة جديدة و لذلك كان علينا إسناد ذلك إلى t.

بعدها نقوم بكتابة القيمة، لاحظ يجب أن نستعمل Write و ليس WriteLine ﻷننا ما زلنا على نفس السطر.

في نهاية كل تكرار من الحلقة الخارجية علينا النزول سطر، و ذلك ﻷننا انتهينا من سطر من المصفوفة.

يكون الخرج كما يلي:

636c9ef42e7f7_Screenshotfrom2022-11-1009-49-11.png.45d35d885cb3dcbb73d5c7c13780c6ef.png

تحياتي لك.

رابط هذا التعليق
شارك على الشبكات الإجتماعية

مسا الخير

بدي حل السؤال هادا ضرورياكتب برنامج يطلب من المستخدم ادخال مصفوفة ثنائية الابعاد من الاعداد الصحيحة ويعيد رقم الصف الذي يحتوي ع اكبر مجموع C#

 

رابط هذا التعليق
شارك على الشبكات الإجتماعية

بتاريخ 11 ساعة قال مرح الاسطل:

مسا الخير

بدي حل السؤال هادا ضرورياكتب برنامج يطلب من المستخدم ادخال مصفوفة ثنائية الابعاد من الاعداد الصحيحة ويعيد رقم الصف الذي يحتوي ع اكبر مجموع C#

 

مرحبًا @مرح الاسطل

تم الإجابة على سؤالك هنا أرجو متابعته:

 

رابط هذا التعليق
شارك على الشبكات الإجتماعية



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...