المشروع النهائي والمراجعة
اجمع كل ما تعلمته في برنامج حقيقي، ثم اختبر نفسك
في نهاية هذه المحاضرة ستكون قادرًا على
- تقسّم برنامجًا إلى عدة ملفات داخل حزمة واحدة
- تبني مدير درجات بقائمة وحلقة ومصفوفات ودوال، مرحلة بعد مرحلة
- تنقل مشروعك من مختبر Java إلى NetBeans عبر ملف ZIP
- تتجنب الفخاخ الكلاسيكية التي مرت في كل محاضرة
- تحل امتحانًا عمليًا تجريبيًا في وقت محدد
محتويات المحاضرة
- ستبني برنامجًا يدير درجات صف كامل، بكل ما تعلمته
- كل ملف له مهمة واحدة، وتجمعها حزمة
grades - يحفظ مختبر Java مشروعك، ويسلّمك إياه ZIP لتفتحه في NetBeans
- المرحلة 1:
Statsتحسب المعدل وأعلى درجة وأدناها - المرحلة 2:
Reportيطبع جدولًا بأعمدة مستقيمة - المرحلة 3: حلقة
do-whileوswitchيصنعان القائمة - المرحلة 5: تجمّعت القطع في برنامج كامل
- الطباعة والمتغيرات والمدخلات: محاضرات 1 إلى 6
- الشروط والقرارات: محاضرتا 7 و8
- الحلقات: محاضرتا 9 و10
- الدوال: محاضرتا 11 و12
- المصفوفات والنصوص: محاضرات 13 إلى 15
- الامتحان: 120 دقيقة وستة أسئلة تتصاعد صعوبتها
- السؤالان 3 و4: المصفوفات والدوال، ثم النصوص
- السؤالان 5 و6: مصفوفة ثنائية، ثم برنامج يجمع كل شيء
- أسئلة المراجعة الأخيرة، وإلى اللقاء في برمجة 2
ستبني برنامجًا يدير درجات صف كامل، بكل ما تعلمته
| الفكرة | أين تظهر في المشروع |
|---|---|
Scanner وnextLine | قراءة الأسماء والدرجات |
do-while وswitch | القائمة التي تتكرر حتى الخروج |
while للتحقق من المدخلات | رفض الدرجة خارج المدى من 0 إلى 100 |
| المصفوفات و2D | String[] للأسماء وint[][] للدرجات |
| الدوال والمعاملات | كل مهمة في دالة، وكل مجموعة دوال في صنف |
printf وequalsIgnoreCase | جدول منسق وبحث بالاسم |
كل ملف له مهمة واحدة، وتجمعها حزمة grades
| الملف | مهمته | دواله |
|---|---|---|
grades/GradeBook.java | main والقائمة والقراءة من المستخدم | main, addStudent, readMark, findStudent |
grades/Stats.java | الحساب فقط، دون طباعة | average, max, min |
grades/Report.java | الطباعة المنسقة فقط | printTable, printSummary |
- أول سطر في كل ملف هو
package grades;، والملف داخل مجلد بالاسم نفسه. - الأصناف هنا تجمع دوالًا ثابتة
staticفقط، ولا ننشئ منها كائنات. - داخل الحزمة نفسها لا حاجة إلى
import: نكتبStats.average(row)مباشرة.
البداية: ملفان يعملان معًا
انتقل بين الملفين من أعلى المحرر. اضغط «تتبّع سطرًا سطرًا» وادخل إلى Stats.average لترى كيف ينتقل التنفيذ إلى ملف آخر ثم يعود. غيّر الدرجات وتوقّع النتيجة.
package grades;
public class GradeBook {
public static void main(String[] args) {
int[] marks = {70, 85, 90};
System.out.printf("Average: %.2f%n", Stats.average(marks));
System.out.println("Best: " + Stats.max(marks));
System.out.println("Lowest: " + Stats.min(marks));
}
}package grades;
public class Stats {
public static double average(int[] values) {
int sum = 0;
for (int value : values) {
sum += value;
}
return (double) sum / values.length;
}
public static int max(int[] values) {
int best = values[0];
for (int value : values) {
if (value > best) {
best = value;
}
}
return best;
}
public static int min(int[] values) {
int worst = values[0];
for (int value : values) {
if (value < worst) {
worst = value;
}
}
return worst;
}
}Average: 81.67 Best: 90 Lowest: 70
لماذا لا يطبع الصنف Stats شيئًا، بل يرجع القيم فقط؟
Report يطبعها في جدول، وغيره قد يقارن بها. هذا الفصل بين الحساب والعرض من أهم عادات المبرمج.يحفظ مختبر Java مشروعك، ويسلّمك إياه ZIP لتفتحه في NetBeans
المختبر أعلى الموقع يتسع لمشروع كامل بعدة ملفات وحزم، ولا يحتاج إلى تثبيت.
- افتح «مختبر Java» من أعلى الموقعمن القائمة «+ مشروع جديد…» اختر «برنامج فارغ»، ثم اضغط «إعادة التسمية» وسمّه
Grades. - أضف الملفات بزر
+فوق المحرراكتب الاسم مع المجلد:grades/GradeBook.java، ثمgrades/Stats.javaوgrades/Report.java. يضيف المختبر سطرpackageبنفسه. احذفMain.javaبزر×. - اكتب الكود، أو انسخه من المختبرات في هذه الصفحةيُحفظ كل شيء في هذا المتصفح تلقائيًا. اضغط Ctrl+Enter للتشغيل.
- اضغط «تنزيل ZIP»ثم فك الضغط في مجلد جديد، مثل
GradesSource. يجب أن تجد في داخله المجلدgrades. - افتحه في NetBeans 8.2اختر File ثم New Project ثم Java ثم Java Project with Existing Sources. سمّ المشروع، وعند Source Package Folders اضغط Add Folder واختر
GradesSource، وليسgrades. - شغّله بالمفتاح F6إذا سألك NetBeans عن الصنف الرئيسي، فاختر
grades.GradeBook.
المرحلة 1: Stats تحسب المعدل وأعلى درجة وأدناها
المرحلة 1: أكمل Stats
الدالة main جاهزة: تقرأ عدد الدرجات ثم الدرجات. أكمل الدوال الثلاث في Stats دون أن تطبع منها شيئًا.
import java.util.Scanner;
class Stats {
static double average(int[] values) {
return 0; // Replace this
}
static int max(int[] values) {
return 0; // Replace this
}
static int min(int[] values) {
return 0; // Replace this
}
}
public class StageStats {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int[] marks = new int[n];
for (int i = 0; i < n; i++) {
marks[i] = input.nextInt();
}
System.out.printf("Average: %.2f%n", Stats.average(marks));
System.out.println("Max: " + Stats.max(marks));
System.out.println("Min: " + Stats.min(marks));
}
}3 70 85 90
Average: 81.67 Max: 90 Min: 70
تلميح 1
قسمة sum / values.length بين عددين صحيحين تحذف الكسر. استخدم (double) sum.
تلميح 2
ابدأ max وmin بالقيمة values[0]، وليس 0: لماذا تفشل min إذا بدأت بصفر؟
الحل
import java.util.Scanner;
class Stats {
static double average(int[] values) {
int sum = 0;
for (int value : values) {
sum += value;
}
return (double) sum / values.length;
}
static int max(int[] values) {
int best = values[0];
for (int value : values) {
if (value > best) {
best = value;
}
}
return best;
}
static int min(int[] values) {
int worst = values[0];
for (int value : values) {
if (value < worst) {
worst = value;
}
}
return worst;
}
}
public class StageStats {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int[] marks = new int[n];
for (int i = 0; i < n; i++) {
marks[i] = input.nextInt();
}
System.out.printf("Average: %.2f%n", Stats.average(marks));
System.out.println("Max: " + Stats.max(marks));
System.out.println("Min: " + Stats.min(marks));
}
}المرحلة 2: Report يطبع جدولًا بأعمدة مستقيمة
الدرجات في مصفوفة ثنائية: كل صف طالب، وكل عمود امتحان. وmarks[i] هو صف كامل من نوع int[]، فنمرره مباشرة إلى Stats.average.
ثلاثة ملفات وجدول
افتح Report.java وغيّر %-12s إلى %12s: ماذا يحدث لعمود الأسماء؟ ثم أضف طالبًا ثالثًا في GradeBook.java.
package grades;
public class GradeBook {
public static void main(String[] args) {
String[] names = {"Sara Ali", "Omar"};
int[][] marks = {
{80, 90, 100},
{55, 60, 70}
};
Report.printTable(names, marks, 2);
Report.printSummary(marks, 2);
}
}package grades;
public class Stats {
public static double average(int[] values) {
int sum = 0;
for (int value : values) {
sum += value;
}
return (double) sum / values.length;
}
public static int max(int[] values) {
int best = values[0];
for (int value : values) {
if (value > best) {
best = value;
}
}
return best;
}
public static int min(int[] values) {
int worst = values[0];
for (int value : values) {
if (value < worst) {
worst = value;
}
}
return worst;
}
}package grades;
public class Report {
public static void printTable(String[] names, int[][] marks, int count) {
if (count == 0) {
System.out.println("No students yet.");
return;
}
System.out.printf("%-12s%5s%5s%5s%8s%6s%6s%n", "Name", "M1", "M2", "M3", "Avg", "Best", "Low");
for (int i = 0; i < count; i++) {
int[] row = marks[i];
System.out.printf("%-12s%5d%5d%5d%8.2f%6d%6d%n", names[i], row[0], row[1], row[2],
Stats.average(row), Stats.max(row), Stats.min(row));
}
}
public static void printSummary(int[][] marks, int count) {
if (count == 0) {
System.out.println("No students yet.");
return;
}
double total = 0;
for (int i = 0; i < count; i++) {
total += Stats.average(marks[i]);
}
System.out.printf("Students: %d%n", count);
System.out.printf("Class average: %.2f%n", total / count);
}
}Name M1 M2 M3 Avg Best Low Sara Ali 80 90 100 90.00 100 80 Omar 55 60 70 61.67 70 55 Students: 2 Class average: 75.83
المرحلة 2: أكمل Report
تقرأ main عدد الطلاب، ثم لكل طالب اسمًا من كلمة واحدة وثلاث درجات. أكمل printRow لتطبع سطرًا بالتنسيق %-10s%5d%5d%5d%8.2f%n وآخره المعدل، وprintPassed لتطبع Passed: مع عدد الطلاب الذين معدلهم 60 فأكثر.
import java.util.Scanner;
class Report {
static void printRow(String name, int[] row) {
// printf with %-10s%5d%5d%5d%8.2f%n
}
static void printPassed(int[][] marks) {
// Count the rows whose average is 60 or more
}
}
public class StageReport {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int[][] marks = new int[n][3];
for (int i = 0; i < n; i++) {
String name = input.next();
for (int k = 0; k < 3; k++) {
marks[i][k] = input.nextInt();
}
Report.printRow(name, marks[i]);
}
Report.printPassed(marks);
}
}2 Sara 80 90 100 Omar 55 60 70
Sara 80 90 100 90.00 Omar 55 60 70 61.67 Passed: 2
تلميح 1
المعدل (row[0] + row[1] + row[2]) / 3.0، والقسمة على 3.0 تمنع حذف الكسر.
تلميح 2
marks[i] صف كامل، فالحلقة في printPassed تكفيها marks.length.
الحل
import java.util.Scanner;
class Report {
static double average(int[] row) {
return (row[0] + row[1] + row[2]) / 3.0;
}
static void printRow(String name, int[] row) {
System.out.printf("%-10s%5d%5d%5d%8.2f%n", name, row[0], row[1], row[2], average(row));
}
static void printPassed(int[][] marks) {
int passed = 0;
for (int i = 0; i < marks.length; i++) {
if (average(marks[i]) >= 60) {
passed++;
}
}
System.out.println("Passed: " + passed);
}
}
public class StageReport {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int[][] marks = new int[n][3];
for (int i = 0; i < n; i++) {
String name = input.next();
for (int k = 0; k < 3; k++) {
marks[i][k] = input.nextInt();
}
Report.printRow(name, marks[i]);
}
Report.printPassed(marks);
}
}المرحلة 3: حلقة do-while وswitch يصنعان القائمة
countحجم المصفوفة ثابت، لكن عدد الطلاب يكبر. نضيف عند الموقع count ثم نزيده، ولا نمر إلا على i < count.
names[count] = name;
count++;nextIntيترك nextInt نهاية السطر خلفه. إذا لم تتجاوزها، فستقرأ nextLine التالية اسمًا فارغًا.
choice = input.nextInt();
input.nextLine();المرحلة 3: القائمة
اكتب حلقة تقرأ رقم خيار في سطر، حتى يكون 0. الخيار 1: اقرأ اسمًا في السطر التالي (قد يحوي مسافات)، احفظه واطبع Added مع الاسم. الخيار 2: اطبع كل اسم في سطر بالشكل 1. Sara، أو No students إذا لم يوجد أحد. الخيار 0: اطبع Goodbye. أي رقم آخر: Unknown. احفظ حتى 30 اسمًا. لا تطبع أي نص يطلب الإدخال.
import java.util.Scanner;
public class StageMenu {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// A String array, a count, then a do-while loop with a switch inside
}
}1 Sara Ali 1 Omar 2 0
Added Sara Ali Added Omar 1. Sara Ali 2. Omar Goodbye
تلميح 1
ألم تنسَ break في كل case؟ بدونها ينفذ البرنامج الحالة التالية أيضًا.
تلميح 2
بعد nextInt استدعِ nextLine لتجاوز نهاية السطر، حتى في الخيارات التي لا تقرأ اسمًا.
الحل
import java.util.Scanner;
public class StageMenu {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String[] names = new String[30];
int count = 0;
int choice;
do {
choice = input.nextInt();
input.nextLine();
switch (choice) {
case 1:
names[count] = input.nextLine();
System.out.println("Added " + names[count]);
count++;
break;
case 2:
if (count == 0) {
System.out.println("No students");
}
for (int i = 0; i < count; i++) {
System.out.println((i + 1) + ". " + names[i]);
}
break;
case 0:
System.out.println("Goodbye");
break;
default:
System.out.println("Unknown");
}
} while (choice != 0);
}
}المرحلة 4: البحث بالاسم
السطر الأول عدد الطلاب، ثم لكل طالب سطر اسمه وسطر درجته، ثم سطر الاسم المطلوب. اكتب دالة find ترجع موقع الطالب أو -1، مع إهمال حالة الأحرف والمسافات الزائدة. اطبع Sara Ali: 80، أو Not found.
import java.util.Scanner;
public class StageFind {
static int find(String[] names, String target) {
// Return the position of target, or -1
return -1;
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// Read the students, read the target, call find, print
}
}2 Sara Ali 80 Omar 75 sara ali
Sara Ali: 80
تلميح 1
قارن بالدالة equalsIgnoreCase، وليس بالعامل ==.
تلميح 2
Integer.parseInt(input.nextLine().trim()) تقرأ العدد من سطر كامل، فتتجنب فخ nextInt.
الحل
import java.util.Scanner;
public class StageFind {
static int find(String[] names, String target) {
for (int i = 0; i < names.length; i++) {
if (names[i].equalsIgnoreCase(target.trim())) {
return i;
}
}
return -1;
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = Integer.parseInt(input.nextLine().trim());
String[] names = new String[n];
int[] marks = new int[n];
for (int i = 0; i < n; i++) {
names[i] = input.nextLine();
marks[i] = Integer.parseInt(input.nextLine().trim());
}
int at = find(names, input.nextLine());
if (at == -1) {
System.out.println("Not found");
} else {
System.out.println(names[at] + ": " + marks[at]);
}
}
}المرحلة 5: تجمّعت القطع في برنامج كامل
مدير الدرجات: جرّبه بنفسك
الملف الذي فيه main أولًا. أضف طالبين، واطلب الجدول، وجرّب إدخال الدرجة 150. ثم انسخ الملفات الثلاثة إلى مشروعك في مختبر Java ونزّلها ZIP وافتحها في NetBeans.
package grades;
import java.util.Scanner;
public class GradeBook {
static final int MAX_STUDENTS = 30;
static final int EXAMS = 3;
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String[] names = new String[MAX_STUDENTS];
int[][] marks = new int[MAX_STUDENTS][EXAMS];
int count = 0;
int choice;
do {
System.out.println("1 Add 2 Table 3 Summary 4 Find 0 Exit");
System.out.print("Choice: ");
choice = input.nextInt();
input.nextLine(); // nextInt leaves the end of the line behind
switch (choice) {
case 1:
count = addStudent(input, names, marks, count);
break;
case 2:
Report.printTable(names, marks, count);
break;
case 3:
Report.printSummary(marks, count);
break;
case 4:
findStudent(input, names, marks, count);
break;
case 0:
System.out.println("Goodbye.");
break;
default:
System.out.println("Unknown choice.");
}
} while (choice != 0);
}
static int addStudent(Scanner input, String[] names, int[][] marks, int count) {
if (count == MAX_STUDENTS) {
System.out.println("The class is full.");
return count;
}
System.out.print("Name: ");
names[count] = input.nextLine().trim();
for (int exam = 0; exam < EXAMS; exam++) {
marks[count][exam] = readMark(input, exam + 1);
}
input.nextLine();
System.out.println("Added " + names[count] + ".");
return count + 1;
}
static int readMark(Scanner input, int number) {
System.out.print("Mark " + number + ": ");
int mark = input.nextInt();
while (mark < 0 || mark > 100) {
System.out.print("Enter 0 to 100: ");
mark = input.nextInt();
}
return mark;
}
static void findStudent(Scanner input, String[] names, int[][] marks, int count) {
System.out.print("Name to find: ");
String target = input.nextLine().trim();
for (int i = 0; i < count; i++) {
if (names[i].equalsIgnoreCase(target)) {
System.out.printf("%s: average %.2f%n", names[i], Stats.average(marks[i]));
return;
}
}
System.out.println("Not found.");
}
}package grades;
public class Stats {
public static double average(int[] values) {
int sum = 0;
for (int value : values) {
sum += value;
}
return (double) sum / values.length;
}
public static int max(int[] values) {
int best = values[0];
for (int value : values) {
if (value > best) {
best = value;
}
}
return best;
}
public static int min(int[] values) {
int worst = values[0];
for (int value : values) {
if (value < worst) {
worst = value;
}
}
return worst;
}
}package grades;
public class Report {
public static void printTable(String[] names, int[][] marks, int count) {
if (count == 0) {
System.out.println("No students yet.");
return;
}
System.out.printf("%-12s%5s%5s%5s%8s%6s%6s%n", "Name", "M1", "M2", "M3", "Avg", "Best", "Low");
for (int i = 0; i < count; i++) {
int[] row = marks[i];
System.out.printf("%-12s%5d%5d%5d%8.2f%6d%6d%n", names[i], row[0], row[1], row[2],
Stats.average(row), Stats.max(row), Stats.min(row));
}
}
public static void printSummary(int[][] marks, int count) {
if (count == 0) {
System.out.println("No students yet.");
return;
}
double total = 0;
for (int i = 0; i < count; i++) {
total += Stats.average(marks[i]);
}
System.out.printf("Students: %d%n", count);
System.out.printf("Class average: %.2f%n", total / count);
}
}جلسة كاملة بمدخلات جاهزة
هذه النسخة تقرأ مدخلات جاهزة، فلا تظهر مكتوبة في الناتج، ولذلك تتلاصق النصوص التي تطلب الإدخال. اضغط «تتبّع سطرًا سطرًا» وراقب count وnames.
package grades;
import java.util.Scanner;
public class GradeBook {
static final int MAX_STUDENTS = 30;
static final int EXAMS = 3;
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String[] names = new String[MAX_STUDENTS];
int[][] marks = new int[MAX_STUDENTS][EXAMS];
int count = 0;
int choice;
do {
System.out.println("1 Add 2 Table 3 Summary 4 Find 0 Exit");
System.out.print("Choice: ");
choice = input.nextInt();
input.nextLine(); // nextInt leaves the end of the line behind
switch (choice) {
case 1:
count = addStudent(input, names, marks, count);
break;
case 2:
Report.printTable(names, marks, count);
break;
case 3:
Report.printSummary(marks, count);
break;
case 4:
findStudent(input, names, marks, count);
break;
case 0:
System.out.println("Goodbye.");
break;
default:
System.out.println("Unknown choice.");
}
} while (choice != 0);
}
static int addStudent(Scanner input, String[] names, int[][] marks, int count) {
if (count == MAX_STUDENTS) {
System.out.println("The class is full.");
return count;
}
System.out.print("Name: ");
names[count] = input.nextLine().trim();
for (int exam = 0; exam < EXAMS; exam++) {
marks[count][exam] = readMark(input, exam + 1);
}
input.nextLine();
System.out.println("Added " + names[count] + ".");
return count + 1;
}
static int readMark(Scanner input, int number) {
System.out.print("Mark " + number + ": ");
int mark = input.nextInt();
while (mark < 0 || mark > 100) {
System.out.print("Enter 0 to 100: ");
mark = input.nextInt();
}
return mark;
}
static void findStudent(Scanner input, String[] names, int[][] marks, int count) {
System.out.print("Name to find: ");
String target = input.nextLine().trim();
for (int i = 0; i < count; i++) {
if (names[i].equalsIgnoreCase(target)) {
System.out.printf("%s: average %.2f%n", names[i], Stats.average(marks[i]));
return;
}
}
System.out.println("Not found.");
}
}package grades;
public class Stats {
public static double average(int[] values) {
int sum = 0;
for (int value : values) {
sum += value;
}
return (double) sum / values.length;
}
public static int max(int[] values) {
int best = values[0];
for (int value : values) {
if (value > best) {
best = value;
}
}
return best;
}
public static int min(int[] values) {
int worst = values[0];
for (int value : values) {
if (value < worst) {
worst = value;
}
}
return worst;
}
}package grades;
public class Report {
public static void printTable(String[] names, int[][] marks, int count) {
if (count == 0) {
System.out.println("No students yet.");
return;
}
System.out.printf("%-12s%5s%5s%5s%8s%6s%6s%n", "Name", "M1", "M2", "M3", "Avg", "Best", "Low");
for (int i = 0; i < count; i++) {
int[] row = marks[i];
System.out.printf("%-12s%5d%5d%5d%8.2f%6d%6d%n", names[i], row[0], row[1], row[2],
Stats.average(row), Stats.max(row), Stats.min(row));
}
}
public static void printSummary(int[][] marks, int count) {
if (count == 0) {
System.out.println("No students yet.");
return;
}
double total = 0;
for (int i = 0; i < count; i++) {
total += Stats.average(marks[i]);
}
System.out.printf("Students: %d%n", count);
System.out.printf("Class average: %.2f%n", total / count);
}
}1 Add 2 Table 3 Summary 4 Find 0 Exit Choice: No students yet. 1 Add 2 Table 3 Summary 4 Find 0 Exit Choice: Name: Mark 1: Mark 2: Mark 3: Added Sara Ali. 1 Add 2 Table 3 Summary 4 Find 0 Exit Choice: Name: Mark 1: Enter 0 to 100: Mark 2: Mark 3: Added Omar. 1 Add 2 Table 3 Summary 4 Find 0 Exit Choice: Name M1 M2 M3 Avg Best Low Sara Ali 80 90 100 90.00 100 80 Omar 55 60 70 61.67 70 55 1 Add 2 Table 3 Summary 4 Find 0 Exit Choice: Students: 2 Class average: 75.83 1 Add 2 Table 3 Summary 4 Find 0 Exit Choice: Name to find: Sara Ali: average 90.00 1 Add 2 Table 3 Summary 4 Find 0 Exit Choice: Name to find: Not found. 1 Add 2 Table 3 Summary 4 Find 0 Exit Choice: Unknown choice. 1 Add 2 Table 3 Summary 4 Find 0 Exit Choice: Goodbye.
- سهل: أضف خيارًا يحذف آخر طالب بإنقاص
count. - متوسط: أضف إلى
Statsدالةletter(double average)ترجعAإلىF، واعرضها عمودًا في الجدول. - أصعب: رتّب الجدول حسب المعدل بالترتيب الفقاعي. تذكّر: يجب أن تبدّل الاسم والصف معًا.
الطباعة والمتغيرات والمدخلات: محاضرات 1 إلى 6
المحاضرة 1: الصنف العام اسمه Hello. ما اسم الملف الذي يجب أن يحفظ فيه؟
hello.java ليس الاسم نفسه.المحاضرة 2: ماذا يفعل المترجم بسطر يبدأ بـ //؟
/** */ تعليق توثيق javadoc، يتجاهله المترجم أيضًا لكن أداة javadoc تقرؤه.المحاضرتان 1 و2: print وprintln و\n. ماذا يطبع؟
public class PrintReview {
public static void main(String[] args) {
System.out.print("A");
System.out.println("B");
System.out.print("C\nD");
}
}أظهر الناتج
AB C D
لماذا؟ print لا ينزل إلى سطر جديد، وprintln ينزل بعد الطباعة، و\n داخل النص ينزل في مكانه.
المحاضرة 3: + مع النصوص والأرقام. ماذا يطبع؟
public class ConcatReview {
public static void main(String[] args) {
int a = 2;
int b = 3;
System.out.println("Sum: " + a + b);
System.out.println(a + b + " is the sum");
}
}أظهر الناتج
Sum: 23 5 is the sum
لماذا؟ تُقرأ + من اليسار. بعد أول نص يصبح كل شيء دمجًا، أما قبله فالعددان يُجمعان. والأقواس هي الحل: "Sum: " + (a + b).
المحاضرة 3: x++ يستخدم القيمة ثم يزيدها. ماذا يطبع؟
public class IncrementReview {
public static void main(String[] args) {
int x = 5;
int y = x++;
System.out.println(x + " " + y);
}
}أظهر الناتج
6 5
لماذا؟ تأخذ y القيمة القديمة 5، ثم تصبح x مساوية 6.
المحاضرة 4: ماذا يحدث عند تنفيذ System.out.printf("%d%n", 3.5);؟
%d للأعداد الصحيحة فقط، و%f للعشرية. والمترجم لا يفحص نص التنسيق، فيظهر IllegalFormatConversionException عند التشغيل.المحاضرة 5: المدخلات هي 19 ثم Sara، كل منهما في سطر. ماذا يطبع؟
import java.util.Scanner;
public class NextLineTrap {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int age = input.nextInt();
String name = input.nextLine();
System.out.println(age);
System.out.println("[" + name + "]");
}
}أظهر الناتج
19 []
لماذا؟ تقرأ nextInt الرقم وتترك نهاية السطر. ثم تقرأ nextLine ما بقي من السطر، وهو لا شيء. الحل: input.nextLine(); إضافية بعد nextInt.
علاج فخ nextLine
السطر الإضافي يتجاوز نهاية السطر الأول. احذفه وشغّل البرنامج لترى الاسم الفارغ يعود.
import java.util.Scanner;
public class NextLineFix {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int age = input.nextInt();
input.nextLine();
String name = input.nextLine();
System.out.println(age);
System.out.println("[" + name + "]");
}
}19 [Sara]
المحاضرة 6: قسمة الأعداد الصحيحة. ماذا تطبع الأسطر الأربعة؟
public class DivisionReview {
public static void main(String[] args) {
System.out.println(7 / 2);
System.out.println(7 / 2.0);
System.out.println((double) 7 / 2);
System.out.println((double) (7 / 2));
}
}أظهر الناتج
3 3.5 3.5 3.0
لماذا؟ عددان صحيحان يعطيان ناتجًا صحيحًا. في السطر الأخير حدثت القسمة أولًا فضاع الكسر، ثم جاء التحويل متأخرًا. لذلك ضع (double) على أحد طرفي القسمة.
المحاضرة 6: ما قيمة 2 + 3 * 4 % 5؟
* و% قبل +، ومن اليسار إلى اليمين: 3 × 4 = 12، ثم 12 % 5 = 2، ثم 2 + 2 = 4.الشروط والقرارات: محاضرتا 7 و8
= أم ==؟
المحاضرة 7: أصلح الشرط ليطبع five.
public class AssignOrEqual {
public static void main(String[] args) {
int x = 5;
if (x = 5) {
System.out.println("five");
}
}
}incompatible types: int cannot be converted to booleanأظهر التصحيح
public class AssignOrEqual {
public static void main(String[] args) {
int x = 5;
if (x == 5) {
System.out.println("five");
}
}
}five
لماذا؟ x = 5 إسناد ناتجه العدد 5، والشرط يحتاج إلى boolean. لذلك تتحدث الرسالة عن الأنواع ولا تذكر السبب الحقيقي: العلامة الناقصة.
المحاضرة 7: المستخدم يكتب java. ماذا يطبع؟
import java.util.Scanner;
public class StringEquals {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String word = input.next();
System.out.println(word == "java");
System.out.println(word.equals("java"));
}
}أظهر الناتج
false true
لماذا؟ == تسأل عن المكان في الذاكرة، وما يُقرأ من المستخدم نص جديد في مكان جديد. قارن النصوص دائمًا بالدالة equals.
المحاضرة 8: ترتيب الشروط. الدرجة 95. ماذا يطبع؟
public class GradeOrder {
public static void main(String[] args) {
int mark = 95;
if (mark >= 60) {
System.out.println("D");
} else if (mark >= 80) {
System.out.println("B");
} else if (mark >= 90) {
System.out.println("A");
}
}
}أظهر الناتج
D
لماذا؟ في سلسلة else if ينفذ أول فرع يتحقق شرطه فقط، ولا تُفحص البقية. ابدأ من الدرجة الأعلى.
المحاضرة 8: نسينا break. ماذا يطبع؟
public class MissingBreak {
public static void main(String[] args) {
int day = 2;
switch (day) {
case 1:
System.out.println("Sunday");
case 2:
System.out.println("Monday");
case 3:
System.out.println("Tuesday");
break;
default:
System.out.println("Other");
}
}
}أظهر الناتج
Monday Tuesday
لماذا؟ يبدأ التنفيذ عند case 2، ويستمر إلى الحالة التالية حتى يصل إلى break. ولا يصل إلى default لأن break أوقفه.
فاصلة منقوطة صغيرة. ماذا يطبع؟
public class IfSemicolon {
public static void main(String[] args) {
int x = 3;
if (x > 10);
{
System.out.println("big");
}
System.out.println("done");
}
}أظهر الناتج
big done
لماذا؟ الفاصلة المنقوطة تنهي if بجملة فارغة، فتصبح الكتلة التي بعدها مستقلة وتُنفذ دائمًا. لا يعدّ المترجم هذا خطأ.
ما قيمة result بعد String result = (7 % 2 == 0) ? "even" : "odd";؟
:.الحلقات: محاضرتا 9 و10
خطأ الزيادة بواحد. كم مرة تدور الحلقة؟
public class OffByOne {
public static void main(String[] args) {
int count = 0;
for (int i = 1; i <= 5; i++) {
count++;
}
for (int i = 0; i <= 5; i++) {
count++;
}
System.out.println(count);
}
}أظهر الناتج
11
لماذا؟ الأولى من 1 إلى 5 خمس مرات، والثانية من 0 إلى 5 ست مرات. تذكر: i < n من 0 تدور n مرة بالضبط.
المحاضرة 9: الشرط خاطئ من البداية. ماذا يطبع؟
public class DoWhileReview {
public static void main(String[] args) {
int a = 10;
while (a < 5) {
System.out.println("while");
}
do {
System.out.println("do");
} while (a < 5);
}
}أظهر الناتج
do
لماذا؟ while تفحص الشرط أولًا فلا تدخل. وdo-while تنفذ مرة ثم تفحص، ولهذا تناسب القوائم والتحقق من المدخلات.
المحاضرة 10: continue وbreak معًا. ماذا يطبع؟
public class BreakContinue {
public static void main(String[] args) {
for (int i = 1; i <= 6; i++) {
if (i == 2) {
continue;
}
if (i == 5) {
break;
}
System.out.print(i + " ");
}
System.out.println();
}
}أظهر الناتج
1 3 4
لماذا؟ continue تتخطى بقية هذه الدورة، وbreak تنهي الحلقة كلها قبل طباعة 5.
المحاضرة 10: حلقتان متداخلتان. ماذا يطبع؟
public class NestedReview {
public static void main(String[] args) {
for (int row = 1; row <= 3; row++) {
for (int col = 1; col <= row; col++) {
System.out.print("*");
}
System.out.println();
}
}
}أظهر الناتج
* ** ***
لماذا؟ تكتمل الحلقة الداخلية في كل دورة من الخارجية، ويتوقف طولها على row.
أين انتهى المتغير i؟
نريد طباعة قيمة i بعد الحلقة. أصلح البرنامج ليطبع 3.
public class LoopScope {
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
System.out.println("Hi");
}
System.out.println(i);
}
}cannot find symbolأظهر التصحيح
public class LoopScope {
public static void main(String[] args) {
int i;
for (i = 0; i < 3; i++) {
System.out.println("Hi");
}
System.out.println(i);
}
}Hi Hi Hi 3
لماذا؟ المتغير المعرّف في رأس for يعيش داخل الحلقة فقط. صرّح عنه قبلها إذا احتجته بعدها.
ماذا ينقص هذه الحلقة؟
int n = 3;
while (n > 0) {
System.out.println(n);
}
n لا تتغير، فالشرط صحيح إلى الأبد ويطبع البرنامج 3 دون توقف. كل حلقة تحتاج إلى خطوة تقربها من النهاية.الدوال: محاضرتا 11 و12
التمرير بالقيمة. ماذا يطبع؟ تتبّعه أيضًا بزر «تتبّع سطرًا سطرًا».
public class PassByValue {
static void change(int x, int[] a) {
x = 99;
a[0] = 99;
}
public static void main(String[] args) {
int n = 1;
int[] list = {1, 2};
change(n, list);
System.out.println(n);
System.out.println(list[0]);
}
}أظهر الناتج
1 99
لماذا؟ يأخذ المعامل نسخة من القيمة دائمًا. نسخة n عدد، فلا يتأثر الأصل. ونسخة list عنوان المصفوفة نفسها، فيظهر التغيير في الأصل.
دالة تبديل. هل تبدّل القيمتين؟
public class SwapMethod {
static void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
}
public static void main(String[] args) {
int a = 1;
int b = 2;
swap(a, b);
System.out.println(a + " " + b);
}
}أظهر الناتج
1 2
لماذا؟ التبديل حدث في نسختين داخل الدالة، ثم اختفتا عند انتهائها. تشابه الأسماء لا يربط المتغيرين.
كل طريق يحتاج إلى return
أصلح الدالة لترجع القيمة الأكبر. لاحظ أن الرسالة تشير إلى آخر الدالة، لا إلى مكان محدد داخلها.
public class MaxOfTwo {
static int max(int a, int b) {
if (a > b) {
return a;
}
}
public static void main(String[] args) {
System.out.println(max(3, 8));
}
}missing return statementأظهر التصحيح
public class MaxOfTwo {
static int max(int a, int b) {
if (a > b) {
return a;
}
return b;
}
public static void main(String[] args) {
System.out.println(max(3, 8));
}
}8
لماذا؟ إذا لم يتحقق الشرط فلن تجد الدالة ما ترجعه. يطلب المترجم return في كل طريق ممكن عبر الدالة.
المحاضرة 12: أي دالة يستدعيها show(5.0) إذا وُجدت show(int) وshow(double)؟
5.0 من نوع double.المحاضرة 12: الاستدعاء الذاتي. ماذا يطبع؟
public class RecursionReview {
static int sum(int n) {
if (n == 0) {
return 0;
}
return n + sum(n - 1);
}
public static void main(String[] args) {
System.out.println(sum(4));
}
}أظهر الناتج
10
لماذا؟ 4 + 3 + 2 + 1 + 0 = 10. وشرط التوقف n == 0 هو ما يمنع الاستدعاء من الاستمرار إلى الأبد.
المصفوفات والنصوص: محاضرات 13 إلى 15
حدود المصفوفة
شغّله وأنت تعلم أنه سيتوقف: تظهر 3 أرقام، ثم ArrayIndexOutOfBoundsException: 3. غيّر الشرط إلى i < marks.length.
public class ArrayBounds {
public static void main(String[] args) {
int[] marks = {70, 85, 92};
for (int i = 0; i <= marks.length; i++) {
System.out.println(marks[i]);
}
}
}70 85 92
المحاضرة 13: نسخنا المصفوفة، أم لا؟ ماذا يطبع؟
public class ArrayAlias {
public static void main(String[] args) {
int[] a = {1, 2, 3};
int[] b = a;
b[0] = 9;
System.out.println(a[0]);
int[] c = new int[2];
System.out.println(c[1]);
}
}أظهر الناتج
9 0
لماذا؟ b = a لا تنشئ مصفوفة، بل اسمًا ثانيًا للمصفوفة نفسها. وعناصر int[] الجديدة تبدأ بالقيمة 0.
المحاضرة 14: Arrays والمصفوفة الثنائية. ماذا يطبع؟
import java.util.Arrays;
public class ArraysReview {
public static void main(String[] args) {
int[] nums = {3, 1, 2};
Arrays.sort(nums);
System.out.println(Arrays.toString(nums));
int[][] grid = {{1, 2, 3}, {4, 5, 6}};
System.out.println(grid.length);
System.out.println(grid[0].length);
System.out.println(grid[1][2]);
}
}أظهر الناتج
[1, 2, 3] 2 3 6
لماذا؟ grid.length عدد الصفوف، وgrid[0].length عدد أعمدة الصف الأول. والمواقع تبدأ من 0، فالموقع [1][2] هو آخر عنصر. وsort تغيّر المصفوفة نفسها، خلافًا لدوال النصوص.
ماذا يطبع System.out.println(marks); إذا كانت marks مصفوفة int[]؟
Arrays.toString(marks) أو حلقة.المحاضرة 15: ما الذي تغيّر فعلًا؟ ماذا يطبع؟
public class StringReview {
public static void main(String[] args) {
String s = " Gaza ";
s.trim();
System.out.println(s.length());
s = s.trim().toUpperCase();
System.out.println(s + s.length());
System.out.println(s.substring(1, 3));
}
}أظهر الناتج
6 GAZA4 AZ
لماذا؟ s.trim(); وحدها تهمل الناتج، فالطول ما زال 6. وبعد الحفظ يصبح الطول 4. وsubstring(1, 3) تأخذ الموقعين 1 و2 فقط.
الامتحان: 120 دقيقة وستة أسئلة تتصاعد صعوبتها
- شغّل مؤقتًا. الوقت المقترح مكتوب في عنوان كل سؤال، ومجموعه 120 دقيقة.
- لا تفتح التلميحات أو الحل حتى ينتهي الوقت، فلن تجدها في امتحان حقيقي.
- لا تطبع أي نص يطلب الإدخال، واطبع الناتج كما هو مطلوب تمامًا. زر «تحقّق من الحل» يشغّل عدة اختبارات، منها حالات حدية.
- إذا علقت في سؤال أكثر من وقته، فانتقل إلى التالي. الدرجات الجزئية موجودة.
السؤال 1 (10 دقائق): أجرة الموقف
اقرأ عدد الساعات عددًا صحيحًا. الساعتان الأوليان بسعر 2.50 للساعة، وكل ساعة بعدهما بسعر 1.50، والحد الأقصى للأجرة 15.00. اطبع Fee: مع الأجرة بمنزلتين. وإذا كان عدد الساعات صفرًا أو سالبًا فاطبع Invalid.
import java.util.Scanner;
public class Parking {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// Read the hours, work out the fee, print it
}
}1
Fee: 2.50
تلميح 1
Math.min(fee, 15.0) تطبق الحد الأقصى.
الحل
import java.util.Scanner;
public class Parking {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int hours = input.nextInt();
if (hours <= 0) {
System.out.println("Invalid");
} else {
double fee;
if (hours <= 2) {
fee = hours * 2.5;
} else {
fee = 5 + (hours - 2) * 1.5;
}
System.out.printf("Fee: %.2f%n", Math.min(fee, 15.0));
}
}
}السؤال 2 (15 دقيقة): الأرقام
اقرأ عددًا صحيحًا غير سالب. اطبع في ثلاثة أسطر: Digits: مع عدد أرقامه، وSum: مع مجموعها، وReversed: مع العدد معكوسًا بوصفه عددًا، فمعكوس 1200 هو 21. لا تستخدم النصوص، بل % و/.
import java.util.Scanner;
public class Digits {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// Take digits off the end with % 10 and / 10
}
}1234
Digits: 4 Sum: 10 Reversed: 4321
تلميح 1
الحالة 0 تحتاج انتباهًا: حلقة while (n > 0) لا تدور، لكن للعدد 0 رقم واحد. فكّر في do-while.
الحل
import java.util.Scanner;
public class Digits {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int digits = 0;
int sum = 0;
int reversed = 0;
do {
int last = n % 10;
digits++;
sum += last;
reversed = reversed * 10 + last;
n = n / 10;
} while (n > 0);
System.out.println("Digits: " + digits);
System.out.println("Sum: " + sum);
System.out.println("Reversed: " + reversed);
}
}السؤالان 3 و4: المصفوفات والدوال، ثم النصوص
السؤال 3 (20 دقيقة): تحليل مصفوفة
اقرأ n (واحد أو أكثر)، ثم n عددًا صحيحًا قد تكون سالبة. اكتب دالة لكل مطلوب، واطبع: Max: 9 at 2 أكبر قيمة وموقع أول ظهور لها، وAbove average: مع عدد القيم الأكبر تمامًا من المعدل الحقيقي، وReversed: مع القيم معكوسة تفصلها مسافة.
import java.util.Scanner;
public class ArrayStats {
// Write your methods here: indexOfMax, countAboveAverage, printReversed
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int[] values = new int[n];
// Read the values, then call your methods
}
}5 4 8 15 16 23
Max: 23 at 4 Above average: 3 Reversed: 23 16 15 8 4
تلميح 1
ابدأ بأول عنصر لا بصفر، فكل القيم قد تكون سالبة.
تلميح 2
المعدل double. قسمة الأعداد الصحيحة تعطي جوابًا خاطئًا في الاختبار الأخير.
الحل
import java.util.Scanner;
public class ArrayStats {
static int indexOfMax(int[] values) {
int best = 0;
for (int i = 1; i < values.length; i++) {
if (values[i] > values[best]) {
best = i;
}
}
return best;
}
static int countAboveAverage(int[] values) {
int sum = 0;
for (int value : values) {
sum += value;
}
double average = (double) sum / values.length;
int count = 0;
for (int value : values) {
if (value > average) {
count++;
}
}
return count;
}
static void printReversed(int[] values) {
System.out.print("Reversed:");
for (int i = values.length - 1; i >= 0; i--) {
System.out.print(" " + values[i]);
}
System.out.println();
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int[] values = new int[n];
for (int i = 0; i < n; i++) {
values[i] = input.nextInt();
}
int at = indexOfMax(values);
System.out.println("Max: " + values[at] + " at " + at);
System.out.println("Above average: " + countAboveAverage(values));
printReversed(values);
}
}السؤال 4 (20 دقيقة): تنسيق العناوين
اقرأ سطرًا قد يحوي مسافات زائدة. اطبع كلماته في سطر واحد بينها مسافة واحدة، وكل كلمة تبدأ بحرف كبير وبقيتها صغيرة. ثم اطبع Words: مع عددها، ثم Longest: مع أطول كلمة بعد تنسيقها، والأولى عند التساوي. وإذا كان السطر فارغًا فاطبع Words: 0 فقط.
import java.util.Scanner;
public class TitleCase {
// Write a method that formats one word
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String line = input.nextLine();
// Clean the line, split it, build the result
}
}hello world
Hello World Words: 2 Longest: Hello
تلميح 1
Character.toUpperCase(w.charAt(0)) + w.substring(1).toLowerCase() تنسق كلمة واحدة، وتعمل حتى لو كانت من حرف واحد.
تلميح 2
StringBuilder مناسب لبناء السطر. لا تضف مسافة قبل الكلمة الأولى.
الحل
import java.util.Scanner;
public class TitleCase {
static String format(String word) {
return Character.toUpperCase(word.charAt(0)) + word.substring(1).toLowerCase();
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String line = input.nextLine().trim();
if (line.length() == 0) {
System.out.println("Words: 0");
return;
}
String[] words = line.split("\\s+");
StringBuilder out = new StringBuilder();
String longest = "";
for (int i = 0; i < words.length; i++) {
String word = format(words[i]);
if (i > 0) {
out.append(" ");
}
out.append(word);
if (word.length() > longest.length()) {
longest = word;
}
}
System.out.println(out);
System.out.println("Words: " + words.length);
System.out.println("Longest: " + longest);
}
}السؤالان 5 و6: مصفوفة ثنائية، ثم برنامج يجمع كل شيء
السؤال 5 (25 دقيقة): مجاميع الجدول
اقرأ عدد الصفوف r وعدد الأعمدة c (واحد أو أكثر)، ثم قيم الجدول صفًا بعد صف. اطبع Row 0: مع مجموع كل صف، ثم Column 0: مع مجموع كل عمود، ثم Best row: مع موقع الصف ذي المجموع الأكبر، والأول عند التساوي. اكتب دالة rowSum ودالة columnSum.
import java.util.Scanner;
public class TableTotals {
// Write rowSum and columnSum here
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int r = input.nextInt();
int c = input.nextInt();
int[][] table = new int[r][c];
// Read the table, then print the totals
}
}2 3 1 2 3 4 5 6
Row 0: 6 Row 1: 15 Column 0: 5 Column 1: 7 Column 2: 9 Best row: 1
تلميح 1
في columnSum يتغير الصف ويثبت العمود: table[i][col]، وتدور الحلقة حتى table.length.
تلميح 2
الجدول ليس مربعًا دائمًا: لا تخلط بين r وc. وقد تكون كل المجاميع سالبة، فابدأ بالصف 0 لا بالقيمة 0.
الحل
import java.util.Scanner;
public class TableTotals {
static int rowSum(int[][] table, int row) {
int sum = 0;
for (int k = 0; k < table[row].length; k++) {
sum += table[row][k];
}
return sum;
}
static int columnSum(int[][] table, int col) {
int sum = 0;
for (int i = 0; i < table.length; i++) {
sum += table[i][col];
}
return sum;
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int r = input.nextInt();
int c = input.nextInt();
int[][] table = new int[r][c];
for (int i = 0; i < r; i++) {
for (int k = 0; k < c; k++) {
table[i][k] = input.nextInt();
}
}
int best = 0;
for (int i = 0; i < r; i++) {
System.out.println("Row " + i + ": " + rowSum(table, i));
if (rowSum(table, i) > rowSum(table, best)) {
best = i;
}
}
for (int k = 0; k < c; k++) {
System.out.println("Column " + k + ": " + columnSum(table, k));
}
System.out.println("Best row: " + best);
}
}السؤال 6 (30 دقيقة): تقرير من ملف درجات
السطر الأول n، ثم n سطرًا بالشكل name,m1,m2,m3، وقد توجد مسافات حول الفواصل. يكون السطر سليمًا إذا كان فيه أربع قطع، وكانت كل درجة أرقامًا فقط وقيمتها من 0 إلى 100. لكل سطر سليم اطبع Sara: 90.00 A، والحرف: A من 90، وB من 80، وC من 70، وD من 60، وإلا F. ولكل سطر غير سليم اطبع Line 2: invalid برقم السطر من 1. وفي النهاية اطبع Valid: 2 of 3، ثم Top: Sara 90.00 للمعدل الأعلى والأول عند التساوي، أو Top: none.
import java.util.Scanner;
public class MarksReport {
// Suggested methods: isMark(String text), letter(double average)
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = Integer.parseInt(input.nextLine().trim());
// Read n lines and process each one
}
}3 Sara,80,90,100 Omar,70,70,71 Huda,50,55,60
Sara: 90.00 A Omar: 70.33 C Huda: 55.00 F Valid: 3 of 3 Top: Sara 90.00
تلميح 1
اكتب isMark تفحص أن النص غير فارغ، وكل محارفه Character.isDigit، ثم حوّله وافحص المدى. الدرجة 0 يمكن أن تكون الأعلى، فلا تجعل top يبدأ من 0 مع >.
تلميح 2
قد تكون الدرجة الأولى فارغة بين فاصلتين، فلا تحوّل قبل الفحص، وإلا ظهر NumberFormatException.
الحل
import java.util.Scanner;
public class MarksReport {
static boolean isMark(String text) {
if (text.length() == 0 || text.length() > 3) {
return false;
}
for (int i = 0; i < text.length(); i++) {
if (!Character.isDigit(text.charAt(i))) {
return false;
}
}
return Integer.parseInt(text) <= 100;
}
static char letter(double average) {
if (average >= 90) {
return 'A';
} else if (average >= 80) {
return 'B';
} else if (average >= 70) {
return 'C';
} else if (average >= 60) {
return 'D';
}
return 'F';
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = Integer.parseInt(input.nextLine().trim());
int valid = 0;
String topName = "";
double topAverage = -1;
for (int line = 1; line <= n; line++) {
String[] parts = input.nextLine().split(",");
boolean good = parts.length == 4;
int total = 0;
for (int i = 1; good && i < 4; i++) {
String mark = parts[i].trim();
if (isMark(mark)) {
total += Integer.parseInt(mark);
} else {
good = false;
}
}
if (good) {
String name = parts[0].trim();
double average = total / 3.0;
System.out.printf("%s: %.2f %c%n", name, average, letter(average));
valid++;
if (average > topAverage) {
topAverage = average;
topName = name;
}
} else {
System.out.println("Line " + line + ": invalid");
}
}
System.out.println("Valid: " + valid + " of " + n);
if (valid == 0) {
System.out.println("Top: none");
} else {
System.out.printf("Top: %s %.2f%n", topName, topAverage);
}
}
}أسئلة المراجعة الأخيرة، وإلى اللقاء في برمجة 2
في مشروعنا نحتفظ بالأسماء في names والدرجات في marks. ما المشكلة عند ترتيب الطلاب؟
Student يضم الاسم والدرجات في كائن واحد، فتختفي هذه المشكلة.ما دور الصنف Stats في مشروعنا؟
Stats.average(row) باسم الصنف دون إنشاء كائن، كما نستدعي Math.sqrt. الأصناف التي تمثل أشياء بحقولها هي موضوع برمجة 2.