מערכים סטאטיים
מערך סטאטי הוא מערך בו מספר האיברים ידוע לפני ריצת התוכנית - בזמן קומפילציה. הסינטקס להגדרת מערך של N איברים מטיפוס type בשם array היא:
type array[N];
כאשר N הוא קבוע כלשהו הידוע בזמן קומפילציה.
לדוגמא, נגדיר מערך של 100 איברי int בשם grades עבור הציונים של 100 סטודנטים:
int grades[100];
על מנת לגשת לאיבר כלשהו בתוך המערך, לאחר הגדרתו ניתן להשתמש באופרטור הסוגריים המרובעים - נניח שהסטודנט ה-64 קיבל ציון 75 במבחן:
int grades[100];
grades[64] = 75;
ננתח:
- המשתנה
gradesהוא מערך באורך 100 של משתניint. בהמשך ננתח בפירוט את הטיפוס שלו. - המשתנה
grades[64]לעומתו הוא משתנהintרגיל לחלוטין. - המספר
64בהקשר זה נקרא האינדקס של האיבר. - האיבר הראשון במערך הוא
grade[0]ולאgrades[1]כפי שאולי ניתן לצפות. האיבר האחרון במערך הואgrades[99], אוgrades[N - 1]עבורNגודל המערך.
גבולות מערכים
לכל מערך יש אינדקס מינימלי ומקסימלי בהם ניתן להשתמש על מנת לגשת לאיברים שבו. נבחן למשל את הדוגמא הבאה:
#define N 30
int main() {
int array[N];
array[-1] = 0;
array[N + 1] = -3;
}
תוכנית זו אינה חוקית וככל הנראה תקרוס בזמן ריצתה. גישה לאיבר מחוץ לגבולות מערך הוא נקרא out of bounds error, והוא מקור נפוץ לבאגים, ורצוי להמנע ממנו.
אתחול מערכים
ניתן לתת ערכים התחלתיים למערך סטאטי ע״י שימוש בסינטקס הבא:
#include <stdio.h>
int main(void) {
// With length
int numbers1[4] = {1, -3, 10, 5};
// Inferred length
int numbers2[] = {1, -3, 10, 5};
// Given and inferred length mismatch
int numbers3[2] = {1, -3, 10, 5};
int numbers4[6] = {1, -3, 10, 5};
// Initializer all elements
int numbers5[4] = {0};
}
לרשימת האיברים שבתוך הסוגריים המסולסלים המופרדים בפסיקים נקרא רשימת אתחול, או initializer list. נבחין בין 4 אופציות:
- עבור
numbers1הגדרנו גם אורך וגם ערך התחלתי לכל הערכים. - עבור
numbers2נתתו לקומפיילר להסיק מהו האורך של המערך ע״י קריאת רשימת האתחול. - עבור
numbers3אורך המערך שנתנו קצר מאורך רשימת התאחול. במקרה זה רשימת האתחול ילקחו שני האיברים הראשונים מרשימת האתחול והשאר לא יכנסו למערך, שאורכו קבוע. - עבור
numbers4אורך רשימת האתחול קצר מאורך המערך. במקרה זה רשימת האתחול כולה תאכלס את תחילת המערך, ושאר האיברים יאותחלו ל-0. - עבור
numbers5כל האיברים מאותחלים לאיבר0.
בצורה דומה למשתנים אחרים, רצוי כדאי להמנע מאיברים שאינם מאותחלים בתוך המערכים בהם נשתמש. מצד שני, לפעמים נגדיר מערך ומיד ״נאכלס״ את האיברים שבו, כך שאתחול יכול להיות מיותר - יש להזהר ולפעול לפי צורך התוכנית הנוכחית.
דוגמא
בקורס שמונה 100 סטודנטים ניגשו למבחן. יתכן וחלק מהסטודנטים לא ניגשו למבחן. לכל סטודנט יש מזהה בין 0 ל-100. כתבו תוכנית המקבלת ברצף עבור כל סטודנט ניגש למבחן את המזהה שלו ואת ציונו, כאשר מזהה שלילי מסמן את סוף הציונים. התוכנית תדפיס את הממוצע של הסטודנטים שניגשו למבחן ואת המזהים של כל הסטודנטים שלא ניגשו למבחן.
#include <stdio.h>
#define N 100
#define NO_GRADE -1
int main() {
int grades[N] = {NO_GRADE};
while (1) {
int id;
int grade;
scanf("%d %d", &id, &grade);
if (id < 0) {
break;
}
grades[id] = grade;
}
int grades_sum = 0;
int nstudents = 0;
for (int id = 0; id < N; id++) {
int grade = grades[id];
if (grade == NO_GRADE) {
printf("%d\n", id);
} else {
grades_sum += grade;
nstudents++;
}
}
printf("Average: %d\n", grades_sum / nstudents);
}