יום חמישי, 2 בנובמבר 2017

מערכים והלולאה C#) foreach)

Arrays


בשפת #C מערכים מתנהגים קצת שונה מבשפת C.

- לקביעת גודל של מערך אפשר להשתמש במשתנה.
- מערך הוא אובייקט (כמו הכל ב #C), יש לו שדה שמייצג את מספר איבריו: Length.


הגדרת מערך של int:
int[] Array;
מערך זה עדיין לא מאותחל. כרגע Array הוא רק "שם של מערך". בדומה לשפת C - שם של מערך הוא מצביע.
(בשפת #C לא משתמשים במצביעים, לכן לא נקפיד לקרוא לו בשם "מצביע". זכרו שהוא מתנהג כמו מצביע.)


כדי להתחיל להשתמש בו לאחסון מידע נצטרך לבצע לו איתחול:
Array = new int[5];
כעת Array הוא מערך מאותחל בגודל 5 איברים.
כשמערך מאותחל כל איבריו מקבלים את הערך 0.



ניתן לבצע את כל זה בשורה אחת:
int[] Array = new int[5];





אפשר להכניס ערכים כבר בשורת האתחול:
int[] Array = new int[5]{25,3,100,7,-3};


במקרה כזה אפשר לא לכתוב את הגודל:
int[] Array = new int[]{25,3,100,7,-3}; // הגודל יהיה 5






סריקת מערך תוך שימוש בשדה Length:
            for (int i = 0; i < Array.Length; i++)
            {
                Array[i] = 100;
            }

            for (int i = 0; i < Array.Length; i++)
            {
                Console.WriteLine(Array[i]);
            }




בדוגמה נתנו את הערך 100 לכל איברי המערך.
אפשר לקצר את יצירת המערך וההשמה לשורה אחת:
int[] Array = Enumerable.Repeat(100, 5).ToArray();
(לא נלמד כרגע למה הקוד הזה עובד)






ניתן לבצע '=' בין שני מערכים.
במקרה זה שניהם יאוחסנו באותה כתובת ולכן ישפיעו אחד על השני.
            int[] Array1 = new int[5] { 25, 3, 100, 7, -3 };
            int[] Array2 = Array1;
            for (int i = 0; i < Array2.Length; i++)
            {
                Console.WriteLine(Array2[i]); // print: 25, 3, 100, 7, -3  
            }
            Array2[0] = 0;
            for (int i = 0; i < Array1.Length; i++)
            {
                Console.WriteLine(Array1[i]);  // print: 0, 3, 100, 7, -3  
            }







ניתן לקצר הדפסת מערך לשורה אחת:
            int[] Array = new int[5] { 25, 3, 100, 7, -3 };
            Console.WriteLine(String.Join(", ",Array));
כעת כל המערך Array יודפס כשבין כל איבר מפריד " ,".










מערך דו-ממדי:
הגדרת ואתחול מערך דו-ממדי בשורה אחת:
int[,] Array = new int[4, 3];
כדי לקבל את מספר איברי המערך נשתמש כמו קודם בשדה Length.

כדי לקבל את האורך של מימד מסוים, לדוגמה כדי לקבל את ה"רוחב" של המערך, נשתמש בפונקציה (מספר)GetLength.
הפונקציה מקבלת את מספר המימד ומחזירה את אורכו.
0 - המימד הראשון
1 - המימד השני
2 - המימד השלישי (במערך תלת-מימדי)
וכו'


לדוגמה:
            int[,] ArrayD = new int[4,2];
            for (int i = 0; i < ArrayD.GetLength(0); i++)
            {
                for (int j = 0; j < ArrayD.GetLength(1); j++)
                {
                    Console.Write("Enter number: ");
                    ArrayD[i, j] = int.Parse(Console.ReadLine());
                }
            }
 
            for (int i = 0; i < ArrayD.GetLength(0); i++)
            {
                for (int j = 0; j < ArrayD.GetLength(1); j++)
                {
                    Console.Write(ArrayD[i,j]);
                }
                Console.WriteLine();
            }






אפשר להכניס ערכים כבר בשורת האתחול:
int[,] Array = new int[4, 3] { { 1, 2, 3 }, { 7, 6, 1 }, { 8, 9, 0 }, { 3, 3, 3 } };



ניתן לקצר הדפסת מערך דו-ממדי לשורה אחת:
            int[,] ArrayD = new int[4, 5]
            {   
                {10000,2,1,222,1},
                {5,60,1,-60,1},
                {-10,-15,1,1,1},
                {300,400,1,11,1}
            };
            Console.WriteLine(String.Join(" ", ArrayD.Cast<int>()));

החיסרון של השיטה: כל האיברים מודפסים בשורה אחת.






בדוגמה הבאה נדפיס מערך דו-ממדי בצורה מסודרת, כך שכל עמודה בגודל המדויק שנצרך לה.
כל זה תוך שימוש בפונקציה ()Print2DArray.
[נ.ב - באותו נושא של הדפסה מסודרת, תראו גם את הדוגמה האחרונה כאן]

    class Program
    {
        public static void Print2DArray(int[,] arr)
        {
            int[] BiggerstInEach = new int[arr.GetLength(0)]; // מאחסן את המספר הכי ארוך בכל עמודה
            for (int i = 0; i < arr.GetLength(0); i++)
            {
                int Max = 0;
                for (int j = 0; j < arr.GetLength(1); j++)
                {
                    int n;
                    n = arr[i, j].ToString().Length;
                    if (Max < n) Max = n;
                }
                BiggerstInEach[i] = Max;
            }
 
 
            String s = "";
            for (int j = 0; j < arr.GetLength(1); j++)
            {
                for (int i = 0; i < arr.GetLength(0); i++)
                {
                    s += arr[i, j].ToString().PadLeft(BiggerstInEach[i]);
                    // PadLeft במקום PadRight אם אתם רוצים אפשר לעשות יישור לצד שמאל עם
                    s += ", ";
                }
                s = s.Remove(s.Length - 2); // remove ", " from the end of the line
                s += "\n";
            }
 
            Console.WriteLine(s);
        }
 
 
        static void Main(string[] args)
        {
            int[,] ArrayD = new int[4, 5]
            {   
                {10000,2,1,222,1},
                {5,60,1,-60,1},
                {-10,-15,1,1,1},
                {300,400,1,11,1}
            };
            Print2DArray(ArrayD);
        }
    }










לולאת foreach
לולאת foreach מותאמת לעבודה עם מערכים. בלולאה מסוג זה אין צורך להגדיר משתנה שימנה את מספר האיטרציות שעברנו. הלולאה תנוע בעצמה על כל איברי המערך.
תחביר לולאה זו הוא נקי וקריא יותר, אך עדיין יש מי שיעדיפו את לולאת for הרגילה.
חסרונה הגדול של foreach:  היא לא יכולה להשפיע על המערך. רק לקרוא ממנו.

תחביר:
foreach(שם_כלשהו לייצוג_תוכן_האיברים  סוג_איברי_המערך  in שם_המערך){ . . . . }


הדפסת מערך:
            int[] arr = new int[] { 3, 4, 77, 1 };
            foreach (int x in arr)
            {
                Console.WriteLine(x);
                
            }













נושא נוסף שנלמד הוא "מערך של מערכים"

מקור: JavaTpoint

מערך של מערכים (Jagged Arrays) הוא מערך שמכיל בתוכו מספר מערכים.
הכתיבה אמנם דומה לכתיבה של מערך דו-ממדי, אך בשונה ממנו המערכים הפנימיים יכולים להיות בגדלים שונים אחד מהשני.


הגדרה ואתחול מערך של מערכים:
int[][] arr = new int[2][];
כעת יצרנו מערך שמכיל שני מערכים שגודלם עדיין לא ידוע.




אתחול המערכים הפנימיים:
            arr[0] = new int[4];
            arr[1] = new int[6];  




אפשר גם למלא אותם בשורת האתחול:
            arr[0] = new int[4] { 11, 21, 56, 78 };
            arr[1] = new int[6] { 42, 61, 37, 41, 59, 63 };







הדפסת תוכן כל המערכים הפנימיים:
        static void Main(string[] args)
        {
            int[][] arr = new int[2][];// הצהרה על המערך של מערכים
 
            arr[0] = new int[] { 11, 21, 56, 78 };// אתחול מערך ראשון
            arr[1] = new int[] { 42, 61, 37, 41, 59, 63 }; // אתחול מערך פנימי שני
 
            // הדפסה של תוכן המערכים הפנימיים
            for (int i = 0; i < arr.Length; i++)
            {
                for (int j = 0; j < arr[i].Length; j++) // תנאי היציאה: על פי גודל המערך הנוכחי
                {
                    System.Console.Write(arr[i][j] + " ");
                }
                System.Console.WriteLine();
            }
        } 
















מקור הרעיון לפונקציה "()Print2DArray":
stackoverflow (תשובה 5)

וכדי להבין את זה ראו גם:
PadLeft
GetUpperBound
StringBuilder.Append Method






בהצלחה!

אין תגובות:

הוסף רשומת תגובה