أوامر التكرار
في البرمجة المُتقدمة والتي نتعامل فيها مع الكثير من المُعطيات أو التي يعمل البرنامج فيها مرات عديدة نحتاج أن نكرر أوامر بطريقة مُختصرة وناجعة وسهله بدلا من نسخ الأوامر وتكرارها مما سيؤدي لتضخم الكود وجعله غير قابل للقراءة أو الفهم (بالإضافة انه سيتطلب منا الكثير من الوقت).
سنتعلم كيف نكرر أوامر بطريقتين:
- صيغة تكرار while
- صيغة تكرار for
الطريقتين متكافئتين ويمكن استعمال أي منهما، ولكن هناك حالات تكون فيها طريقة من هذه الطرق أسرع وأسهل من الأخرى. سنبدأ بصيغة التكرار while ثم نعود لصيغة التكرار for
6.1 صيغة التكرار while – לולאת while
علينا أن نتذكر دائما وان نستحضر أن while معناها طالما (כל עוד).
يُستعمل أمر while لتكرار مقطع أوامر معين عدداً من المرات، والتي من الممكن أن تكون معروفة مسبقاً (تتعلق بمتطلبات البرنامج أو المُبرمج) أو يكون عدد مرات التكرار غير معروف مسبقاً (يتعلق باستقبال معطيات من المستخدم أو بحسابات خلال تشغيل البرنامج).
مبنى التكرار while:
اوامر قيمة بدائية ;
while ( شرط التكرار )
{
....
....
أوامر للتكرار *
....
....
}- لكي يتحقق شرط التكرار في البداية علينا أن نكتب أوامر تعطي قيمة بدائية للمُتغيرات المُشتركة في شرط التكرار الموجود داخل الأقواس ( )
- إذا تحقق شرط التكرار داخل أقواس while فان الحاسوب يدخل الى الأوامر المُعدة للتكرار الموجودة داخل الأقواس المُتعرجة وينفذها.
- بعد كل تنفيذ للأوامر المُخصصة للتكرار يعود الحاسوب لفحص شرط التكرار من جديد.
- إذا كان شرط التكرار مُتحققاً (true) فإن الحاسوب يدخل من جديد الى الأوامر للتكرار الموجودة داخل الأقواس المُتعرجة وينفذها. لهذا السبب نتذكر أن while معناها لطالما وذلك لأننا نُكرر الأوامر لطالما الشرط يتحقق.
- لكي ينتهي تكرار تنفيذ أوامر التكرار على الشرط أن لا يتحقق (ان يصبح false) لذلك يجدر بنا أن نضع أمراً أو أوامر تؤثر على الشرط داخل أوامر التكرار وذلك لكي يتغير وضع الشرط من true الى false
- إذا لم يتغير الشرط بأي حال من الأحوال ولم نستطع التأثير عليه بواسطة أوامر التكرار لكي يصبح شرط التكرار false فان التكرار هو لا نهائي (לולאה אינסופית) وهو وضع غير مقبول بشكل عام، الا في حالات خاصة مُعينة.
(*) أوامر التكرار تتضمن أمر تأثير على شرط التكرار. (أمر تقدم).
متى نستعمل صيغة التكرار while ؟:
يُمكن استعمال صيغة التكرار while في الحالات التالية:
- أوامر تكرار مشروطة بشرط مُعين (بدون عداد)، التي تكون عادة استقبال مُعطيات مع شرط توقف مثلاً استقبال أرقام حتى نستقبل أول رقم سالب (استقبال رقم سالب هو شرط التوقف). (وهو الاستعمال الدارج والمُستحسن للصيغة while).
بشكل عام اذا استخدمنا صيغة while بهذه الحالة (شرط توقف) فانه يجدر بنا أن نستقبل مُعطيات مرة واحدة خارج التكرار قبل ال while أي قبل أن نصل الى شرط التكرار. - أوامر تكرار مشروطة بعدّاد مُعين ( i مثلا) حيث أننا نضع أمر إعطاء قيمة بدائية للعداد قبل while ونضع الشرط في أقواس ( ) بعد كلمة while ثم يجب علينا أن نضع أوامر تُغير قيمة العدّاد (نُقدمه أو نأخره) داخل الأوامر المُخصصة للتكرار والموجودة داخل الأقواس المُتعرجة، وذلك للتأثير على الشرط كي تتوقف عملية التكرار بمرحلة معينة (بعد عدد معين من المرات).
اعطاء قيمة بدائية للعداد ;
while ( شرط التكرار )
{
....
....
أوامر للتكرار
....
....
أمر تقدم للعداد.
}- أوامر تكرار لا نهائية.
- أوامر تكرار تتعلق بحصول حدث معين ترتبط في رفع علم مُعين flag (نتيجة معينة).
الحل:
static void Main(string[] args)
{
int num1, num2, i=1, result=0;
Console.Write("Insert a number: ");
num1 = int.Parse(Console.ReadLine());
Console.Write("Insert another number: ");
num2 = int.Parse(Console.ReadLine());
while(i<=num2)
{
result = result + num1; // جمع تراكمي
i++; // i=i+1;
}
Console.WriteLine("{0} * {1} = {2}",num1,num2,result);
}نتيجة تشغيل البرنامج للمُدخلات 3 و 7 :
Insert a number: 3 Insert another number: 7 3 * 7 = 21
ملاحظة: ليس من الضرورة أن يكون الرقمين مُختلفين وليس من الضرورة أن يُعطى الرقم الأصغر أولا كما أنه يُمكن للأرقام أن تكون سالبة.
الحل:
static void Main(string[] args)
{
int num1, num2, i,max;
Console.Write("insert the first number: ");
num1 = int.Parse(Console.ReadLine());
Console.Write("insert the second number: ");
num2 = int.Parse(Console.ReadLine());
i = Math.Min(num1, num2);
max = Math.Max(num1, num2);
while (i<=max)
{
if(i%2==0)
Console.WriteLine(i);
i++;
}
}نتيجة عمل البرنامج للمُدخل 3 و −4
insert the first number: 3 insert the second number: -4 -4 -2 0 2
- عدد المواضيع التي فيها عدم نجاح (تحت ال 55).
- عدد المواضيع التي فيها نجاح. (55 أو أكثر).
- مُعدل الطالب.
- أعلى علامة حصل عليها الطالب.
- أدنى علامة حصل عليها الطالب.
- العدد الكلي للأعداد المُدخلة بالسلسلة دون العدد السالب (أي عدد الأعداد غير السالبة).
- مُعدل الأعداد غير السالبة (أي مُعدل الأعداد غير السالبة).
- أكبر عدد في هذه السلسلة.
ملاحظة: ليس من الضرورة أن يكون الرقمين مُختلفين وليس من الضرورة أن يُعطى الرقم الأصغر أولا كما أنه يُمكن للأرقام أن تكون سالبة.
مثال: إذا أدخل 8 و −3 يطبع:
-2,0,2,4,6,8.الحل:
static void Main(string[] args)
{
int num1, num2, i,max;
Console.Write("insert the first number: ");
num1 = int.Parse(Console.ReadLine());
Console.Write("insert the second number: ");
num2 = int.Parse(Console.ReadLine());
i = Math.Min(num1, num2);
max = Math.Max(num1, num2);
if (max % 2 != 0)
max = max-1;
while (i<=max)
{
if(i%2==0 && i!= max)
Console.Write("{0},",i);
else if(i%2==0 && i==max)
Console.WriteLine("{0}.", i);
i++;
}
}نتيجة تشغيل البرنامج أعلاه للمُدخل 9 و −11
insert the first number: 9 insert the second number: -11 -10,-8,-6,-4,-2,0,2,4,6,8.
(العدد الأولي هو عدد لا يقسم قسمة صحيحة إلا على نفسه وعلى 1).
6.2 صيغة التكرار for – לולאת for
تستعمل الصيغة for لجميع الحالات التي نريد أن نكرر فيها مقطع برمجي مُعين بالضبط كما فعلنا بالصيغة while فالصيغتان متكافئتان ولكن من المُفضل أن نستخدم الصيغة for بشكل عام مع عدادات أو لعدد مُحدد من المرات.
يتم تنفيذ أمر إعطاء قيمة بدائية (أمر رقم 1) فقط مرة واحدة في البداية قبل فحص الشرط (بغض النظر هل يتحقق الشرط أم لا)، ثم نفحص الشرط (2)، إذا تحقق الشرط (true)، ندخل لتنفيذ الأوامر للتكرار (3)، ثم بعد تنفيذ الأوامر للتكرار (3)، نعود وننفذ أمر التقدم (الأمر 4 وهو أمر تغيير العدّاد)، ثم نفحص الشرط مرة أخرى (5) وإذا تحقق الشرط (true) ندخل لتنفيذ أوامر التكرار (6) وبعدها ننفذ أمر التقدم (7)، ودائما بعد تنفيذ أمر التقدم نفحص الشرط (8) واذا تحقق الشرط نستمر بالتكرار وهكذا ولكن اذا لم يتحقق الشرط (اصبح false) فإننا لن ندخل الى الأقواس المُتعرجة لتنفيذ أوامر التكرار بل سنقفز عنها لنصل الى الأوامر خارج التكرار (نقفز خارج الحلقة) ونكمل البرنامج (الأوامر 9 * )
الحل:
static void Main(string[] args)
{
int i, n;
Console.Write("Insert a number: ");
n = int.Parse(Console.ReadLine());
for (i =1;i<=n;i++)
Console.WriteLine("Hello Hammam");
}6.3 مقارنة بين صيغة for وصيغة while – השוואה בין for ל-while
كما ذكرنا سابقاً فإن الصيغتين متكافئتين وكل ما يمكن حله بواسطة احداهما، يمكن أن نحله بواسطة الصيغة الأخرى، ولكن هناك حالات يكون استعمال while أسهل لنا وأسرع وحالات أخرى تكون الصيغة for هي الأسهل.
بشكل عام تستعمل for لتكرار مع عَدّاد او للعدّ أو لعَدد معروف مسبقا من المرات مع عدّاد، بينما صيغة while تستعمل إذا كان لنا تكرار مع شرط توقف أو تكرار يعتمد على حدوث شيء ما (نتيجة مُعينة) أو استقبال مُعطى مُعين.
نكتب تكرار 10 مرات:
int i;
for(i=1;i<=10;i++)
Console.WriteLine("Hammam");int i;
i = 1;
while(i<=10)
{
Console.WriteLine("Hammam");
i++;
}- بواسطة while
- بواسطة for
الحل:
(أ)
static void Main(string[] args)
{
int mark,i=1,sum=0;
double avg ;
while(i<=10)
{
Console.WriteLine("Insert a mark: ");
mark = int.Parse(Console.ReadLine());
sum += mark;
i++;
}
avg = (double)sum / 10;
Console.WriteLine("The average is: {0}",avg);
}(ب)
static void Main(string[] args)
{
int mark,i,sum=0;
double avg ;
for(i=1;i<=10;i++)
{
Console.WriteLine("Insert a mark: ");
mark = int.Parse(Console.ReadLine());
sum += mark;
}
avg = (double)sum / 10;
Console.WriteLine("The average is: {0}",avg);
}<number>!=<result>مثلا:
اذا استقبلنا الرقم 5 فان المخرجات ستكون: 5!=120
تذكير:
الحل:
static void Main(string[] args)
{
int n,res=1,i;
Console.Write("Insert a positive number: ");
n = int.Parse(Console.ReadLine());
if (n == 0)
Console.WriteLine("{0}!=1", n);
else
{
for (i = 1; i <= n; i++)
res = res * i;
Console.WriteLine("{0}!={1}", n, res);
}
}جدول متابعة لبرنامج العاملي:
جدول متابعة عند استقبال المُدخل n=5.
| الأمر | n | res | i | الشرط | شرط التكرار | المُخرجات |
|---|---|---|---|---|---|---|
| int n,res=1,i; | 1 | |||||
| Console.Write("Insert a positive number: "); | 1 | Insert a positive number: | ||||
| n = int.Parse(Console.ReadLine()); | 5 | 1 | ||||
| if (n == 0) | 5 | 1 | F | |||
| else | 5 | 1 | ||||
| i = 1; | 5 | 1 | 1 | |||
| i <= n | 5 | 1 | 1 | T | ||
| res = res * i; | 5 | 1 | 1 | |||
| i++; | 5 | 1 | 2 | |||
| i <= n | 5 | 1 | 2 | T | ||
| res = res * i; | 5 | 2 | 2 | |||
| i++; | 5 | 2 | 3 | |||
| i <= n | 5 | 2 | 3 | T | ||
| res = res * i; | 5 | 6 | 3 | |||
| i++; | 5 | 6 | 4 | |||
| i <= n | 5 | 6 | 4 | T | ||
| res = res * i; | 5 | 24 | 4 | |||
| i++; | 5 | 24 | 5 | |||
| i <= n | 5 | 24 | 5 | T | ||
| res = res * i; | 5 | 120 | 5 | |||
| i++; | 5 | 120 | 6 | |||
| i <= n | 5 | 120 | 6 | F | ||
| Console.WriteLine("{0}!={1}", n, res); | 5 | 120 | 6 | 5!=120 |
6.4 أمر break – הפקודה break
نحتاج في بعض الظروف أن نوقف التكرار (الحلقة loop) على الرغم من أن الشرط ما زال مُتحققا، وأن نوقف عمل أوامر التكرار رغم ان هذه الأوامر لم تنتهي بعد (لم نصل لنهاية أوامر التكرار). من أجل ذلك يوجد الأمر break.
الأمر break هو أمر يوقف تنفيذ التكرار ويوقف تنفيذ أوامر التكرار من داخل الحلقة (loop) حتى لو أن الشرط ما زال مُتحققا، وحتى لو ان الدورة لم تنتهِ بعد، عندما نصل الى الأمر break يقفز مؤشر تنفيذ الأوامر الى اول أمر خارج الحلقة loop (خارج أوامر التكرار) ليكمل الحاسوب تنفيذ الأوامر الموجودة خارج اطار التكرار.
أمر break هو أمر يسهل علينا حل المسائل ويساعدنا في تبسيط الحلول وليس إلزاميا علينا دائماً أن نستخدمه.
for (int i = 1; i <= 100; i++)
{
Console.WriteLine(i);
if (i == 5)
break;
}int i = 1;
while(true)
{
Console.WriteLine(i);
if (i == 5)
break;
i++;
}هذان المقطعان يطبعان الأرقام من 1 حتى 5 (يشمل 1 و 5)
إذا توقف العامل عن العمل بالشركة فان البرنامج لن يكمل حساب مجموع معاشاته (لأنها ستكون صفرا بالأشهر المتبقية للسنة) وعليه ان يطبع له مجموع راتبه خلال الأشهر التي عملها بالشركة.
الحل:
static void Main()
{
double total = 0, salary;
int i;
for (i = 1; i <= 12; i++)
{
Console.Write("Insert your salary in month {0}: ", i);
salary = double.Parse(Console.ReadLine());
if (salary == 0) // لم يعد يعمل العامل بالشركة
break;
total += salary;
}
if (i < 13) // i!=13
Console.WriteLine("You worked only {0} months,and you earned:{1}",i-1,total);
else
Console.WriteLine("You earned a {0} in this year.",total);
}تشغيل البرنامج في حالة نصل فيها الى تنفيذ أمر break:
Insert your salary in month 1: 50 Insert your salary in month 2: 100 Insert your salary in month 3: 350 Insert your salary in month 4: 0 You worked only 3 months,and you earned:500
6.5 أمر continue – הפקודה continue
أحيانا يحدث أننا لا نريد أن نستمر بتنفيذ باقي الأوامر في الحلقة (الدورة) لكن بدون أن نوقف التكرار إنما نريد الانتقال لأول الحلقة (أو لأمر التقدم في for). لذلك يوجد امر continue
أمر continue هو أمر يوقف تنفيذ الدورة الحالية (التكرارية التي نحن بها) ولكنه لا يوقف التكرار بل يقفز مؤشر تنفيذ الأوامر الى نهاية مقطع أوامر التكرار ويعود من جديد (إما لفحص الشرط في while وإما لأمر التقدم في for)
for(int i=1;i<=10;i++)
{
if (i == 5)
continue;
Console.Write("{0} ",i);
}1 2 3 4 6 7 8 9 10
يطبع جميع الأرقام من 1 حتى 10 (يشمل 10) عدا الرقم 5
static void Main()
{
int i=1,num;
while(i<=10)
{
Console.Write("Insert a number: ");
num = int.Parse(Console.ReadLine());
if (num == 0)
continue;
Console.WriteLine("100/{0} = {1}",num,100.0/num);
i++;
}
}هذا البرنامج يضمن أن يكون لدينا 10 نتائج قسمة 100 على أرقام. ان استقبلنا صفرا لن تحدث عملية القسمة كما أن العدّاد لن يتقدم في هذه الحالة، وهذه المُحاولة لن تُحسب من العشرة مرات تكرار.
6.6 المتواليات – סדרות
6.6.1 المتوالية الحسابية – סדרה חשבונית
هي عبارة عن سلسلة من الأرقام التي فيها قانونية (علاقة) مُحددة وهي أن الفرق بين كل حدين متتاليين هو فرق ثابت ويساوي d . الحد الأول في المتوالية يرمز له a1 أما الحد ذو الترتيب n فانه يُرمز له بالحرف an
نستطيع أن نصل للقانون التالي:
أما مجموع الحدود حتى الحد رقم n فهو:
المتوالية التالية:
الحد الأول هو 7 أما فرق المتوالية d = 3
مجموع اول 3 حدود هو : 7+10+13 أي 30
الحد رقم 37 هو : 115 وذلك حسب القانون التالي:
أما مجموع أول 37 حد فهو : 2257 حسب القانون التالي:
يوجد قوانين أخرى لمجموع حدود المتوالية حتى الحد n وهي:
عند استعمالنا للبرمجة والحاسوب نستطيع حل المتواليات بواسطة التكرار دون استعمال القوانين وذلك لان الحاسوب سريع جدا في تنفيذ الأوامر حيث نستطيع أن نجد الحدود وأن نجد المجموع.
317 , 300 , 283 …بواسطة كتابة برنامج ملائم (دون استعمال قوانين الرياضيات للمتواليات)
- جد الحد رقم 10.
- أي حد هو أول حد سالب؟
static void Main(string[] args)
{
int a1 = 317, d = -17, sum,ai=0,ai_1,flag=1;
int i;
ai_1 = a1;
for (i = 2; i <= 10 || flag ==1; i++)
{
ai = ai_1 + d; // متوالية حسابية
if(ai<0)
{
Console.WriteLine("The first negative element is {0}",ai);
Console.WriteLine("His order is {0}",i);
flag = 0;
}
ai_1 = ai;
if(i==10)
Console.WriteLine("a10={0}", ai);
}
}نتيجة التشغيل:
a10=164 The first negative element is -6 His order is 20
أما الحل بواسطة قوانين الرياضيات فهو:
(أ) d=300 − 317 = −17 ➔ a10 = 317 + (10−1)·(−17) = 164
(ب) نحل المتباينة التالية : an < 0 أي نحل ما يلي: 317+(n−1)·(−17) < 0 نرتبها ونحلها ونحصل على n > 19.64 وبما أن n عدد صحيح اذا الإجابة هي n=20 والحد هو
static void Main(string[] args)
{
int a, d, i;
Console.Write("insert the first element: ");
a = int.Parse(Console.ReadLine());
Console.Write("insert the difference: ");
d = int.Parse(Console.ReadLine());
for (i = 1; i <= 20 ; i++)
{
if(i!=20)
Console.Write("{0},",a);
else
Console.WriteLine("{0}.",a);
a = a + d;
}
}نتيجة تشغيل البرنامج للمُدخلات a1=317 و d = −17 هي:
insert the first element: 317 insert the difference: -17 317,300,283,266,249,232,215,198,181,164,147,130,113,96,79,62,45,28,11,-6.
static void Main(string[] args)
{
int a, d,n,sum=0,i;
Console.Write("insert the first element: ");
a = int.Parse(Console.ReadLine());
Console.Write("insert the difference: ");
d = int.Parse(Console.ReadLine());
Console.Write("insert the number of elements you want: ");
n = int.Parse(Console.ReadLine());
for (i = 1; i <= n ; i++)
{
sum += a;
if(i!=n)
Console.Write("{0},",a);
else
Console.WriteLine("{0}.",a);
a = a + d;
}
Console.WriteLine("sum={0}",sum);
}نتائج تشغيل البرنامج للمُدخلات: a1 = −4 و d=5 ونريد أول 5 حدود ( n=5 ).
insert the first element: -4 insert the difference: 5 insert the number of elements you want: 5 -4,1,6,11,16. sum=30
6.6.2 المتوالية الهندسية – סדרה הנדסית
هي سلسلة أعداد فيها كل حد بعد الأول هو حاصل ضرب الحد الذي قبله بعدد ثابت (ليس 0) يدعى ثابت المتوالية (أو نسبة المتوالية) يرمز له بالحرف q.
مجموع المتوالية الهندسية هو:
3,12,48,192,…اكتب برنامج يطبع أول 10 حدود ويحسب مجموعها.
static void Main()
{
int i,a1=3,q=4,ai=a1,sum=0;
for(i=1; i<=10;i++)
{
sum += ai;
if (i != 10)
Console.Write("{0},", ai);
else
Console.Write("{0}.", ai);
ai = ai * q;
}
Console.WriteLine("\nThe Sum (S10) = "+sum);
}نتيجة تشغيل البرنامج:
3,12,48,192,768,3072,12288,49152,196608,786432. The Sum (S10) = 1048575
6.6.3 متواليات عامة – סדרות כלליות
متوالية فيبوناتشي:
متوالية فيبوناتشي هي متوالية أعداد صحيحة وموجبة فيها كل حد هو عبارة عن مجموع الحدين السابقين له. تبدأ المتوالية من حدين بدائيين وهما 1 و 1 (هناك من يبدأ من 0 و 1) .
المتوالية هي:
يمكن كتابة قانونية باستعمال دستور تراجعي كما يلي:
مثلا اذا ادخلنا 1 يطبع على الشاشة 1 بينما اذا ادخلنا 6 يطبع على الشاشة 8 ...
static void Main(string[] args)
{
int i, n,an=1,an_1=1,an_2=1;
Console.Write("Insert a number: ");
n = int.Parse(Console.ReadLine());
if(n==1 || n==2)
Console.WriteLine("a{0} = 1",n);
else
{
for (i = 3; i <= n; i++)
{
an = an_1 + an_2;
an_2 = an_1;
an_1 = an;
}
Console.WriteLine("a{0}={1}",n,an);
}
}نتيجة تشغيل البرنامج للمُدخل 10 هي:
Insert a number: 10 a10=55
نطبع الحدود الواحد بجانب الآخر، يفصل بينها فاصلة عدا آخر حد نضع بعده نقطة.
مثلا اذا استقبلنا الرقم 7 نطبع:
1,1,2,3,5,8,13.6.7 تكرار داخل تكرار – לולאה בתוך לולאה
أحيانا هناك حاجة ان تكون حلقة تكرار داخل تكرار آخر وأحيانا يكون ذلك أسهل لنا لحل المسائل.
الحلقة الأولى (الداخلية) هي حلقة تُكَرِّر مقطع أوامر داخلي وقد يلزمنا ان نُكرر كل هذه الحلقة العديد من المرات باستعمال حلقة تكرارية خارجية تكرر كل الحلقة الداخلية.
static void Main(string[] args)
{
int i, j;
for(i=1;i<=7;i++)
{
for(j=1;j<=10;j++)
Console.Write("*");
Console.WriteLine();
}
}********** ********** ********** ********** ********** ********** **********
الأمر Console.Write("*"); يتم تنفيذه في حلقة التكرار الداخلية 10 مرات (من j=1 حتى j=10) لكل مرة ندخل فيها حلقة التكرار الخارجية (لكل i من i=1 حتى i=7) أي يتم تنفيذ هذا الأمر: 7·10 مرات أي 70 مرة.
static void Main(string[] args)
{
int i, j,num;
char ch;
Console.Write("Insert a character: ");
ch = char.Parse(Console.ReadLine());
Console.Write("Insert a number: ");
num = int.Parse(Console.ReadLine());
for(i=1;i<=num;i++) // (i=0;i<num;i++)
{
for(j=1;j<=i;j++)
Console.Write("{0}",ch);
Console.WriteLine();
}
}Insert a character: $ Insert a number: 5 $ $$ $$$ $$$$ $$$$$
* ** *** **** ***** **** *** ** *
مثلا اذا استقبلنا 5 :
1 22 333 4444 55555
اطبع اسطرا مساويا للعد الذي تستقبله من المُستخدم
مثلا اذا استقبلنا 5 نطبع
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15