4·1

مقدمة الإدخال والإخراج + طباعة بأناقة

حتى الآن كانت برامجنا تتحدث وحدها — تطبع على الشاشة ولا تسمع أحدًا. هذه الوحدة تعلّمها الاستماع.

كل برنامج له قناتان أساسيتان مع العالم الخارجي: الإخراج (Output) — ما يظهر على الشاشة، وقد استخدمناه منذ الدرس الأول عبر System.out.print وprintln (وفرّق بينهما في جدول المقارنة في درس 1·2)، والإدخال (Input) — ما يكتبه المستخدم أثناء التشغيل، وسنفتحه في الدرس التالي.

قبل أن نفتح باب الإدخال، لنتقن الإخراج أولًا. أحيانًا نريد طباعة نص يحتوي سطرًا جديدًا أو علامة تنصيص داخل النص نفسه — هنا تظهر رموز الهروب (Escape Characters): شرطة مائلة خلفية تليها حرف واحد، يفهمها جافا كأمر تنسيق:

الرمزاسمهماذا يفعل
\nسطر جديد (newline)ينزل إلى بداية السطر التالي — مثل println من داخل النص
\tجدولة (tab)مسافة بادئة تُنظم الأعمدة في الطباعة
\"علامة تنصيصيطبع " بدون أن يظن جافا أن النص انتهى
\\شرطة مائلةيطبع \ نفسها — لأن كتابة \ وحدها تُفسَّر بداية رمز هروب
EscapeChars.java
public class EscapeChars {    public static void main(String[] args) {        System.out.println("سطر أول\nسطر ثانٍ");        System.out.println("عمود1\tعمود2\tعمود3");        System.out.println("مسار الملف: C:\\Users\\Sara");        System.out.println("قال المعلم: \"جافا ممتعة\"");    }}

اقرأ المثال سطرًا سطرًا

  • النص الأول يحمل \n في منتصفه — لاحظ أن المخرجات تنقسم على سطرين رغم أننا استخدمنا println مرة واحدة.
  • \t تترك مسافة جدولة واسعة بين «عمود1» و«عمود2» — أساس تنسيق الجداول النصية قبل أن نتعرف على printf.
  • في مسار الملف كتبنا \\ لأن \U وحدها ليست رمز هروب صالحًا — جافا الحقيقية ترفضها بخطأ ترجمة (illegal escape character)، لذلك يجب مضاعفة الشرطة المائلة دائمًا عند طباعتها.
  • \" تسمح بعلامتي تنصيص داخل النص — تذكّر أنها بديل الدرس 3·1 الذي شرحنا فيه \" بالفعل، والآن تعرف اسمها: رمز هروب.
تلميحشغّل المثال وراقب المخرجات سطرًا سطرًا — ثم اضغط «✎ تعديل» وجرّب إضافة \t أو \n في أماكن أخرى من النصوص وشاهد كيف يتغير الشكل.
اختبر نفسك · +5 نقاط
ما ناتج System.out.print("أ\nب"); ؟
اختبر نفسك ٢ · حتى +5 نقاط
أي سطر يطبع المسار C:\Users بشكل صحيح؟
اختبر نفسك ٣ · حتى +5 نقاط
ماذا يظهر عند تنفيذ هذا الكود؟
System.out.print("A");
System.out.println("B");
System.out.print("C");
4·2

كلاس Scanner وقراءة المدخلات

الآن نفتح باب الإدخال: برنامج يسأل المستخدم سؤالًا ويتوقف منتظرًا إجابته، ثم يكمل التنفيذ بناءً عليها.

تخيّل موظف استقبال في مكتبة: يقف عند الباب، يستقبل كل قادم ويسجّل ما يقوله في الاستمارة. في جافا هذا الموظف هو Scanner — كلاس جاهز يقرأ ما يكتبه المستخدم على لوحة المفاتيح. ثلاث خطوات ثابتة في كل برنامج:

  • في أول السطر الأول: import java.util.Scanner; — أمر للمترجم أن يجلب كلاس Scanner من مكتبة جافا الجاهزة.
  • داخل main ننشئ الموظف: Scanner sc = new Scanner(System.in); — حيث System.in تعني «اقرأ من لوحة المفاتيح».
  • ثم نستدعيه متى شئنا: sc.nextInt() وغيرها من ميثودات القراءة.
