المصفوفات
كيف نخزّن ثلاثين علامة دون ثلاثين متغيرًا؟
في نهاية هذه المحاضرة ستكون قادرًا على
- تشرح المصفوفة بأنها صف من الصناديق المرقّمة يجمعها اسم واحد
- تصرّح عن مصفوفة وتنشئها وتعطيها قيمًا أولية، وتعرف قيمها الافتراضية
- تقرأ العناصر وتكتبها باستخدام الموقع والخاصية
length - تمرّ على عناصر المصفوفة بحلقة
forوبحلقةforالمحسّنة، وتعرف متى لا تصلح الثانية - تقرأ رسالة
ArrayIndexOutOfBoundsExceptionوتصلح خطأ<= length - تمرّر المصفوفة إلى دالة وتعيدها منها، وتشرح لماذا تستطيع الدالة تغيير عناصرها
محتويات المحاضرة
- ثلاثون علامة في ثلاثين متغيرًا برنامج لا يريد أحد كتابته
- المصفوفة صف من الصناديق المرقّمة يجمعها اسم واحد
- ثلاث خطوات: التصريح، ثم الإنشاء، ثم إعطاء القيم
- المصفوفة الجديدة تمتلئ بقيم افتراضية
- المواقع تبدأ من 0، وآخر موقع هو
length - 1 - العنصر يُقرأ ويُكتب كأي متغير
- حلقة
forتمر على الصناديق واحدًا بعد الآخر - الحلقة نفسها تقرأ المصفوفة من لوحة المفاتيح
- الموقع خارج المصفوفة يوقف البرنامج أثناء التشغيل
<= lengthهو الخطأ الأشهر مع المصفوفات- حلقة
forالمحسّنة تقرأ كل العناصر دون موقع - الدالة تستقبل المصفوفة كلها في معامل واحد
- الدالة لا تغيّر وسيطًا بدائيًا، لكنها تغيّر عناصر المصفوفة
- الدالة تستطيع إنشاء مصفوفة جديدة وإعادتها
- أسئلة المراجعة
ثلاثون علامة في ثلاثين متغيرًا برنامج لا يريد أحد كتابته
تعرف حتى الآن أن المتغير يحمل قيمة واحدة. فإذا كان في الشعبة خمسة طلاب احتجت إلى خمسة متغيرات، وإذا صاروا ثلاثين احتجت إلى ثلاثين متغيرًا، وثلاثين سطر قراءة، وعملية جمع طويلة جدًا.
الطريقة المتعبة
شغّل البرنامج، ثم تخيّل أنك تضيف طالبًا سادسًا: كم سطرًا عليك أن تغيّر؟ جرّب ذلك.
public class FiveMarks {
public static void main(String[] args) {
int mark1 = 85;
int mark2 = 70;
int mark3 = 92;
int mark4 = 60;
int mark5 = 77;
int sum = mark1 + mark2 + mark3 + mark4 + mark5;
System.out.println(sum);
}
}384
المصفوفة صف من الصناديق المرقّمة يجمعها اسم واحد
- كل صندوق هنا متغير عادي من نوع
int، يسمى عنصرًا. - للصف كله اسم واحد هو
marks، ولكل صندوق رقم يسمى الموقع. - عناصر المصفوفة كلها من نوع واحد.
- عدد الصناديق يُحدد عند الإنشاء ولا يتغير بعد ذلك.
| المتغير | المصفوفة |
|---|---|
| صندوق واحد | صف من الصناديق |
نصل إليه باسمه: mark | نصل إلى العنصر بالاسم والموقع: marks[2] |
| الموقع غير موجود | يمكن أن يكون الموقع متغيرًا: marks[i] |
في المصفوفة أعلاه، أي تعبير يعطي العلامة 60، وهي الرابعة في الصف؟
ثلاث خطوات: التصريح، ثم الإنشاء، ثم إعطاء القيم
int[] يعني مصفوفة أعداد صحيحة. هذا السطر يحجز الاسم فقط، ولا صناديق بعد.
int[] marks;new تنشئ الصف بالعدد المطلوب من الصناديق.
marks = new int[5];ضع في كل صندوق قيمته، كما تفعل مع أي متغير.
marks[0] = 85;الخطوات الثلاث في برنامج
اضغط «تتبّع سطرًا سطرًا» وراقب الصف يظهر بعد سطر new، ثم يمتلئ. أضف عنصرًا رابعًا: ما السطران اللذان يجب تغييرهما؟
public class ThreeSteps {
public static void main(String[] args) {
int[] marks;
marks = new int[3];
marks[0] = 85;
marks[1] = 70;
marks[2] = 92;
System.out.println(marks[0] + marks[1] + marks[2]);
}
}247
إذا كنت تعرف القيم مسبقًا فاكتبها دفعة واحدة بين قوسين معقوفين، فتتم الخطوات الثلاث في سطر واحد ويحسب المترجم العدد بنفسه: int[] marks = {85, 70, 92};
صرّحنا ولم ننشئ
أصلح البرنامج ليطبع 85.
public class ForgotNew {
public static void main(String[] args) {
int[] marks;
marks[0] = 85;
System.out.println(marks[0]);
}
}might not have been initializedأظهر التصحيح
public class ForgotNew {
public static void main(String[] args) {
int[] marks = new int[3];
marks[0] = 85;
System.out.println(marks[0]);
}
}85
لماذا؟ التصريح وحده لا ينشئ صناديق، فلا يوجد marks[0] نكتب فيه. وتذكر الرسالة أن المتغير marks لم يأخذ قيمة، لأن new هي التي تعطيه الصف.
القوسان المعقوفان في سطر التصريح فقط
اجمع السطرين في سطر واحد حتى يترجم البرنامج.
public class BracesLater {
public static void main(String[] args) {
int[] marks;
marks = {85, 70, 92};
System.out.println(marks[2]);
}
}illegal start of expressionأظهر التصحيح
public class BracesLater {
public static void main(String[] args) {
int[] marks = {85, 70, 92};
System.out.println(marks[2]);
}
}92
لماذا؟ الصيغة {...} وحدها مسموحة فقط في سطر التصريح نفسه. ولا تذكر الرسالة ذلك صراحة؛ إنها تقول فقط إن المترجم لم يتوقع القوس هنا، ولهذا تبدو بعيدة عن السبب.
المصفوفة الجديدة تمتلئ بقيم افتراضية
| نوع العناصر | القيمة الافتراضية |
|---|---|
int | 0 |
double | 0.0 |
boolean | false |
char | المحرف الذي رمزه صفر، ولا يظهر عند الطباعة |
String | null |
ماذا يوجد في الصناديق قبل أن نكتب فيها؟
توقّع الأسطر الأربعة قبل التشغيل، ثم أضف السطر counts[0] = 5; قبل الطباعة وشغّل مرة أخرى.
public class Defaults {
public static void main(String[] args) {
int[] counts = new int[3];
double[] prices = new double[3];
boolean[] paid = new boolean[3];
String[] names = new String[3];
System.out.println(counts[0]);
System.out.println(prices[1]);
System.out.println(paid[2]);
System.out.println(names[0]);
}
}0 0.0 false null
المواقع تبدأ من 0، وآخر موقع هو length - 1
تحفظ كل مصفوفة عدد صناديقها في length. وفي مصفوفة من 4 عناصر تكون المواقع 0 و1 و2 و3، فلا يوجد موقع 4.
الأول والأخير والطول
أضف عنصرين إلى القوسين المعقوفين وشغّل. لاحظ أن آخر عنصر يُطبع صحيحًا دون أن تغيّر الأسطر التي تحت.
public class IndexAndLength {
public static void main(String[] args) {
int[] marks = {85, 70, 92, 60};
System.out.println(marks.length);
System.out.println(marks[0]);
System.out.println(marks[marks.length - 1]);
}
}4 85 60
length بلا قوسين
public class LengthParens {
public static void main(String[] args) {
int[] marks = {85, 70, 92};
System.out.println(marks.length());
}
}cannot find symbolأظهر التصحيح
public class LengthParens {
public static void main(String[] args) {
int[] marks = {85, 70, 92};
System.out.println(marks.length);
}
}3
لماذا؟ length في المصفوفة قيمة محفوظة وليست دالة، فكتابة القوسين تجعل المترجم يبحث عن دالة بهذا الاسم فلا يجدها.
المصفوفة int[] a = new int[10];. ما أكبر موقع مسموح به؟
العنصر يُقرأ ويُكتب كأي متغير
marks[1] متغير كامل: يوضع يسار = ليستقبل قيمة، ويوضع يمينها لتُقرأ قيمته، ويقبل ++ و+=. وما بين القوسين يمكن أن يكون أي تعبير نتيجته عدد صحيح.
اكتب الصناديق الثلاثة على الورق وحدّثها بعد كل سطر. ماذا يُطبع؟
public class ReadWrite {
public static void main(String[] args) {
int[] a = new int[3];
a[0] = 4;
a[1] = a[0] + 5;
a[2] = a[1] * 2;
a[0] = a[2] - a[1];
System.out.println(a[0]);
System.out.println(a[1]);
System.out.println(a[2]);
}
}أظهر الناتج
9 9 18
لماذا؟ كل سطر يقرأ القيم الحالية في الصناديق: a[1] تصبح 9، وa[2] تصبح 18، ثم تتغير a[0] من 4 إلى 18 − 9 = 9.
الموقع يمكن أن يكون متغيرًا أو تعبيرًا
توقّع الأسطر الأربعة، ثم شغّل. غيّر i إلى 0 وتوقّع مرة أخرى. وماذا لو صارت i تساوي 3؟ جرّب، وسنشرح ما يحدث بعد قليل.
public class IndexExpression {
public static void main(String[] args) {
int[] marks = {85, 70, 92, 60};
int i = 1;
System.out.println(marks[i]);
System.out.println(marks[i + 1]);
marks[i] = marks[i] + 10;
marks[i + 1]++;
System.out.println(marks[1]);
System.out.println(marks[2]);
}
}70 92 80 93
حلقة for تمر على الصناديق واحدًا بعد الآخر
النمط الذي ستكتبه مئات المرات
اضغط «تتبّع سطرًا سطرًا» وراقب i تتحرك على المواقع. ثم عدّل الحلقة لتطبع من الأخير إلى الأول: ابدأ من marks.length - 1 وتوقف عند 0.
public class Traverse {
public static void main(String[] args) {
int[] marks = {85, 70, 92};
for (int i = 0; i < marks.length; i++) {
System.out.println("marks[" + i + "] = " + marks[i]);
}
}
}marks[0] = 85 marks[1] = 70 marks[2] = 92
| الجزء | السبب |
|---|---|
int i = 0 | أول موقع |
i < marks.length | الموقع الأخير أقل من الطول بواحد، ويبقى صحيحًا إذا غيّرنا عدد العناصر |
i++ | الصندوق التالي |
marks[i] | العنصر الحالي |
الحلقة نفسها تقرأ المصفوفة من لوحة المفاتيح
لا يلزم أن نعرف عدد الصناديق وقت كتابة البرنامج: اقرأ العدد أولًا، ثم أنشئ مصفوفة بهذا الحجم، ثم املأها بحلقة.
اقرأ العلامات ثم اطبعها
المدخلات هنا: 3، ثم 85 و70 و92. لاحظ أن رقم العلامة للمستخدم هو i + 1، لأن الناس يعدّون من 1. غيّر البرنامج ليطبع مجموع العلامات في النهاية.
import java.util.Scanner;
public class ReadMarks {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("How many marks? ");
int n = in.nextInt();
int[] marks = new int[n];
for (int i = 0; i < marks.length; i++) {
System.out.print("Mark " + (i + 1) + ": ");
marks[i] = in.nextInt();
}
System.out.println();
System.out.println("You entered:");
for (int i = 0; i < marks.length; i++) {
System.out.println(marks[i]);
}
}
}How many marks? Mark 1: Mark 2: Mark 3: You entered: 85 70 92
اطبع بالعكس
اقرأ عددًا صحيحًا n، ثم n عددًا صحيحًا في مصفوفة. اطبع العناصر من الأخير إلى الأول، كل عنصر في سطر. لا تطبع أي رسائل طلب.
import java.util.Scanner;
public class Backwards {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// Read n, create the array, fill it, then print it backwards
}
}3 10 20 30
30 20 10
تلميح 1
تحتاج إلى حلقتين: واحدة للقراءة وواحدة للطباعة.
تلميح 2
حلقة الطباعة: for (int i = n - 1; i >= 0; i--).
الحل
import java.util.Scanner;
public class Backwards {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] numbers = new int[n];
for (int i = 0; i < n; i++) {
numbers[i] = in.nextInt();
}
for (int i = n - 1; i >= 0; i--) {
System.out.println(numbers[i]);
}
}
}الموقع خارج المصفوفة يوقف البرنامج أثناء التشغيل
تجربة مخطط لها: نكسر البرنامج عمدًا
في المصفوفة خمسة عناصر، فلا يوجد marks[5]. شغّل البرنامج واقرأ الرسالة الحمراء كاملة. لاحظ أن المترجم لم يعترض، وأن Done لم تُطبع. غيّر 5 إلى 7 وشاهد الرقم يتغير في الرسالة.
public class OutOfBounds {
public static void main(String[] args) {
int[] marks = {85, 70, 92, 60, 77};
System.out.println(marks[4]);
System.out.println(marks[5]);
System.out.println("Done");
}
}77
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
at OutOfBounds.main(OutOfBounds.java:5)| الجزء | معناه |
|---|---|
ArrayIndexOutOfBoundsException | اسم الاستثناء: الموقع خارج حدود المصفوفة |
5 | الموقع الخاطئ نفسه، وهو أهم ما في الرسالة |
OutOfBounds.java:5 | الملف والسطر الذي توقف عنده البرنامج |
ماذا يظهر في الناتج العادي قبل أن يتوقف البرنامج؟
public class CrashPoint {
public static void main(String[] args) {
int[] a = {1, 2, 3};
int i = 2;
System.out.println(a[i]);
i++;
System.out.println("i is " + i);
System.out.println(a[i]);
System.out.println("end");
}
}أظهر الناتج
3 i is 3
لماذا؟ تنفذ الأسطر بالترتيب حتى يصل البرنامج إلى a[3]. هناك يتوقف ولا يطبع end، والمصفوفة لا تعطي 0 لموقع غير موجود.
<= length هو الخطأ الأشهر مع المصفوفات
أصلح الحلقة
هذا البرنامج يترجم، ثم يتوقف عند التشغيل بعد طباعة كل العناصر. شغّله واقرأ الرقم في الرسالة: أي قيمة كانت في i؟ أصلح الشرط حتى تظهر الكلمة Done، واستخدم «تتبّع سطرًا سطرًا» لترى الدورة الأخيرة.
public class LengthBug {
public static void main(String[] args) {
int[] marks = {85, 70, 92};
for (int i = 0; i <= marks.length; i++) {
System.out.println(marks[i]);
}
System.out.println("Done");
}
}85 70 92
أي حلقة تمر على كل عناصر a دون خطأ؟
حلقة for المحسّنة تقرأ كل العناصر دون موقع
«لكل علامة في العلامات»
اقرأ السطر هكذا: لكل mark من marks. في كل دورة تحمل mark نسخة من العنصر التالي. أضف عنصرًا واطبع مجموع العناصر.
public class EnhancedFor {
public static void main(String[] args) {
int[] marks = {85, 70, 92};
for (int mark : marks) {
System.out.println(mark);
}
}
}85 70 92
هل تغيّر الحلقة الأولى عناصر المصفوفة؟
public class EnhancedCopy {
public static void main(String[] args) {
int[] numbers = {1, 2, 3};
for (int n : numbers) {
n = n * 10;
}
for (int n : numbers) {
System.out.println(n);
}
}
}أظهر الناتج
1 2 3
لماذا؟ n متغير منفصل يحمل نسخة من العنصر. تغيير النسخة لا يصل إلى الصندوق الأصلي. وهذه الفكرة نفسها ستعود بعد قليل مع الدوال.
| تريد أن | for المحسّنة | for العادية |
|---|---|---|
| تقرأ كل العناصر بالترتيب | نعم، وهي الأوضح | نعم |
| تعرف موقع العنصر | لا | نعم |
| تغيّر عناصر المصفوفة | لا | نعم |
| تمر من الأخير إلى الأول | لا | نعم |
| تمر على جزء من المصفوفة | لا | نعم |
| تقارن عنصرًا بالذي يليه | لا | نعم |
بعد النقطتين مصفوفة، لا عدد
public class ForEachLength {
public static void main(String[] args) {
int[] marks = {85, 70};
for (int mark : marks.length) {
System.out.println(mark);
}
}
}for-each not applicable to expression typeأظهر التصحيح
public class ForEachLength {
public static void main(String[] args) {
int[] marks = {85, 70};
for (int mark : marks) {
System.out.println(mark);
}
}
}85 70
لماذا؟ marks.length عدد واحد، والحلقة المحسّنة تحتاج إلى شيء تمر عليه عنصرًا بعد عنصر.
الدالة تستقبل المصفوفة كلها في معامل واحد
دالة تعمل مع أي طول
نوع المعامل هو int[]، أما عند الاستدعاء فنمرر الاسم فقط. استدعِ total بمصفوفة ثالثة من عنصر واحد.
public class ArrayParameter {
static int total(int[] numbers) {
int sum = 0;
for (int n : numbers) {
sum += n;
}
return sum;
}
public static void main(String[] args) {
int[] section1 = {85, 70, 92};
int[] section2 = {60, 77};
System.out.println(total(section1));
System.out.println(total(section2));
}
}247 137
لا أقواس مربعة عند الاستدعاء
public class CallBrackets {
static int first(int[] numbers) {
return numbers[0];
}
public static void main(String[] args) {
int[] marks = {85, 70};
System.out.println(first(marks[]));
}
}'.class' expectedأظهر التصحيح
public class CallBrackets {
static int first(int[] numbers) {
return numbers[0];
}
public static void main(String[] args) {
int[] marks = {85, 70};
System.out.println(first(marks));
}
}85
لماذا؟ int[] تُكتب في تعريف الدالة لبيان النوع، أما عند الاستدعاء فنكتب اسم المصفوفة فقط. والرسالة '.class' expected تبدو غريبة تمامًا، لكنها تظهر غالبًا لهذا السبب.
الدالة لا تغيّر وسيطًا بدائيًا، لكنها تغيّر عناصر المصفوفة
في محاضرة الدوال فشلت محاولتنا لكتابة دالة تبدّل متغيرين، لأن الوسيط يُمرَّر بالقيمة، فتعمل الدالة على نسخة. شغّل المثالين بالتتبّع وقارن.
تذكّر: التبديل الفاشل
اضغط «تتبّع سطرًا سطرًا». داخل swap تتبدل a وb، فهما نسختان. وعند العودة إلى main تكون x وy لم تتغيرا.
public class FailedSwap {
static void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
}
public static void main(String[] args) {
int x = 5;
int y = 9;
swap(x, y);
System.out.println(x + " " + y);
}
}5 9
التبديل نفسه داخل مصفوفة ينجح
تتبّع البرنامج سطرًا سطرًا وتوقف داخل swap. لاحظ أن arr وpair يشيران إلى الصف نفسه، فما تكتبه الدالة تراه main.
public class ArraySwap {
static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void main(String[] args) {
int[] pair = {5, 9};
swap(pair, 0, 1);
System.out.println(pair[0] + " " + pair[1]);
}
}9 5
| ما يوجد في المتغير | ما يصل إلى الدالة | هل تتأثر main؟ |
|---|---|---|
int x: القيمة 5 نفسها | نسخة من 5 | لا |
int[] pair: سهم يشير إلى الصف | نسخة من السهم تشير إلى الصف نفسه | نعم، في العناصر |
دالتان متشابهتان، إحداهما تأخذ int والأخرى int[]. ماذا يطبع البرنامج؟
public class DoubleBoth {
static void doubleValue(int x) {
x = x * 2;
}
static void doubleAll(int[] arr) {
for (int i = 0; i < arr.length; i++) {
arr[i] = arr[i] * 2;
}
}
public static void main(String[] args) {
int n = 5;
int[] a = {3, 4};
doubleValue(n);
doubleAll(a);
System.out.println(n);
System.out.println(a[0]);
System.out.println(a[1]);
}
}أظهر الناتج
5 6 8
لماذا؟ doubleValue غيّرت نسختها من 5 فقط. أما doubleAll فكتبت في الصف الذي تشير إليه a.
الأمر نفسه دون دالة: int[] b = a;. هل صار لدينا صفان؟
public class TwoNames {
public static void main(String[] args) {
int[] a = {1, 2, 3};
int[] b = a;
b[0] = 99;
System.out.println(a[0]);
System.out.println(b[0]);
}
}أظهر الناتج
99 99
لماذا؟ new وحدها تنشئ صفًا جديدًا. السطر int[] b = a; نسخ السهم، فصار للصف الواحد اسمان.
دالة علامات إضافية
اكتب الدالة static void addBonus(int[] marks, int bonus) التي تزيد كل علامة بمقدار bonus داخل المصفوفة نفسها، على ألا تتجاوز العلامة 100. في main اقرأ n، ثم n علامة، ثم bonus. استدعِ الدالة واطبع العلامات، كل علامة في سطر.
import java.util.Scanner;
public class Bonus {
// Write addBonus here
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// Read the input, call addBonus, print the marks
}
}3 50 90 70 5
55 95 75
تلميح 1
لتغيير العناصر تحتاج إلى for العادية، فالمحسّنة تعمل على نسخة.
تلميح 2
الدالة لا تعيد شيئًا: main ترى التغيير في المصفوفة نفسها.
الحل
import java.util.Scanner;
public class Bonus {
static void addBonus(int[] marks, int bonus) {
for (int i = 0; i < marks.length; i++) {
marks[i] = marks[i] + bonus;
if (marks[i] > 100) {
marks[i] = 100;
}
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] marks = new int[n];
for (int i = 0; i < n; i++) {
marks[i] = in.nextInt();
}
int bonus = in.nextInt();
addBonus(marks, bonus);
for (int mark : marks) {
System.out.println(mark);
}
}
}الدالة تستطيع إنشاء مصفوفة جديدة وإعادتها
دالة نوع إرجاعها int[]
اضغط «تتبّع سطرًا سطرًا». ينتهي result عند انتهاء الدالة، لكن الصف يبقى لأن main أخذت السهم إليه. غيّر الدالة لتعيد المكعبات بدل المربعات.
public class ReturnArray {
static int[] squares(int n) {
int[] result = new int[n];
for (int i = 0; i < n; i++) {
result[i] = (i + 1) * (i + 1);
}
return result;
}
public static void main(String[] args) {
int[] s = squares(4);
for (int value : s) {
System.out.println(value);
}
}
}1 4 9 16
أول الأعداد الزوجية
اكتب الدالة static int[] firstEvens(int n) التي تعيد مصفوفة فيها أول n عددًا زوجيًا: 2، 4، 6، وهكذا. في main اقرأ n واطبع العناصر، كل عنصر في سطر.
import java.util.Scanner;
public class FirstEvens {
// Write firstEvens here
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// Read n, call firstEvens, print the result
}
}4
2 4 6 8
تلميح 1
العنصر في الموقع i يساوي (i + 1) * 2.
الحل
import java.util.Scanner;
public class FirstEvens {
static int[] firstEvens(int n) {
int[] evens = new int[n];
for (int i = 0; i < n; i++) {
evens[i] = (i + 1) * 2;
}
return evens;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
for (int value : firstEvens(n)) {
System.out.println(value);
}
}
}من علامة إلى نسبة مئوية
اكتب الدالة static double[] toPercent(int[] marks, int outOf) التي تعيد مصفوفة جديدة فيها كل علامة نسبةً مئوية، وتترك الأصلية دون تغيير. في main اقرأ n ثم outOf ثم n علامة، واطبع كل نسبة في سطر، ثم اطبع العلامة الأصلية الأولى.
import java.util.Scanner;
public class Percent {
// Write toPercent here
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// Read the input, call toPercent, print the results
}
}2 50 45 25
90.0 50.0 45
تلميح 1
طول المصفوفة الجديدة هو marks.length، ونوعها double[].
تلميح 2
تذكّر قسمة الأعداد الصحيحة: اكتب marks[i] * 100.0 / outOf.
الحل
import java.util.Scanner;
public class Percent {
static double[] toPercent(int[] marks, int outOf) {
double[] result = new double[marks.length];
for (int i = 0; i < marks.length; i++) {
result[i] = marks[i] * 100.0 / outOf;
}
return result;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int outOf = in.nextInt();
int[] marks = new int[n];
for (int i = 0; i < n; i++) {
marks[i] = in.nextInt();
}
for (double p : toPercent(marks, outOf)) {
System.out.println(p);
}
System.out.println(marks[0]);
}
}أسئلة المراجعة
ماذا تحوي new double[4] مباشرة بعد إنشائها؟
double هي 0.0.أي مهمة لا تستطيع حلقة for المحسّنة القيام بها؟
for المحسّنة نسخة من كل عنصر، فالكتابة فيها لا تصل إلى الصندوق. أما البقية فتقرأ فقط.البرنامج يتوقف بالرسالة ArrayIndexOutOfBoundsException: 3. ماذا تعني 3؟
<= length، لكن قد يكون أي قيمة خارج الحدود. أما رقم السطر فيظهر في السطر التالي من الرسالة.هذه الدالة تنشئ صفًا جديدًا وتكتب فيه. ماذا يطبع البرنامج؟
public class Replace {
static void replace(int[] arr) {
arr = new int[2];
arr[0] = 9;
}
public static void main(String[] args) {
int[] a = {1, 2};
replace(a);
System.out.println(a[0]);
}
}أظهر الناتج
1
لماذا؟ arr نسخة من السهم. السطر الأول جعل هذه النسخة تشير إلى صف جديد، فبقي a يشير إلى الصف القديم. الدالة تغيّر عناصر الصف الذي تصل إليه، لكنها لا تغيّر السهم الموجود في main.