C: هياكل التكرار

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

1. حلقة while

while هي أبسط حلقة: تتحقق من الشرط أولًا، وتنفّذ جسم الحلقة إذا كان صحيحًا، ثم تتحقق مجددًا، وتكرر حتى يصبح الشرط خاطئًا.

C
#include <stdio.h>

int main(void) {
    int count = 1;
    while (count <= 5) {
        printf("Lap %d\n", count);
        count++;
    }
    printf("Done!\n");
    return 0;
}
TEXT 📖 للعرض فقط
Lap 1
Lap 2
Lap 3
Lap 4
Lap 5
Done!
⚠️ ملاحظة: يجب أن يحتوي جسم الحلقة على عملية تجعل الشرط خاطئًا في النهاية (مثل count++). وإلا ستتحصل على حلقة لا نهائية ولن يتوقف البرنامج أبدًا.

(1) متى تستخدم while

عما يكون عدد التكرارات غير محدد ويعتمد على شرط وقت التنفيذ، تكون while الخيار الأكثر طبيعية. مثلًا، قراءة المدخلات حتى قيمة معينة:

C
#include <stdio.h>

int main(void) {
    int sum = 0;
    int num = 0;
    printf("Enter positive integers to sum, 0 to finish: ");
    scanf("%d", &num);
    while (num != 0) {
        sum += num;
        scanf("%d", &num);
    }
    printf("Sum: %d\n", sum);
    return 0;
}
TEXT 📖 للعرض فقط
Enter positive integers to sum, 0 to finish: 10 20 30 0
Sum: 60

2. حلقة do-while

تنفِّذ do-while جسم الحلقة أولًا، ثم تتحقق من الشرط. هذا يضمن تنفيذ جسم الحلقة مرة واحدة على الأقل، وهو الفرق الجوهري عن while.

TEXT 📖 للعرض فقط
#include <stdio.h>

int main(void) {
    int num;
    do {
        printf("Enter a number 1-10: ");
        scanf("%d", &num);
    } while (num < 1 || num > 10);
    printf("You entered: %d\n", num);
    return 0;
}
TEXT 📖 للعرض فقط
Enter a number 1-10: 15
Enter a number 1-10: 0
Enter a number 1-10: 7
You entered: 7
⚠️ ملاحظة: الفاصلة المنقوطة في نهاية do-while يجب ألا تُحذف: } while (condition); نسيانها يسبب خطأ تجميع.

(1) الاختيار بين while و do-while


3. حلقة for

تجمع for بين التهيئة والتحقق من الشرط والتحديث في الرأس، مما يجعلها أكثر أشكال الحلقات شيوعًا.

C
for (initialization; condition; update) {
    loop body;
}
C
#include <stdio.h>

int main(void) {
    for (int i = 1; i <= 5; i++) {
        printf("%d ", i);
    }
    printf("\n");
    return 0;
}
TEXT 📖 للعرض فقط
1 2 3 4 5

(1) سير تنفيذ حلقة for

  1. تنفيذ التهيئة (مرة واحدة فقط)
  2. التحقق من الشرط — إذا كان خاطئًا، الخروج من الحلقة
  3. تنفيذ جسم الحلقة
  4. تنفيذ التحديث
  5. العودة إلى الخطوة 2

(2) مرونة for

يمكن حذف الأجزاء الثلاثة في for، لكن الفواصل المنقوطة يجب أن تبقى:

C
#include <stdio.h>

int main(void) {
    int i = 1;
    for (; i <= 5; ) {
        printf("%d ", i);
        i++;
    }
    printf("\n");
    return 0;
}

حذف الشرط يُنشئ حلقة لا نهائية: for (;;) {} تكافئ while (1) {}.

💡 نصيحة: فضّل حلقات for — متغير الحلقة وشرط الحد وطريقة التحديث كلها مرئية بنظرة، مما يصعّب كتابة حلقة لا نهائية بالخطأ.

(3) اعتبارات النطاق

يسمح C99 بتعريف المتغيرات في تهيئة for. هذه المتغيرات نطاقها يقتصر على حلقة for فقط:

C
#include <stdio.h>

int main(void) {
    for (int i = 0; i < 3; i++) {
        printf("i = %d\n", i);
    }
    return 0;
}

بعد انتهاء الحلقة، لم يعد i متاحًا. إذا كنت تحتاج استخدام i خارج الحلقة، عرّفه قبل for.


4. الحلقات المتداخلة

حلقة داخل حلقة أخرى هي حلقة متداخلة. كل تكرار للحلقة الخارجية يشغل الحلقة الداخلية بالكامل.