١ — نستدعي الكلاس من مكتبة جافا مكتبة جافا الجاهزة java.util Scanner برنامجك import java.util.Scanner; «أحضِر لي وصف الوظيفة» الكلاس مجرد وصف للوظيفة — لا يوجد موظف يعمل بعد ٢ — نوظّف موظفًا حقيقيًا (ننشئ كائنًا) Scannersc=new Scanner(System.in); النوع (الوظيفة) اسم الموظف — تختاره أنت new = وظِّف موظفًا جديدًا مكان عمله: لوحة المفاتيح sc كائن حقيقي جاهز للعمل ٣ — نناديه باسمه ونطلب منه أن يقرأ المستخدم يكتب 17 sc.nextInt() «اقرأ لي رقمًا» int age = 17 تُحفظ في المتغير النقطة بعد الاسم تعني: «نادِ هذا الموظف ونفِّذ له طلبًا» الاسم يختاره المبرمج — ولو سمّيته reader لناديناه باسمه الجديد
الكلاس Scanner وصف للوظيفة، والكائن sc موظف حقيقي نناديه باسمه كلما احتجنا قراءة
توقّف وفكّرلو أنشأنا الموظف هكذا: Scanner input = new Scanner(System.in); — كيف نطلب منه قراءة سطر نصي كامل؟
اكشف الإجابة input.nextLine() — نناديه باسمه الجديد input؛ فالاسم يختاره المبرمج، أما الموظف وميثوداته فهي نفسها.
الميثودتقرأ ماذا؟تُخزَّن في
sc.nextInt()رقمًا صحيحًا (int)int age = sc.nextInt();
sc.nextDouble()رقمًا عشريًا (double)double price = sc.nextDouble();
sc.nextLine()سطرًا كاملًا حتى نهايتهString name = sc.nextLine();
sc.next()كلمة واحدة فقط (حتى أول مسافة)String word = sc.next();
sc.nextBoolean()true أو false — في جافا الكاملة(غير متاحة في بيئة الورشة)
كيف يعمل الإدخال هنا؟عند ضغط «▶ تشغيل» على أي مثال في هذا الدرس سيسألك المتصفح بنافذة إدخال — سؤال واحد لكل سطر تكتبه فيه إجابتك. اكتب القيمة ثم اضغط موافق، وكرر لكل سؤال حتى يكتمل البرنامج.

أول برنامج: يقرأ رقمين ويطبع مجموعهما — لاحظ أن كل ميثود قراءة تتوقف وتنتظر إجابتك:

SumTwo.java
import java.util.Scanner;public class SumTwo {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        System.out.print("أدخل الرقم الأول: ");        int a = sc.nextInt();        System.out.print("أدخل الرقم الثاني: ");        int b = sc.nextInt();        System.out.println("المجموع: " + (a + b));    }}

وماذا لو كتب المستخدم أكثر من قيمة في سطر واحد؟ ميثودات القراءة الرقمية والكلمة تتجاهل المسافات وتقرأ الرموز واحدًا واحدًا — جرّب إدخال «7 5» في السؤال الأول وسترى البرنامج يقرأهما معًا:

TwoOnOneLine.java
import java.util.Scanner;public class TwoOnOneLine {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        System.out.println("أدخل رقمين على سطر واحد:");        int a = sc.nextInt();        int b = sc.nextInt();        System.out.println("قرأت " + a + " و " + b + " — المجموع " + (a + b));    }}

ولقراءة نص وعدد من نفس السطر، وقراءة سعر عشري مع كمية:

GreetUser.java
import java.util.Scanner;public class GreetUser {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        System.out.print("اكتب اسمك وعمرك مفصولين بمسافة: ");        String name = sc.next();        int age = sc.nextInt();        System.out.println("أهلًا " + name + "، عمرك " + age);    }}
DoubleInput.java
import java.util.Scanner;public class DoubleInput {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        System.out.print("أدخل سعر القطعة: ");        double price = sc.nextDouble();        System.out.print("كم قطعة تريد؟ ");        int qty = sc.nextInt();        System.out.println("الإجمالي: " + (price * qty));    }}
انتبهلو أدخل المستخدم نصًا حيث تتوقع nextInt() رقمًا (مثل كتابة «خمسة») يتوقف البرنامج بخطأ واضح: «الإدخال ... ليس رقمًا صحيحًا». جرّبها في SumTwo بإدخال كلمة بدل رقم وراقب الرسالة — ولذلك تأكد دائمًا أن ما تُدخله يطابق النوع الذي يتوقعه البرنامج.
اختبر نفسك · +5 نقاط
أي سطر ينشئ Scanner يقرأ من لوحة المفاتيح؟
اختبر نفسك ٢ · حتى +5 نقاط
يعمل البرنامج التالي والمستخدم كتب «7 5» في سطر واحد ثم Enter. ما الذي يُطبع؟
int a = sc.nextInt();
int b = sc.nextInt();
System.out.println(a + b);
اختبر نفسك ٣ · حتى +5 نقاط
أي سطر يقرأ عددًا صحيحًا من لوحة المفاتيح في المتغير n ؟
4·3

