C++/מערכים
מערך הוא מבנה נתונים בסיסי. מערך מכיל מספר מסויים של איברים מטיפוסים זהים. לדוגמה: "מערך של 100 איברים מטיפוס int" הוא אזור בזיכרון שמכיל 100 מספרים שלמים.
תכונה חשובה של מערך היא שהזיכרון שמוקצה עבורו הוא זיכרון רציף, כלומר חלקי המערך לא מפוזרים במקומות שונים בזיכרון אלא כל האיברים נמצאים בכתובות עוקבות. בדוגמה שלנו, אם גודל משתנה שלם הוא 4 בתים, אז עבור המערך יוקצה זיכרון רציף בנפח של 100*4=400 בתים. כיוון שהזיכרון הזה הוא רציף, אם נדע את הכתובת של האיבר הראשון במערך, נוכל למצוא כל איבר אחר על ידי חישוב פשוט. למשל אם הכתובת של תחילת המערך (האיבר הראשון) היא 3400, אז כתובת האיבר העשירי תהיה: 3400 + 4*(10 - 1) = 3436.
אין צורך לעשות חישוב זה ידנית. ב-C++ קיימת פעולת גישה לפי אינדקס שנדגים אותה למטה. אינדקס הוא מספרו הסידורי של האיבר במערך. חשוב לזכור שב-C++ אינדקס האיבר הראשון הוא 0 ולא 1, באותו אופן אינדקס האיבר השני הוא 1, העשירי הוא 9, והאחרון במערך 100 איברים הוא 99. דבר זה חוסך מהמחשב את הפחתת ה-1 שביצענו בחישוב שלמעלה. יתר על כן, התחלת הספירה מ-0 נראת טבעית יותר ככל שמקבלים יותר ניסיון בתכנות.
השימוש במערכים בא ביחד עם לולאות ורקורסיה (נלמד בהמשך על פונקציות). אם ניצור 100 משתנים בשמות שונים, לא נוכל לעבוד עם כולם ביחד בתוך אלגוריתם אחד. כאמור במערך האיברים ממוספרים ולכן ניתן לכתוב אלגוריתמים שיעבדו מערכים ללא תלות בגודלם המעשי. למשל נוכל לכתוב אלגוריתם שמחפש את המקסימום בתוך מערך של מספרים שלמים וזה בעזרת לולאה אחת פשוטה. בדרך כלל יש תכונה שמאחדת את כל האיברים במערך מסויים. למשל בתוכנית ניהול של בית ספר, יתכן וניצור מערך של כל התלמידים עבור כל כיתה.
הגדרה
[עריכה]הגדרת המערך תראה כמו הגדרת משתנה רגיל שאחריו נכתוב את גודל המערך (ולא את אינדקס האיבר האחרון):
int a[100];
גודל המערך צריך להיות קבוע שערכו ידוע בזמן ההידור. למשל נוכל, ואף עדיף, להגיד את המערך כך:
const int N = 100;
int a[N];
במקרה כזה אם נרצה לשנות את גודל המערך, נשנה רק מספר אחד.
גישה לפי אינדקס
[עריכה]כעת נוכל לפנות לכל איבר במערך באמצעות אופרטור הגישה לפי אינדקס []:
a[0] = 20;
a[3] = a[0]+2;
cout << a[3]+a[0] << endl;
הפלט יהיה 42.
לאופרטור הגישה לפי אינדקס שני אופרנדים: הראשון שלפני הסוגריים הוא המערך עצמו, השני שנכתב בתוך הסוגריים הוא האינדקס של אליו נרצה לגשת. שני האופרנדים הם ביטויים לכל דבר, לכן נוכל לרשום בתוך הסוגריים גם, למשל, משתנה:
for(int i = 0; i < N; i++)
cout << a[i];
לולאה זו מדפיסה את כל איברי המערך.
איתחול
[עריכה]על מנת לאתחל מערך נוכל להשים לתוכו את הערכים הרצויים:
int prime[100];
prime[0] = 2;
prime[1] = 3;
prime[2] = 5;
prime[3] = 7;
prime[4] = 11;
// ...
אבל לכתוב 100 השמות לגמרי לא נוח. קיימת דרך לאתחל את המערך בשורת הגדרתו. אחרי הסימן = (שווה) נפתח סוגריים מסולסלים שבהם נרשום את רשימת הערכים שאיתם נרצה לאתחל את המערך:
int primes[100] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};
בשורת איתחול זו המתכנת התעצל לכתוב את כל 100 המספרים הראשוניים וכתב רק 12. הדבר לא יגרום לשגיאה, כל שאר הערכים, באינדקסים 12 עד 99 כולל, יואתחלו ל-0 אוטומטית. לעומת זאת אם נרשום בשורת האיתחול יותר איברים מגודל המערך שצויין לפני כן, המהדר יחזיר שגיאה.
לרוב כאשר נאתחל בדרך כזו את המערך, לא נתעניין במספר המעשי של האיברים בו. במקרה כזה נצטרך כל פעם שנשנה את איתחול המערך לספור מחדש את מספר האיברים ולעדכן את גודלו. הדבר לא נוח, לכן קיימת דרך נוספת. מותר לא לכתוב את הגודל בכלל ולהשאיר את הסוגריים ריקים. המהדר יחשב לבד את הגודל המעשי:
int primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};
נשאלת השאלה: כיצד נדע את גודל המערך בשאר התוכנית? ניתן לחשבו בעזרת האופרטור sizeof. מספר האיברים במערך שווה לגודלו בבתים חלקי גודל איבר אחד בבתים. כדי לא לעשות את החישוב בכל מקום בתוכנית, נוכל להגדיר קבוע:
const size_t primesCount = sizeof(primes)/sizeof(primes[0]);
מערכים רב-מימדיים
[עריכה]ניתן גם ליצור מערכים רב מימדיים, המשמעות היא שכל מקום במערך מכיל בתוכו עוד מספר מקומות אחרים, ניתן להסתכל על זה כמו על טבלה שיש בה מספר שורות וכל שורה יש בה מספר עמודות. לדוגמה כך תיצרו מערך בן 5 מקומות שכל מקום בתוכו מכיל 5 מקומות נוספים (ניתן כמובן לעשות עוד ועוד מימדים).
int array[5][5];
ניתן ליצור מערכים מאיזה סוג שנרצה (int, char וכו'). לדוגמא: בשביל לגשת לעמודה השניה בשורה השלישית נכתוב:
array[2][1]
כיון שכידוע ב- ++C המערך מתחיל מאינדקס [0] יש צורך להפחית 1 מהמקום המבוקש.
מחרוזות C
[עריכה]הפרק הקודם: לולאות |
מערכים | הפרק הבא: פונקציות |