(1) طباعة مستطيل من النجوم

C
#include <stdio.h>

int main(void) {
    int rows = 3;
    int cols = 5;
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("* ");
        }
        printf("\n");
    }
    return 0;
}
TEXT 📖 للعرض فقط
* * * * *
* * * * *
* * * * *

(2) جدول الضرب

C
#include <stdio.h>

int main(void) {
    for (int i = 1; i <= 9; i++) {
        for (int j = 1; j <= i; j++) {
            printf("%d*%d=%-4d", j, i, i * j);
        }
        printf("\n");
    }
    return 0;
}
TEXT 📖 للعرض فقط
1*1=1
1*2=2   2*2=4
1*3=3   2*3=6   3*3=9
1*4=4   2*4=8   3*4=12  4*4=16
1*5=5   2*5=10  3*5=15  4*5=20  5*5=25
1*6=6   2*6=12  3*6=18  4*6=24  5*6=30  6*6=36
1*7=7   2*7=14  3*7=21  4*7=28  5*7=35  6*7=42  7*7=49
1*8=8   2*8=16  3*8=24  4*8=32  5*8=40  6*8=48  7*8=56  8*8=64
1*9=9   2*9=18  3*9=27  4*9=36  5*9=45  6*9=54  7*9=63  8*9=72  9*9=81
⚠️ ملاحظة: إجمالي عدد التكرارات في الحلقات المتداخلة هو حاصل ضرب عددي الحلقة الخارجية والداخلية. ثلاثة مستويات من التداخل قد تسبب نموًا أُسّيًا — انتبه للأداء.


5. جملة break

تخرج break فورًا من الحلقة الحالية (مستوى واحد فقط). تُتجاوز التكرارات المتبقية.

C
#include <stdio.h>

int main(void) {
    for (int i = 1; i <= 10; i++) {
        if (i == 5) {
            break;
        }
        printf("%d ", i);
    }
    printf("\nStopped at 5\n");
    return 0;
}
TEXT 📖 للعرض فقط
1 2 3 4
Stopped at 5

(1) إيجاد أول عنصر يحقق شرطًا

C
#include <stdio.h>

int main(void) {
    int nums[] = {3, 7, 2, 9, 5, 1};
    int target = 9;
    int found = 0;
    for (int i = 0; i < 6; i++) {
        if (nums[i] == target) {
            printf("Found %d at index %d\n", target, i);
            found = 1;
            break;
        }
    }
    if (!found) {
        printf("%d not found\n", target);
    }
    return 0;
}
TEXT 📖 للعرض فقط
Found 9 at index 3

6. جملة continue

تتجاوز continue الجمل المتبقية في التكرار الحالي وتنتقل إلى التكرار التالي (العودة إلى خطوة التحقق أو التحديث).

C
#include <stdio.h>

int main(void) {
    for (int i = 1; i <= 10; i++) {
        if (i % 3 == 0) {
            continue;
        }
        printf("%d ", i);
    }
    printf("\nMultiples of 3 skipped\n");
    return 0;
}
TEXT 📖 للعرض فقط
1 2 4 5 7 8 10
Multiples of 3 skipped
⚠️ ملاحظة: عند استخدام continue في حلقتي while و do-while، تأكد أن جملة التحديث تأتي قبل continue، وإلا قد تُنشئ حلقة لا نهائية.


7. أنماط التكرار الشائعة

(1) نمط العد

عدّ عدد العناصر التي تحقق شرطًا:

C
#include <stdio.h>

int main(void) {
    int nums[] = {12, 45, 3, 67, 89, 23, 56};
    int count = 0;
    for (int i = 0; i < 7; i++) {
        if (nums[i] > 50) {
            count++;
        }
    }
    printf("Numbers greater than 50: %d\n", count);
    return 0;
}
TEXT 📖 للعرض فقط
Numbers greater than 50: 3

(2) نمط التراكم

جمع سلسلة من القيم:

C
#include <stdio.h>

int main(void) {
    int sum = 0;
    for (int i = 1; i <= 100; i++) {
        sum += i;
    }
    printf("Sum from 1 to 100: %d\n", sum);
    return 0;
}
TEXT 📖 للعرض فقط
Sum from 1 to 100: 5050

(3) نمط البحث

إيجاد أول عنصر يحقق شرطًا، ثم الخروج بـ break:

راجع مثال break السابق.

(4) نمط الاجتياز

معالجة كل عنصر في مصفوفة بالتسلسل:

C
#include <stdio.h>