فخ nextLine() الشهير + تطبيقات عملية

أشهر فخ يقع فيه كل مبرمج جافا مبتدئ — اسمه «السطر المتبقي». سيصيبك يومًا ما، لكنك الآن ستعرفه من قبل أن يقع.

تذكر قاعدة الدرس السابق: ميثودات مثل nextInt() تقرأ الرمز (الرقم) من السطر وتتوقف، ولا تستهلك بقية السطر. أما nextLine() فتقرأ كل ما تبقى حتى نهاية السطر — حتى لو كان هذا الباقي فارغًا تمامًا! شغّل هذا المثال وأدخل «17» ثم «سارة المهداوي» وراقب الكارثة الصامتة:

NameTrap.java
import java.util.Scanner;public class NameTrap {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        System.out.print("كم عمرك؟ ");        int age = sc.nextInt();        System.out.print("ما اسمك الكامل؟ ");        String name = sc.nextLine();  // ← الفخ: تقرأ بقية سطر العمر الفارغ!        System.out.println("عمرك: " + age);        System.out.println("اسمك: [" + name + "]");    }}

النتيجة؟ اسمك: [] — الاسم فارغ! ما حدث بالضبط: عندما كتبت «17» وضغطت Enter، بقي في ذاكرة Scanner شيء واحد: نهاية ذلك السطر الفارغة. سأل البرنامج عن الاسم فالتقطت nextLine() هذه النهاية الفارغة، ولم يتبقَّ شيء لقراءة «سارة المهداوي».

Scanner sc = new Scanner(System.in); int age = sc.nextInt(); String name = sc.nextLine(); sc.nextLine(); String name = sc.nextLine(); 1 8 ⏎ S a r a ⏎ المؤشر المؤشر المؤشر المؤشر age age ? 18 name name ? "" فارغ! "Sara"
كتب المستخدم «18 ⏎ Sara ⏎»: كل ما كتبه ينتظر في سطر الإدخال، والمؤشر عند البداية. ميثود nextInt() قرأت الرقم 18 فقط (age = 18) وتوقّف المؤشر قبل ⏎ مباشرة؛ فلم تُستهلك نهاية السطر. ميثود nextLine() تقرأ من المؤشر حتى أول ⏎، وأول ⏎ أمامها مباشرة، فتعيد نصًا فارغًا (name = "") ويتجاوز المؤشر ⏎. أما Sara فبقيت دون قراءة. الحل: بعد nextInt() نستدعي sc.nextLine(); إضافية، فتبتلع ⏎ المتبقية ويصير المؤشر قبل S. الآن ميثود nextLine() تقرأ من S حتى ⏎ فتعيد «Sara» (name = "Sara") ويتجاوز المؤشر ⏎.

توقّع: أين سيقف المؤشر بعد nextInt()؟

لماذا لم يقرأ Sara؟

الحل

قبل أي nextLine() تأتي بعد قراءة رمز، أدخل استدعاءً إضافيًا «لتفريغ» بقية السطر — كأنك ترمي الفراغ في سلة المهملات:

NameFixed.java
import java.util.Scanner;public class NameFixed {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        System.out.print("كم عمرك؟ ");        int age = sc.nextInt();        sc.nextLine();  // ← استهلك بقية سطر العمر (الفراغ)        System.out.print("ما اسمك الكامل؟ ");        String name = sc.nextLine();        System.out.println("عمرك: " + age);        System.out.println("اسمك: " + name);    }}
قاعدة ذهبيةكلما قرأت رقمًا بـ nextInt/nextDouble/next ثم أردت سطرًا كاملًا بـ nextLine — استدعِ sc.nextLine(); مرة إضافية بينهما لتفريغ السطر. (بديل آخر: اقرأ كل شيء بـ nextLine وخزّنه كنصوص — لكن تحويل النص إلى رقم يحتاج أدوات غير متاحة في هذه الورشة.)

تطبيقان عمليان

حاسبة عمر تقريبية تقرأ الاسم ثم العمر، وبرنامج تحويل درجة الحرارة — كلاهما يستخدم الحل الصحيح لقراءة السطر:

AgeFuture.java
import java.util.Scanner;public class AgeFuture {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        System.out.print("ما اسمك؟ ");        String name = sc.nextLine();        System.out.print("كم عمرك؟ ");        int age = sc.nextInt();        sc.nextLine();        System.out.println("أهلًا " + name + "!");        System.out.println("بعد 10 سنوات ستبلغ " + (age + 10) + " عامًا");    }}
ToFahrenheit.java
import java.util.Scanner;public class ToFahrenheit {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        System.out.print("درجة الحرارة بالمئوية: ");        double c = sc.nextDouble();        double f = c * 9 / 5 + 32;        System.out.println("بالفهرنهايت: " + f);    }}
اختبر نفسك · +5 نقاط
قرأت int age = sc.nextInt(); والمستخدم أدخل «17» ثم Enter — ماذا تعيد sc.nextLine() المستدعاة مباشرة بعدها؟
اختبر نفسك ٢ · حتى +5 نقاط
المستخدم كتب 5 ثم Enter ثم «ali» ثم Enter. ما الذي يُطبع؟
int n = sc.nextInt();
String s = sc.nextLine();
System.out.println("[" + s + "]");
اختبر نفسك ٣ · حتى +5 نقاط
بعد تفريغ السطر المتبقي، أي ميثود تقرأ الاسم الكامل «سارة علي» (بمسافة بين كلمتيه) في متغير نصي؟
4·4

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

