ما هي دالة getchar في لغة C؟ شرح مفصل وأمثلة عملية للمبتدئين

1. ما هي دالة getchar؟

تُعد دالة getchar واحدة من أبسط طرق الإدخال في لغة C، حيث تقوم بقراءة حرف واحد من الإدخال القياسي (لوحة المفاتيح). تُرجع هذه الدالة القيمة الرقمية (كود ASCII) للحرف الذي أدخله المستخدم، لذا فهي مفيدة عند الحاجة إلى معالجة إدخال بسيط. غالبًا ما تُستخدم عندما تريد معالجة كل حرف يُدخله المستخدم بشكل منفصل.

خصائص دالة getchar

  • الحصول على حرف واحد من الإدخال القياسي: تنتظر الدالة حتى ينتهي المستخدم من إدخال الحرف ويضغط Enter، ثم تبدأ المعالجة.
  • ترجع كود ASCII: الحرف المُدخل يُرجع كقيمة رقمية (ASCII)، ولعرضه كحرف يجب تحويله (cast) إلى نوع حرفي.

تُعتبر getchar مثالية لمعالجة الإدخال البسيط من المستخدم أو في البرامج التفاعلية. وبسبب سهولة استخدامها، فهي شائعة بين المبتدئين عند تعلم لغة C.

مثال على الاستخدام

فيما يلي مثال بسيط لاستخدام getchar لقراءة حرف من المستخدم.

#include <stdio.h>

