C: الإدخال والإخراج

الإدخال والإخراج أشبه بمحادثة بينك وبين الحاسوب - printf هو الحاسوب يتحدث معك، و scanf هو أنت تتحدث مع الحاسوب. أصب التنسيق، وإلا س تتحدثان بلا تفاهم.

1. إخراج printf المنسق

يرمز printf إلى "print formatted" (طباعة منسقة). وسيطته الأولى هي سلسلة تنسيق، تليها القيم المراد إخراجها.

(1) محددات التنسيق الأساسية

المحدد الغرض مثال المخرجات
%d عدد صحيح عشري printf("%d", 42) 42
%f فاصلة عائمة printf("%f", 3.14) 3.140000
%c محرف واحد printf("%c", 'A') A
%s سلسلة نصية printf("%s", "hi") hi
%x سداسي عشري printf("%x", 255) ff
%o ثماني printf("%o", 8) 10
%p عنوان المؤشر printf("%p", &a) قيمة العنوان
%% علامة نسبة حرفية printf("100%%") 100%
C
#include <stdio.h>

int main(void) {
    int age = 25;
    float height = 175.5f;
    char grade = 'A';
    printf("العمر: %d، الطول: %.1f، التقدير: %c\n", age, height, grade);
    return 0;
}
TEXT 📖 للعرض فقط
العمر: 25، الطول: 175.5، التقدير: A

(2) العرض والمحاذاة

يمكنك إدراج أرقام بين % ومحدد التنسيق للتحكم في عرض المخرجات:

C
#include <stdio.h>

int main(void) {
    int num = 42;
    printf("[%5d]\n", num);
    printf("[%-5d]\n", num);
    printf("[%05d]\n", num);
    printf("[%+5d]\n", num);
    return 0;
}
TEXT 📖 للعرض فقط
[   42]
[42   ]
[00042]
[  +42]

(3) دقة الفاصلة العائمة

C
#include <stdio.h>

int main(void) {
    double pi = 3.14159265358979;
    printf("افتراضي:  %f\n", pi);
    printf("منزلتان: %.2f\n", pi);
    printf("6 منازل: %.6f\n", pi);
    printf("8.2:      %8.2f\n", pi);
    return 0;
}
TEXT 📖 للعرض فقط
افتراضي:  3.141593
منزلتان: 3.14
6 منازل: 3.141593
8.2:          3.14
💡 نصيحة: %f افتراضيا 6 منازل عشرية. استخدم %.0f لإخفاء الجزء العشري بالكامل.


2. قراءة الإدخال بـ scanf

يرمز scanf إلى "scan formatted" (مسح منسق). يقرأ البيانات من المدخلات القياسية وفقا لسلسلة التنسيق ويخزنها في متغيرات.

(1) الاستخدام الأساسي

C
#include <stdio.h>

int main(void) {
    int age;
    float score;
    printf("أدخل عمرك: ");
    scanf("%d", &age);
    printf("أدخل درجتك: ");
    scanf("%f", &score);
    printf("العمر: %d، الدرجة: %.1f\n", age, score);
    return 0;
}
TEXT 📖 للعرض فقط
أدخل عمرك: 20
أدخل درجتك: 92.5
العمر: 20، الدرجة: 92.5
⚠️ ملاحظة: وسائط scanf المتغيرة يجب أن تسبق بـ & (معامل أخذ العنوان)، تخبر scanf "خزّن القيمة في هذا العنوان." نسيان & هو أكثر أخطاء المبتدئين شيوعا - البرنامج لن يُخطئ لكنه سينهار.

(2) قراءة عدة قيم

C
#include <stdio.h>

int main(void) {
    int a, b, c;
    printf("أدخل ثلاثة أعداد صحيحة (مفصولة بمسافات): ");
    scanf("%d %d %d", &a, &b, &c);
    printf("أدخلت: %d، %d، %d\n", a, b, c);
    return 0;
}
TEXT 📖 للعرض فقط
أدخل ثلاثة أعداد صحيحة (مفصولة بمسافات): 10 20 30
أدخلت: 10، 20، 30

افتراضيا، يستخدم scanf المسافات البيضاء (مسافات، أسطر جديدة، جدولات) لفصل القيم المختلفة.

(3) قراءة المحارف والسلاسل النصية

C
#include <stdio.h>