حتى الآن طبعنا النصوص كما هي — لكن ماذا لو أردنا جدولًا بأعمدة محاذاة وأرقام بكسور موحدة؟ هنا يأتي printf.

تخيّل printf قالبًا معدنيًا: تكتب النص مرة واحدة وتترك فيه فتحات تُملأ بالقيم عند الطباعة. كل فتحة تبدأ بـ % يليها حرف يحدد نوع القيمة. جافا تحل محل كل محدد بالقيمة التالية بالترتيب:

المحدديستقبلمثال
%dعدد صحيح intprintf("%d", 42) → 42
%fعدد عشري double (٦ خانات افتراضيًا)printf("%f", 3.5) → 3.500000
%.2fعشري بدقة رقمين بعد الفاصلةprintf("%.2f", 3.14159) → 3.14
%sنص Stringprintf("%s", "جافا") → جافا
%cحرف charprintf("%c", 'A') → A
%nلا يستقبل شيئًا — سطر جديدprintf("أ%nب") → سطران
%%لا يستقبل شيئًا — تطبع % نفسهاprintf("%d%%", 95) → 95%
انتبهprintf مثل print تمامًا: لا تنزل سطرًا جديدًا بعد الطباعة — استخدم %n أو println بعدها. وكل محدد يستهلك قيمة من القائمة بالترتيب؛ لو احتاجت قيمة ولم تجدها توقف البرنامج بخطأ واضح، ولو كانت القيمة من النوع الخطأ (مثل %d لنص) يتوقف أيضًا برسالة تفسّر الخلل.
PrintfDemo.java
public class PrintfDemo {    public static void main(String[] args) {        System.out.printf("نص: %s | عدد صحيح: %d | حرف: %c%n", "جافا", 42, 'A');        System.out.printf("عدد عشري: %f — وبدقة رقمين: %.2f%n", 3.5, 3.14159);        System.out.printf("علامة النسبة: %d%%%n", 95);    }}

العرض والمحاذاة — روح الجداول

بين % والحرف يمكنك كتابة رقم عرض: أقل عرض للحقل. والشرطة - قبل الرقم تجعل القيمة تلتصق باليسار بدل اليمين (مفيد مع النصوص). جرّب هذا المثال ولاحظ الأقواس — كل قيمة حشوت بمسافات حتى بلغت عرضها:

PrintfWidth.java
public class PrintfWidth {    public static void main(String[] args) {        System.out.printf("[%5d][%-5d]%n", 42, 42);        System.out.printf("[%10s][%-10s]%n", "جافا", "جافا");        System.out.printf("[%10.2f][%-10.2f]%n", 3.14159, 3.14159);    }}