int main() {
    int c;
    printf("أدخل حرفًا: ");
    c = getchar();
    printf("الحرف الذي أدخلته: %c
", c);
    return 0;
}

في هذا البرنامج، يتم قراءة حرف واحد من لوحة المفاتيح وعرضه على الشاشة. فعلى سبيل المثال، إذا أدخلت “A” ستكون النتيجة كما يلي:

أدخل حرفًا: A
الحرف الذي أدخلته: A

2. الاستخدام الأساسي لدالة getchar

كيفية الاستدعاء الأساسية

يتم استدعاء دالة getchar بهذه الطريقة:

int getchar(void);

لا تأخذ الدالة أي معاملات وتقوم بإرجاع كود ASCII للحرف المدخل كقيمة عددية من نوع int. إذا حدث خطأ، يتم إرجاع EOF (نهاية الملف).

مثال على إدخال حرف بسيط

في المثال السابق، استخدمنا getchar لقراءة حرف واحد وعرضه. هذه الطريقة مفيدة عندما تحتاج إلى معالجة حرف واحد فقط.

#include <stdio.h>

int main() {
    int c;
    printf("أدخل حرفًا: ");
    c = getchar();
    printf("الحرف الذي أدخلته: %c
", c);
    return 0;
}

في هذا الكود، يتم قراءة الحرف بواسطة getchar ثم يتم عرضه باستخدام printf.

3. أمثلة متقدمة على استخدام getchar

EOF (نهاية الملف) مع getchar

لا تقتصر دالة getchar على قراءة الحروف فقط، بل تستطيع أيضًا التعرف على نهاية الإدخال عند وصول EOF (نهاية الملف). على سبيل المثال، عند إدخال “Ctrl+Z” في ويندوز أو “Ctrl+D” في يونكس يمكن الكشف عن EOF.

فيما يلي مثال لبرنامج يقرأ الحروف حتى يتم إدخال EOF:

#include <stdio.h>

int main() {
    int c;
    printf("أدخل الحروف (لإنهاء الإدخال، أدخل EOF): ");
    while ((c = getchar()) != EOF) {
        putchar(c);
    }
    return 0;
}

يستخدم هذا البرنامج دالتي getchar وputchar لقراءة كل حرف من المستخدم وإظهاره مباشرة حتى يتم إدخال EOF.

إدخال عدة حروف

يمكنك أيضًا قراءة عدة حروف باستخدام getchar. في المثال التالي، يتم قراءة وعرض كل الحروف حتى يتم إدخال حرف السطر الجديد.

#include <stdio.h>

int main() {
    int c;
    printf("أدخل سلسلة نصية: ");
    while ((c = getchar()) != '\n') {
        printf("الحرف المُدخل: %c\n", c);
    }
    return 0;
}

يقرأ هذا البرنامج الحروف واحدًا تلو الآخر ويعرضها حتى يتم إدخال سطر جديد (Enter).

4. EOF ومعالجة الذاكرة المؤقتة (Buffer)

دور EOF

EOF (نهاية الملف) تعني نهاية الإدخال من ملف أو من لوحة المفاتيح. عند الوصول إلى EOF، تقوم دالة getchar بإرجاع القيمة -1، ليتمكن البرنامج من إنهاء المعالجة. عادةً يُستخدم EOF للدلالة على نهاية الملف، لكن في الإدخال من لوحة المفاتيح يمكن إدخاله يدويًا.

Buffering ودالة getchar

نظرًا لأن دالة getchar تعتمد على وجود ذاكرة مؤقتة (buffer)، يتم حفظ جميع الحروف التي يُدخلها المستخدم حتى يتم الضغط على Enter. عند استدعاء getchar عدة مرات، يتم قراءة الحروف التالية من الذاكرة المؤقتة. لذلك، أحيانًا لا تنتقل المعالجة حتى يتم إدخال حرف السطر الجديد.

لتجاهل أحرف السطر الجديد الموجودة في الذاكرة المؤقتة، يمكن إضافة الكود التالي:

#include <stdio.h>

int main() {
    int c;
    printf("أدخل حرفًا: ");
    c = getchar();
    while (getchar() != '\n');  // تجاهل أحرف السطر الجديد المتبقية في الذاكرة المؤقتة
    printf("الحرف المُدخل: %c\n", c);
    return 0;
}

يوضح هذا المثال كيفية تجاوز أحرف السطر الجديد قبل عرض الحرف المُدخل.

5. مقارنة دالة getchar مع دوال الإدخال الأخرى

الفرق بين getchar وscanf

كل من getchar وscanf يُستخدمان لقراءة الإدخال، لكن هناك اختلاف كبير في طريقة الاستعمال. تتيح scanf قراءة أنواع بيانات متعددة مثل الأعداد أو السلاسل النصية باستخدام صيغ خاصة، بينما getchar تُستخدم فقط لقراءة حرف واحد من الإدخال القياسي.

مثال على إدخال باستخدام scanf:

#include <stdio.h>

int main() {
    int num;
    printf("أدخل رقمًا: ");
    scanf("%d", &num);
    printf("الرقم المُدخل: %d\n", num);
    return 0;
}

في هذا المثال، يتم قراءة عدد صحيح من المستخدم وعرضه. تتيح scanf إدخال عدة أنواع من البيانات دفعة واحدة.

الفرق بين getchar وfgets

على عكس getchar، تتيح fgets قراءة سلسلة نصية كاملة (عدة حروف) دفعة واحدة من الإدخال القياسي. كما يمكنك تحديد حجم الذاكرة المؤقتة، وبالتالي تجنب أخطاء تجاوز الذاكرة التي قد تحدث مع scanf.

مثال على إدخال باستخدام fgets:

#include <stdio.h>

int main() {
    char str[100];
    printf("أدخل سلسلة نصية: ");
    fgets(str, sizeof(str), stdin);
    printf("السلسلة المُدخلة: %s", str);
    return 0;
}

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

متى تستخدم getchar، scanf، أو fgets؟

  • getchar: مناسبة عند الحاجة لقراءة حرف واحد فقط، مثل الاختيار من قائمة أو عند التعامل مع أوامر بسيطة.
  • scanf: مفيدة لقراءة أنواع بيانات متعددة، لكنها تحتاج إلى معالجة الأخطاء بعناية.
  • fgets: مثالية لقراءة سلاسل نصية طويلة أو إدخال متعدد الأسطر، كما تتيح تحديد حجم الذاكرة المؤقتة للحماية من تجاوز السعة.

6. أمثلة تطبيقية: برامج تفاعلية باستخدام getchar

تُستخدم دالة getchar بشكل شائع في بناء برامج تفاعلية تعتمد على إدخال المستخدم، مثل القوائم أو الألعاب البسيطة. فيما يلي مثال على كيفية بناء قائمة تفاعلية:

كود نموذجي: تنفيذ القوائم حسب إدخال الحرف

#include <stdio.h>

int main() {
    char choice;
    printf("اختر من القائمة (a: مرحبًا, b: إنهاء): ");
    choice = getchar();

    switch (choice) {
        case 'a':
            printf("مرحبًا بك!\n");
            break;
        case 'b':
            printf("سيتم إنهاء البرنامج.\n");
            break;
        default:
            printf("اختيار غير صالح.\n");
    }

    return 0;
}

في هذا البرنامج، يؤدي إدخال المستخدم للحرف ‘a’ أو ‘b’ إلى إظهار رسالة مختلفة حسب الاختيار. تُستخدم getchar لبناء قوائم أو التعامل مع الأوامر البسيطة.

برنامج متقدم: التعامل مع عدة أوامر

يوضح الكود التالي كيفية تنفيذ إجراءات مختلفة بناءً على إدخال المستخدم لحروف معينة:

#include <stdio.h>

int main() {
    char command;
    printf("أدخل أمرًا (l: عرض القائمة, h: التحية, q: إنهاء): ");
    command = getchar();

    switch (command) {
        case 'l':
            printf("سيتم عرض القائمة.\n");
            break;
        case 'h':
            printf("مرحبًا بك!\n");
            break;
        case 'q':
            printf("سيتم إنهاء البرنامج.\n");
            break;
        default:
            printf("أمر غير صالح.\n");
    }

    return 0;
}

يعرض هذا البرنامج رسائل مختلفة حسب الحرف الذي يدخله المستخدم (l، h، q).

7. ملاحظات مهمة وأفضل الممارسات مع getchar

مشكلات شائعة: التعامل مع الذاكرة المؤقتة

من المشاكل الشائعة عند استخدام getchar أن الحروف المتبقية (خاصة أحرف السطر الجديد) قد تؤثر على عملية الإدخال التالية. على سبيل المثال، بعد قراءة حرف واحد، قد تقرأ الدالة حرف السطر الجديد في المرة التالية مباشرة. لتجنب ذلك، يجب تنظيف الذاكرة المؤقتة.

كيفية تجاهل أحرف السطر الجديد:

#include <stdio.h>

int main() {
    int c;
    printf("أدخل حرفًا: ");
    c = getchar();
    while (getchar() != '\n');  // تجاهل أحرف السطر الجديد
    printf("الحرف المُدخل: %c\n", c);
    return 0;
}

يضيف هذا الكود حلقة لتجاهل أحرف السطر الجديد المتبقية في الذاكرة المؤقتة بعد الإدخال الأساسي.

أفضل الممارسات

  1. تنظيف الذاكرة المؤقتة: تأكد من التعامل مع أحرف السطر الجديد المتبقية لمنع التأثير على الإدخالات التالية.
  2. معالجة الأخطاء: تحقق دائمًا من القيمة المُعادة من getchar إذا كانت EOF، خاصة عند قراءة البيانات من ملف.
  3. تحديد الإدخال: في حالات إدخال السلاسل الطويلة أو المتطلبات الخاصة، يُفضل استخدام fgets لضبط حجم الذاكرة المؤقتة وتجنب تجاوز السعة.

8. الخلاصة والخطوات التالية

شرحنا في هذا المقال كيفية استخدام دالة getchar من الأساسيات إلى الأمثلة العملية، وكذلك مقارنة مع دوال الإدخال الأخرى مثل scanf وfgets. تُعد getchar أداة قوية وبسيطة لمعالجة الإدخال في برامج لغة C، خصوصًا في البرامج التفاعلية أو عند الحاجة لمعالجة إدخال بسيط.

الخطوات التالية للتعلم

  1. تعلم المزيد حول fgets وscanf: لفهم كيفية قراءة السلاسل النصية أو الأعداد بشكل متقدم، تعمق في استخدام fgets وscanf.
  2. استخدام إدخال الملفات: لا تقتصر getchar على الإدخال القياسي فقط، بل يمكن استخدامها أيضًا لقراءة البيانات من الملفات.
  3. تطبيق معالجة الأخطاء: درّب على التعامل مع حالات الخطأ، خاصة التعامل مع EOF أو الإدخالات غير الصحيحة، لجعل برامجك أكثر متانة.

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

侍エンジニア塾