int main(void) {
    int scores[] = {85, 92, 78, 96, 61};
    int len = 5;
    for (int i = 0; i < len; i++) {
        printf("Student%d: %d %s\n", i + 1, scores[i], scores[i] >= 60 ? "Pass" : "Fail");
    }
    return 0;
}
TEXT 📖 للعرض فقط
Student1: 85 Pass
Student2: 92 Pass
Student3: 78 Pass
Student4: 96 Pass
Student5: 61 Pass

8. الحلقات اللا نهائية وكيفية تجنبها

الحلقة اللا نهائية هي التي شرطها دائمًا صحيح. الحلقات اللا نهائية المتعمدة تستخدم for(;;) أو while(1)، مع break بداخلها للخروج:

C
#include <stdio.h>

int main(void) {
    int num;
    while (1) {
        printf("Enter a number (0 to quit): ");
        scanf("%d", &num);
        if (num == 0) {
            break;
        }
        printf("You entered: %d\n", num);
    }
    printf("Goodbye!\n");
    return 0;
}

تحدث الحلقات اللا نهائية غير المتعمدة عادةً لأن متغير الحلقة لا يُحدَّث أبدًا أو يُحدَّث بالاتجاه الخاطئ:

TEXT 📖 للعرض فقط
int i = 0;
while (i < 10) {
    printf("%d", i);
}
⚠️ ملاحظة: إذا بدا أن برنامجك "تجمّد"، أول شيء يجب الاشتباه به هو حلقة لا نهائية. اضغط Ctrl+C لإنهائه قسرًا.

▶ مثال

طباعة مثلث قائم باستخدام حلقات متداخلة:

C
#include <stdio.h>

int main(void) {
    int n = 5;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= i; j++) {
            printf("* ");
        }
        printf("\n");
    }
    return 0;
}
▶ جرّب الكود
TEXT 📖 للعرض فقط
*
* *
* * *
* * * *
* * * * *

▶ مثال

إيجاد القاسم المشترك الأكبر لعددين صحيحين موجبين باستخدام خوارزمية إقليدس، مع عرض حلقة while بعدد تكرارات غير محدد:

C
#include <stdio.h>

int main(void) {
    int a = 48, b = 18;
    int orig_a = a, orig_b = b;
    while (b != 0) {
        int temp = a % b;
        a = b;
        b = temp;
    }
    printf("GCD of %d and %d is %d\n", orig_a, orig_b, a);
    return 0;
}
▶ جرّب الكود
TEXT 📖 للعرض فقط
GCD of 48 and 18 is 6

9. الاختيار بين الحلقات الثلاث

الموقف التوصية
عدد تكرارات محدد for
يجب التنفيذ مرة واحدة على الأقل do-while
عدد تكرارات غير محدد while
قائمة تفاعلية do-while + switch
💡 نصيحة: يمكن التحويل المنطقي بين الحلقات الثلاث جميعها. اختر الأنسب لحالتك.


❓ أسئلة شائعة

س هل أستخدم for أم while؟
ج استخدم for عندما يكون عدد التكرارات معروفًا، و while عندما لا يكون معروفًا. هذا هو الدليل الأكثر قبولًا.
س هل يمكن لـ break الخروج من عدة مستويات من الحلقات؟
ج لا. break تخرج فقط من الحلقة الأعمق. للخروج من عدة مستويات، استخدم متغير علم مع تحقق في الحلقة الخارجية، أو goto (غير مستحسن لكنه عملي أحيانًا).
س أيهما أفضل: for(;;) أم while(1)؟
ج متكافئتان وظيفيًا. while(1) أوضح قراءة؛ for(;;) هو أسلوب C تقليدي. اختر وفقًا لاصطلاحات فريقك.
س هل من الجيد استخدام i و j و k كمتغيرات حلقة؟
ج في الحلقات البسيطة، هذا اصطلاح مقبول على نطاق واسع. لكن عندما يكون للمتغير معنى وظيفي (مثلًا row أو col أو student_index)، فالاسم الوصفي أفضل.

📖 ملخص

📝 تمارين

  1. اكتب برنامجًا باستخدام حلقة for لحساب مجموع المضروبات: 1! + 2! + 3! + ... + 10!.
  2. اكتب برنامجًا باستخدام حلقات متداخلة لطباعة مثلث قائم مقلوب (5 صفوف، 5 نجوم في الصف الأول، نجمة واحدة في الصف الخامس).
  3. اكتب برنامجًا يقرأ عددًا صحيحًا موجبًا ويطبع أرقامه بترتيب عكسي (مثلًا: الإدخال 1234 يُخرج 4 3 2 1).
Web-Tutorial.com

فريق Web-Tutorial التقني

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

100%