مثال ختامي: جدول درجات منسق

الآن نجمع كل شيء: %-10s لعمود الأسماء (حقل عرضه 10 خانات تُحاذى النص فيه إلى اليسار وتُملأ بقية الخانات بمسافات، فتبدأ الأعمدة التالية دائمًا من الموضع نفسه) و%-8d للدرجات و%-8c للتقديرات — جدول كامل بثلاث جمل printf فقط:

GradesTable.java
public class GradesTable {    public static void main(String[] args) {        System.out.printf("%-10s %-8s %-8s%n", "الطالب", "الدرجة", "التقدير");        System.out.printf("%-10s %-8d %-8c%n", "سارة", 95, 'A');        System.out.printf("%-10s %-8d %-8c%n", "خالد", 88, 'B');        System.out.printf("%-10s %-8d %-8c%n", "ليلى", 76, 'C');    }}
تلميحمع النصوص العربية قد لا تتساوى المسافات بصريًا تمامًا بسبب اتجاه الكتابة — لكن الفكرة العملية ثابتة: العرض الرقمي + الشرطة للمحاذاة اليسارية هما أداتا تنسيق الأعمدة في كل جافا.
اختبر نفسك · +5 نقاط
أي محدد printf يطبع العدد 3.14159 على الصورة 3.14 ؟
اختبر نفسك ٢ · حتى +5 نقاط
ما ناتج System.out.printf("%d%%%n", 80); ؟
اختبر نفسك ٣ · حتى +5 نقاط
أي استدعاء يطبع «السعر: 4.50» ثم ينزل سطرًا جديدًا دون أخطاء؟
🛠

المشروع التجميعي: بطاقة تعريف الطالب

حان وقت تجميع كل ما تعلمته في الوحدات الأربع: نصوص، مقاطع، أرقام، وإدخال من المستخدم — في برنامج واحد كامل ينتج بطاقة تعريف جاهزة.

الهدف: برنامج يسأل الطالب عن اسمه وصفه، ثم يطبع «بطاقة تعريف» فيها الاسم، والصف، وعدد أحرف الاسم، وأول حرف منه، و«اسم مستخدم» مولّد من أول حرفين + رقم الصف، واسم المقرر بأحرف كبيرة. كل ميزة في البطاقة تستخدم مهارة من دروس الوحدة الثالثة والرابعة — وبعضها من الوحدات الأولى.

خطوات البناء — نفّذها بالترتيب ١) أنشئ Scanner يقرأ من System.in، واسأل «ما اسمك؟» واقرأ الإجابة بـ nextLine() في متغير name.
٢) اسأل «ما صفك؟» واقرأ الإجابة بـ nextInt() في متغير grade.
٣) ابنِ اسم المستخدم: name.substring(0, 2) يلتصق برقم الصف بإشارة +.
٤) اطبع البطاقة: الاسم والصف، ثم name.length() لعدد الأحرف، وname.charAt(0) للحرف الأول.
٥) اختم باسم المقرر: خزّن "java 101" في متغير واطبعه بعد toUpperCase().

ابدأ من هذا الهيكل واملأ التعليقات بنفسك قبل أن تنظر إلى الحل:

StudentCard.java — البداية
import java.util.Scanner;public class StudentCard {    public static void main(String[] args) {        // TODO ١) أنشئ Scanner اسمه sc يقرأ من System.in        // TODO ٢) اطبع "ما اسمك؟ " ثم اقرأ الإجابة في name بـ nextLine()        // TODO ٣) اطبع "ما صفك؟ " ثم اقرأ الإجابة في grade بـ nextInt()        // TODO ٤) عرّف username = أول حرفين من name يلتصقان برقم grade        // TODO ٥) اطبع سطر "======== بطاقة الطالب ========" ثم الأسطر:        //        الاسم، الصف، عدد الأحرف name.length()، الحرف الأول name.charAt(0)        //        اسم المستخدم، وأخيرًا "java 101" بعد تطبيق toUpperCase() عليها    }}

الحل الكامل — قارنه بمحاولتك:

StudentCard.java — الحل الكامل
import java.util.Scanner;public class StudentCard {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        System.out.print("ما اسمك؟ ");        String name = sc.nextLine();        System.out.print("ما صفك؟ ");        int grade = sc.nextInt();        String username = name.substring(0, 2) + grade;        String course = "java 101";        System.out.println("======== بطاقة الطالب ========");        System.out.println("الاسم: " + name);        System.out.println("الصف: " + grade);        System.out.println("الأحرف في الاسم: " + name.length());        System.out.println("الحرف الأول: " + name.charAt(0));        System.out.println("اسم المستخدم: " + username);        System.out.println("المقرر: " + course.toUpperCase());    }}
الناتج المتوقع — تم التحقق منه فعليًاعند تشغيل الحل والإجابة بـ «سارة» ثم «3» تظهر البطاقة:
ما اسمك؟ ما صفك؟ ======== بطاقة الطالب ========
الاسم: سارة
الصف: 3
الأحرف في الاسم: 4
الحرف الأول: س
اسم المستخدم: سا3
المقرر: JAVA 101
أين كل مهارة؟الالتصاق بـ + (3·1)، وlength() وcharAt() وsubstring() (3·2)، وtoUpperCase() (3·3)، وقراءة الإدخال بـ Scanner مع nextLine() وnextInt() (4·2)، وتفادي فخ السطر المتبقي (4·3) — وحفظ النوع الصحيح لكل قيمة (1·5). عند ضغط «▶ تشغيل» سيسألك المتصفح عن الإجابات بنوافذ إدخال — جاوب وشاهد بطاقتك تُطبع.
★

تحدي: أين الخطأ؟

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

المقطع ١: البرنامج يسأل عن العمر ثم الاسم، لكن الترحيب يخرج بلا اسم: «أهلًا !». أين الخطأ؟

import java.util.Scanner; public class Trap1 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int age = sc.nextInt(); String name = sc.nextLine(); System.out.println("أهلًا " + name + "!"); } }

تتبّع ماذا تبقى في سطر الإدخال بعد قراءة الرقم — ومن تقرأه؟ راجع فخ «السطر المتبقي» في الدرس 4·3.

المقطع ٢: أدخلنا 2 ثم 3 ونريد مجموعهما، لكن الناتج «المجموع: 23»! أين الخطأ؟

import java.util.Scanner; public class Trap2 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("رقمان: "); int a = sc.nextInt(); int b = sc.nextInt(); System.out.println("المجموع: " + a + b); } }

الرقمان قُرئا بشكل سليم — فانظر إلى سطر الطباعة: من يلتصق بمن، وبأي ترتيب تُقرأ الإشارات؟ راجع قاعدة الأقواس في الدرس 1·2.

المقطع ٣: سطر printf واحد يوقف البرنامج برسالة «رمز تنسيق غير مدعوم». أين الخطأ؟

public class Trap3 { public static void main(String[] args) { System.out.printf("نسبة النجاح: 95% فقط!%n"); } }

كل % في نص التنسيق تنتظر حرفًا يحدد نوع القيمة — ما الحرف الذي يلي % هنا؟ وكيف تطبع % نفسها؟

لماذا هذا التحدي مهم؟أخطاء الإدخال والإخراج من أخبث الأخطاء: الفخ الأول يتسلل بصمت ويعطي اسمًا فارغًا، والثالث يوقف البرنامج برسالة مربكة. تدريب عينك على تتبّع تدفق القراءة سطرًا سطرًا هو ما يميّز المبرمج المحترف — انسخ هذه المقاطع إلى محرر أي درس وشغّلها وقارن الناتج المتوقع بالفعلي.
✎

تمارين الوحدة ٤

تمارين على الإدخال والإخراج الأساسي (رموز الهروب، Scanner وفخ السطر المتبقي، والإخراج المنسق printf). كل تمرين أمامه كود ناقص: اضغط «✎ تعديل»، اكتب الكود المطلوب مكان التعليقات، اضغط «✔ حفظ» ثم «▶ تشغيل» — وقارن نتيجتك بالهدف المكتوب أسفل كل تمرين. في التمارين التي تسأل المستخدم أدخل القيم الاختبارية المكتوبة داخل التمرين حتى يطابق إخراجك الهدف.

أكمل البرنامج: اقرأ اسم المستخدم بـ nextLine() وعمره بـ nextInt()، ثم اطبع «أهلًا X، بعد 10 سنوات ستكون Y عامًا» حيث Y = العمر + 10. القيم الاختبارية: أدخل «سارة» ثم «17».