int main(void) {
    char ch;
    char name[20];
    printf("أدخل محرفا: ");
    scanf(" %c", &ch);
    printf("أدخل اسمك (بدون مسافات): ");
    scanf("%s", name);
    printf("المحرف: %c، الاسم: %s\n", ch, name);
    return 0;
}
⚠️ ملاحظة: إضافة مسافة قبل %c (" %c") تتجاوز محارف المسافات البيضاء، وإلا ستقرأ سطرا جديدا متبقيا من إدخال سابق. %s يقرأ سلسلة نصية لكنه يتوقف عند المسافة البيضاء. name اسم مصفوفة، وهو بالفعل عنوان، لذا لا حاجة لـ &.

(4) القيمة المرجعة لـ scanf

تُرجع scanf عدد المتغيرات المقروءة بنجاح. يمكن استخدام هذه الميزة للتحقق من صحة الإدخال:

C
#include <stdio.h>

int main(void) {
    int num;
    printf("أدخل عددا صحيحا: ");
    int result = scanf("%d", &num);
    if (result == 1) {
        printf("تمت القراءة بنجاح: %d\n", num);
    } else {
        printf("إدخال غير صالح!\n");
    }
    return 0;
}
TEXT 📖 للعرض فقط
أدخل عددا صحيحا: abc
إدخال غير صالح!

3. getchar و putchar

getchar() تقرأ محرفا واحدا من لوحة المفاتيح، و putchar() تُخرج محرفا واحدا إلى الشاشة. هما أبسط وأكفأ من scanf("%c") و printf("%c").

C
#include <stdio.h>

int main(void) {
    char ch;
    printf("أدخل محرفا: ");
    ch = getchar();
    printf("أدخلت: ");
    putchar(ch);
    putchar('\n');
    return 0;
}
TEXT 📖 للعرض فقط
أدخل محرفا: X
أدخلت: X

(1) قراءة سطر كامل

getchar() مع حلقة يمكنها قراءة سطر كامل حتى يُصادف سطر جديد:

C
#include <stdio.h>

int main(void) {
    char ch;
    printf("أدخل سطرا من النص: ");
    while ((ch = getchar()) != '\n') {
        putchar(ch);
    }
    putchar('\n');
    return 0;
}
TEXT 📖 للعرض فقط
أدخل سطرا من النص: مرحبا بالعالم!
مرحبا بالعالم!
💡 نصيحة: while ((ch = getchar()) != '\n') أسلوب كلاسيكي: اقرأ محرفا أولا في ch، ثم تحقق إن كان سطرا جديدا. لاحظ أن الأقواس الخارجية حول الإسناد إلزامية.


4. مشاكل المخزن المؤقت

المدخلات القياسية في C تستخدم التخزين المؤقت السطري: لا يُسلّم سطر البيانات بالكامل إلى المخزن المؤقت ليقرأه البرنامج إلا بعد أن يضغط المستخدم Enter. هذا يمكن أن يسبب بعض المشاكل المحيرة.

(1) المشكلة: scanf %c تقرأ سطرا جديدا متبقيا

C
#include <stdio.h>

int main(void) {
    int num;
    char ch;
    printf("أدخل عددا صحيحا: ");
    scanf("%d", &num);
    printf("أدخل محرفا: ");
    scanf("%c", &ch);
    printf("العدد=%d، المحرف=%d\n", num, ch);
    return 0;
}
TEXT 📖 للعرض فقط
أدخل عددا صحيحا: 42
أدخل محرفا: العدد=42، المحرف=10

بعد كتابة 42 والضغط على Enter، المخزن المؤقت يحتوي على 42\n. يقرأ scanf("%d") الرقم 42، بينما يقرأ scanf("%c") فورا الـ \n المتبقي (كود ASCII 10)، دون انتظارك لكتابة محرف.

(2) الحلول

الحل 1: إضافة مسافة قبل %c (موصى به)

TEXT 📖 للعرض فقط
scanf(" %c", &ch);

المسافة تتجاوز جميع محارف المسافات البيضاء (بما فيها الأسطر الجديدة والمسافات والجدولات).

الحل 2: استخدام getchar() لامتصاص المتبقي

C
scanf("%d", &num);
getchar();
scanf("%c", &ch);

الحل 3: تفريغ مخزن الإدخال المؤقت