FutureAge.java
import java.util.Scanner;public class FutureAge {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        // ١) اطبع "ما اسمك؟" ثم اقرأ الإجابة في name بـ nextLine        // ٢) اطبع "كم عمرك؟" ثم اقرأ الإجابة في age بـ nextInt        // ٣) اطبع: أهلًا (الاسم)، بعد 10 سنوات ستكون (age+10) عامًا    }}
الهدف — بالقيم الاختبارية سارة و17
ما اسمك؟
كم عمرك؟
أهلًا سارة، بعد 10 سنوات ستكون 27 عامًا
تلميحالترحيب النهائي يحتاج التصاق أربع قطع: النص «أهلًا »، ثم name، ثم النص الأوسط، ثم ناتج (age + 10) بين قوسين حتى يُجمع كرقم.

البرنامج يقرأ رقمين ويطبع مجموعهما — لكن بين القراءتين سؤال نصي، فلو نسيت تفريغ السطر سيفشل. أكمل البرنامج مع sc.nextLine() إضافية بين القراءتين. القيم الاختبارية: أدخل «7» ثم «موافق» ثم «5».

AddTwo.java
import java.util.Scanner;public class AddTwo {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        // ١) اطبع "أدخل الرقم الأول: " واقرأه في a بـ nextInt        // ٢) استدعِ sc.nextLine() مرة إضافية لتفريغ بقية السطر        System.out.print("هل تريد المتابعة؟ ");        String ok = sc.nextLine();        // ٣) اطبع "أدخل الرقم الثاني: " واقرأه في b بـ nextInt        // ٤) اطبع "المجموع: " متبوعًا بمجموع a + b    }}
الهدف — بالقيم الاختبارية 7، موافق، 5
أدخل الرقم الأول: هل تريد المتابعة؟ أدخل الرقم الثاني: المجموع: 12
تلميحبدون سطر التفريغ ستقرأ ok بقية سطر الرقم الأول الفارغ بدل كلمة «موافق» — جرّب حذفه وشغّل لتريد الفخ بنفسك.

اطبع بـ printf ثلاثة أسطر بالصيغة «الرقم مربعه المربع» للأرقام 1 و2 و3 — مثل «1 مربعه 1» — في كل سطر محددان %d وسطر جديد %n.

SquaresTable.java
public class SquaresTable {    public static void main(String[] args) {        // سطر لكل رقم: اطبع الرقم ثم مربعه بمحددين %d وسطر جديد %n        // الأسطر المطلوبة: 1 مربعه 1 / 2 مربعه 4 / 3 مربعه 9    }}
الهدف
1 مربعه 1
2 مربعه 4
3 مربعه 9
تلميحنص التنسيق يحمل محددين لقيمتين بالترتيب: الأولى الرقم نفسه والثانية مربعه (مثل 2 * 2) — ولا تنس %n وإلا التصقت كل الأسطر في سطر واحد.

اقرأ اسم منتج بـ next() وسعره بـ nextDouble() وكميته بـ nextInt()، ثم اطبع بـ printf سطرًا واحدًا بالصيغة [الاسم] xالكمية = الإجمالي: الاسم داخل قوسين مربعين في حقل عرضه 10 خانات محاذى لليسار (%-10s)، والإجمالي (السعر × الكمية) بدقة رقمين بعد الفاصلة. القيم الاختبارية: أدخل «Pen» ثم «2.5» ثم «4».

InvoiceLine.java
import java.util.Scanner;public class InvoiceLine {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        // ١) اطبع "اسم المنتج:" ثم اقرأ الاسم في name بـ next()        // ٢) اطبع "السعر:" ثم اقرأه في price (double) بـ nextDouble()        // ٣) اطبع "الكمية:" ثم اقرأها في qty (int) بـ nextInt()        // ٤) اطبع بـ printf: [الاسم بعرض 10 محاذى لليسار] xالكمية = الإجمالي بدقة رقمين    }}
الهدف — بالقيم الاختبارية Pen و2.5 و4
اسم المنتج:
السعر:
الكمية:
[Pen       ] x4 = 10.00
تلميحنص التنسيق: "[%-10s] x%d = %.2f%n" — ثلاثة محددات للقيم الثلاث بالترتيب: الاسم، ثم الكمية، ثم price * qty. والشرطة في %-10s تجعل الاسم يلتصق باليسار والمسافات الباقية تُملأ بعده.
أنهيت تمارين الوحدة؟انتقل إلى الصفحة الرئيسية وتابع تقدمك في بطاقات الوحدات، أو راجع دروس الوحدة الرابعة من القائمة الجانبية.