TEXT 📖 للعرض فقط
int c;
while ((c = getchar()) != '\n' && c != EOF) {}
⚠️ ملاحظة: لا تستخدم fflush(stdin) لتفريغ مخزن الإدخال المؤقت - إنه سلوك غير معرف في معيار C. بعض المترجمات تدعمه، لكنه غير قابل للنقل.

▶ مثال

اكتب برنامجا يقرأ عددا صحيحا ومحرفا، مع معالجة متبقيات المخزن المؤقت بشكل صحيح:

C
#include <stdio.h>

int main(void) {
    int age;
    char gender;
    printf("أدخل عمرك: ");
    scanf("%d", &age);
    printf("أدخل جنسك (ذ/م): ");
    scanf(" %c", &gender);
    printf("العمر: %d، الجنس: %c\n", age, gender);
    return 0;
}
▶ جرّب الكود
TEXT 📖 للعرض فقط
أدخل عمرك: 25
أدخل جنسك (ذ/م): ذ
العمر: 25، الجنس: ذ

▶ مثال

استخدم getchar() لقراءة المحارف واحدا تلو الآخر وعد عدد الحروف والأرقام في سطر:

C
#include <stdio.h>

int main(void) {
    char ch;
    int letters = 0;
    int digits = 0;
    printf("أدخل سطرا من النص: ");
    while ((ch = getchar()) != '\n') {
        if (ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {
            letters++;
        } else if (ch >= '0' && ch <= '9') {
            digits++;
        }
    }
    printf("حروف: %d، أرقام: %d\n", letters, digits);
    return 0;
}
▶ جرّب الكود
TEXT 📖 للعرض فقط
أدخل سطرا من النص: Hello 2024!
حروف: 5، أرقام: 4

5. puts و fputs

puts() تُخرج سلسلة نصية وتُضيف تلقائيا سطرا جديدا. هي أبسط من printf ومثالية لإخراج النص البسيط:

C
#include <stdio.h>

int main(void) {
    puts("مرحبا بالعالم!");
    puts("سطر جديد تلقائي، لا حاجة لـ \\n");
    return 0;
}
TEXT 📖 للعرض فقط
مرحبا بالعالم!
سطر جديد تلقائي، لا حاجة لـ \n
💡 نصيحة: puts() أكفأ من printf("%s\n", ...) لأنها لا تحتاج لتحليل سلسلة تنسيق. حين لا تحتاج تنسيقا، فضّل puts.


❓ أسئلة شائعة

س لماذا تحتاج وسائط scanf إلى & أمامها؟
ج scanf تحتاج لمعرفة مكان تخزين القيمة، و & يأخذ عنوان المتغير. فقط أسماء المصفوفات لا تحتاجه، لأن اسم المصفوفة هو بالفعل عنوان أول عنصر فيها.
س scanf("%c") تجاوزت إدخالي - ماذا حدث؟
ج هناك سطر جديد متبقٍ في المخزن المؤقت من إدخال سابق. أضف مسافة قبل %c: scanf(" %c", &ch) لتجاوز المسافات البيضاء.
س هل يمكن أن تكون محددات تنسيق printf و scanf بأحرف كبيرة؟
ج بعضها يمكن. %d الصغيرة تقابل int؛ %D الكبيرة غير قياسية. لكن %x تطبع سداسي عشري بأحرف صغيرة (abcdef) بينما %X تطبع بأحرف كبيرة (ABCDEF) - هذا صالح.
س كيف أقرأ سلسلة نصية بمسافات بأمان؟
ج scanf("%s") يتوقف عند المسافة البيضاء. استخدم fgets(name, sizeof(name), stdin) لقراءة سطر كامل - يدعم المسافات وهو أكثر أمانا.

📖 ملخص

📝 تمارين

  1. اكتب برنامجا يقرأ نصف قطر دائرة ويُخرج مساحتها ومحيطها باستخدام تنسيق %.2f في printf.
  2. اكتب برنامجا يستخدم getchar() لقراءة سطر من الإدخال ويعد عدد الحروف الكبيرة والصغيرة التي يحتويها.
  3. اكتب برنامجا يقرأ عددا صحيحا ويُخرجه بالصيغ العشرية (%d) والسداسية عشرية (%x) والثمانية (%o).
Web-Tutorial.com

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

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

100%