Skip to content · ⁨דלג לתוכן⁩
Subjects · ⁨נושאים⁩
  • 1 C basics · ⁨בסיסי C⁩
    1.1

    main, printf & פונקציות

    English

    Every C program starts in main. #include <stdio.h> pulls in a header 头文件 so you can use printf to print. A function 函数 is a named block you can call; \n starts a new line. main returns 0 to mean "success".

    עברית

    כל תוכנית C מתחילה בmain. #include <stdio.h> כולל קובץ ראש כדי שתוכל להשתמש בprintf להדפסה. פונקציה היא בלוק עם שם שמכיל הוראות; \n מייצר שורה חדשה. main מחזיר 0 כדי לסמן "הצלחה".

    #include <stdio.h>
    
    void greet(void) {
        printf("Hello, world!\n");
    }
    
    int main(void) {
        greet();
        printf("I am learning C.\n");
        return 0;
    }
    
    כל תוכנית C רצה מה-main לאחר כלולת קבצי ראש
    כל תוכנית C רצה מה-main לאחר כלולת קבצי ראש
    1.2

    משתנים, סוגים וחישובים

    English

    C needs a type for every variable: int (integer 整数), double (floating-point 浮点数), char (one character). printf uses a format specifier 格式说明符 — %d, %f, %c — for each value. / between two ints is integer division; % is the remainder 余数.

    The format string drives both printing and reading:

    Specifier Type Example output
    %d int 17
    %f double (%.2f = 2 decimal places) 3.14
    %c char A
    %s a string Mei
    %zu a size (from sizeof / strlen) 3
    %x int, printed in base 16 ff

    scanf("%d", &n) reads keyboard input with the same specifiers (note the &). Its sibling sscanf parses values out of a string, so it runs anywhere:

    עברית

    C דורשת סוג לכל משתנה: int (שלם), double (מנוף צף), char (תווה אחד). printf משתמש בספק פורמט — %d, %f, %c — עבור כל ערך. / בין שני שלמים היא חילוק שלם; % הוא השארית.

    #include <stdio.h>
    
    int main(void) {
        int n = 17;
        double pi = 3.14;
        char grade = 'A';
        printf("%d %.2f %c\n", n, pi, grade);   // 17 3.14 A
        printf("%d %d\n", 7 / 2, 7 % 2);        // 3 1
        return 0;
    }
    

    מחרוזת הפורמט מנעה גם הדפסה וגם קריאה:

    ספן סוג דוגמת תוצאה
    %d int 17
    %f double (%.2f = 2 מקומות עשרוניים) 3.14
    %c char A
    %s מחרוזת Mei
    %zu גודל (מ-sizeof / strlen) 3
    %x int, מודפס בבסיס 16 ff

    scanf("%d", &n) קורא קלט ממקלדת באותם ספנים (שימו לב ל&). האח הגדול שלו, sscanf, פורש ערכים ממחרוזת, ולכן ניתן לרוץ אותו בכל מקום:

    #include <stdio.h>
    
    int main(void) {
        char line[] = "Mei 88";
        char name[20];
        int score;
        sscanf(line, "%19s %d", name, &score);   // parse text -> values
        printf("%s scored %d\n", name, score);   // Mei scored 88
        return 0;
    }
    
    1.3

    הערות סגנון

    English

    A comment 注释 is a note for humans; the compiler ignores it. Use // for one line and /* ... */ for a block. Good indentation 缩进 and clear names make code easy to read.

    Common mistakes

    • Every statement ends with ;, and main should return int (return 0;).
    • printf needs a format string: %d for int, %f for double, and \n for a new line.
    • A wrong format like %d for a double prints garbage — match the type.
    עברית

    תגובה היא הערה לאנשים; המתרגם מתעלם ממנה. השתמשו ב-// לקו אחד וב-/* ... */ לחסימת טקסט. ניקוד ותוארים ברורים הופכים את הקוד לקריא.

    #include <stdio.h>
    
    int main(void) {
        // a single-line comment
        /* a block
           comment */
        int total = 3 + 4;       // clear names help
        printf("%d\n", total);   // 7
        return 0;
    }
    

    שגיאות נפוצות

    • כל הוראה מסתיימת ב-;, ו-main אמורה להחזיר int (return 0;).
    • printf דורש שורת פורמט: %d עבור int, %f עבור double, ו-\n עבור שורה חדשה.
    • פורמט שגוי כמו %d עבור double מדפיס גרועות — התאם את הסוג.
  • 2 Selection · ⁨בחירה⁩
    2.1

    if / else

    English

    An if runs a block when a condition 条件 is true. C has no real boolean 布尔值 type by default: 0 is false and any non-zero value is true. Chain choices with else if and else. Compare with ==, !=, <, >, <=, >=.

    עברית

    מבנה if מפעיל בלוק כאשר תנאי הוא אמת. ל-C אין סוג בוליאני אמיתי ברירת מחדל: 0 הוא שגויה וכל ערך שאינו אפס הוא אמת. חברו אפשרויות עם else if ו-else. השוו עם ==, !=, <, >, <=, >=.

    #include <stdio.h>
    
    int main(void) {
        int score = 72;
        if (score >= 90) {
            printf("A\n");
        } else if (score >= 60) {
            printf("Pass\n");
        } else {
            printf("Fail\n");
        }
        return 0;
    }
    
    if בוחר את הענף האמת; else את הענף השגוי
    if בוחר את הענף האמת; else את הענף השגוי
    2.2

    switch

    English

    A switch picks one case by an integer value. Each case needs a break to jump out 跳出 — without it, C "falls through" into the next case. default runs when nothing matches.

    Common mistakes

    • if (x = 5) assigns and is always true; use == to compare.
    • Each switch case needs a break;, or it falls through to the next.
    • 0 is false and any non-zero value is true in a condition.
    עברית

    מבנה switch בוחר ענף case אחד על בסיס ערך שלם. כל ענף case זקוק להוראת break כדי לצאת — ללאה, C "נופל" לענף הבא. default פועל כאשר אינו מתאים דבר.

    #include <stdio.h>
    
    int main(void) {
        int day = 3;
        switch (day) {
            case 1: printf("Mon\n"); break;
            case 2: printf("Tue\n"); break;
            case 3: printf("Wed\n"); break;
            default: printf("Other\n");
        }
        return 0;
    }
    

    שגיאות נפוצות

    • if (x = 5) משתנה ומתמיד אמת; השתמשו ב-== להשוואה.
    • לכל ענף switch יש צורך בהוראת break;, או שהוא יופל לענף הבא.
    • 0 היא שגויה וכל ערך שאינו אפס הוא אמת בתנאי.
  • 3 Loops · ⁨לולאות⁩
    3.1

    while & for loops

    English

    A loop 循环 repeats a block. A while loop runs as long as a condition is true. A for loop packs the start, the test, and the increment 自增 (i++) into one line — best when you know how many times to repeat.

    עברית

    לולאה חוזרת על בלוק. לולאת while פועלת כל עוד תנאי הוא אמת. לולאת for מארגנת את ההתחלה, הבדיקה וההגברה (i++) בשורה אחת — הטובה ביותר כאשר ידוע כמה פעמים לחזור.

    #include <stdio.h>
    
    int main(void) {
        int i = 1;
        while (i <= 3) {
            printf("%d ", i);
            i++;
        }
        printf("\n");                    // 1 2 3
        for (int j = 0; j < 5; j++) {
            printf("%d ", j);
        }
        printf("\n");                    // 0 1 2 3 4
        return 0;
    }
    
    while בודק תנאי; for סופר עם צעד
    while בודק תנאי; for סופר עם צעד
    3.2

    הצטברות

    English

    A common pattern: start an accumulator 累加器 at 0, then add to it inside a loop. The same idea counts items or finds a running total.

    עברית

    דפוס נפוץ: התחילו מצטבר ב-0, ואז הוסיפו אליו בתוך לולאה. אותה רעיון סופר פריטים או מוצא סכום רץ.

    #include <stdio.h>
    
    int main(void) {
        int total = 0;
        for (int i = 1; i <= 5; i++) {
            total += i;            // 1 + 2 + 3 + 4 + 5
        }
        printf("%d\n", total);     // 15
        return 0;
    }
    
    3.3

    Nested loops & patterns

    English

    A loop inside another loop is a nested 嵌套 loop. The inner loop finishes fully for each step of the outer loop — perfect for grids and patterns.

    Common mistakes

    • for (i = 0; i < n; i++) runs n times; a semicolon right after for (...) makes an empty loop.
    • A while whose condition never becomes false loops forever.
    • Declare the counter (int i) before or inside the for header.
    עברית

    לולאה בתוך לולאה אחרת היא לולאה מקוננת. הלולאה הפנימית מסתיימת במלואה עבור כל צעד בלולאה החיצונית — מושלם לגרידים ולדפוסים.

    #include <stdio.h>
    
    int main(void) {
        for (int row = 0; row < 3; row++) {
            for (int col = 0; col < 3; col++) {
                printf("*");
            }
            printf("\n");
        }
        return 0;
    }
    

    שגיאות נפוצות

    • for (i = 0; i < n; i++) פועל n פעמים; נקודה-פסיק immediately לאחר for (...) יוצרת לולאה ריקה.
    • לולאת while שהתנאי שלה לעולם לא הופך לשגויה לולאה לנצח.
    • הכריזו את הסופר (int i) לפני או בתוך כותרת ה-for.
  • 4 Functions · ⁨פונקציות⁩
    4.1

    Parameters & return values

    English

    A function takes parameters 参数 (inputs) and gives back a return value 返回值. The return type comes first (int, double, …); void means it returns nothing.

    עברית

    פונקציה לוקחת פרמטרים (כניסות) וחוזרת ערך חזרה. סוג החזרה מגיע קודם (int, double, …); void פירושה שהיא מחזירה דבר כלל.

    #include <stdio.h>
    
    int square(int x) {        // x is a parameter
        return x * x;          // hand back a value
    }
    
    int main(void) {
        int r = square(5);
        printf("%d\n", r);     // 25
        return 0;
    }
    
    פרמטרים כניסה; ערך חזרה יציאה
    פרמטרים כניסה; ערך חזרה יציאה
    4.2

    פרוטוטיפים וטווח

    English

    C reads top to bottom, so a function must be known before it is called. A prototype 函数原型 — the header line plus ; — declares it early so you can keep main first. A variable's scope 作用域 is the block it lives in: it is local 局部 and disappears when the block ends.

    Common mistakes

    • A function used before it is defined needs a prototype above main.
    • Arguments are passed BY VALUE — changes inside a function do not affect the caller unless you pass a pointer.
    • A variable declared inside a function is local to it.
    עברית

    C קורא מלמעלה למטה, ולכן פונקציה חייבת להיות מוגדרת לפני השימוש בה. פרוטוטיפ — שורת הכותרת plus ; — מכריז עליה מוקדם כדי שתוכל לשמור על main בתחילה. טווח של משתנה הוא הבלוק שבו הוא מתגורר: הוא מקומי ונעלם כאשר הבלוק מסתיים.

    #include <stdio.h>
    
    int add(int a, int b);     // prototype: declared before use
    
    int main(void) {
        printf("%d\n", add(3, 4));   // 7
        return 0;
    }
    
    int add(int a, int b) {    // definition comes later
        int sum = a + b;       // sum is local to add
        return sum;
    }
    

    שגיאות נפוצות

    • פונקציה המשמשת לפני ההגדרה שלה צריכה הגדרה (prototyping) מעל main.
    • ארגומנטים עוברים בערך — שינויים בתוך פונקציה אינם משפיעים על הקורא אלא אם כן עוברת נקודת היפנית (pointer).
    • משתנה המוגדר בתוך פונקציה הוא מקומי לה.
  • 5 Arrays · ⁨מערכים⁩
    5.1

    מערךים בעלי ממד 1

    English

    An array 数组 holds several values of one type. Index 索引 from 0. C does not store an array's length, so a common trick computes the element 元素 count: sizeof(a) / sizeof(a[0]).

    עברית

    מעריך מחזיק מספר ערכים מאותו סוג. אינדקס מתחיל ב0. C אינו אוגר את אורך המערכת, לכן טריק נפוץ מחשב את מספר האלמנטים: sizeof(a) / sizeof(a[0]).

    #include <stdio.h>
    
    int main(void) {
        int scores[3] = {88, 71, 95};
        printf("%d\n", scores[0]);     // 88
        scores[1] = 100;
        printf("%d\n", scores[1]);     // 100
        int n = sizeof(scores) / sizeof(scores[0]);
        printf("%d\n", n);             // 3
        return 0;
    }
    
    מקושי מערכת ממוספרים החל מ-0
    מקושי מערכת ממוספרים החל מ-0
    5.2

    אלגוריתמים למערכים

    English

    Traverse 遍历 an array with a for loop to find a max, a total, or a count. Always loop from 0 up to n - 1.

    עברית

    עבור על מערכת עם לולאת for כדי למצוא מקסימום, סכום או ספירה. תמיד לולאה מהערך 0 ועד הערך n - 1.

    #include <stdio.h>
    
    int main(void) {
        int a[] = {3, 9, 2, 7};
        int n = sizeof(a) / sizeof(a[0]);
        int max = a[0], total = 0;
        for (int i = 0; i < n; i++) {
            if (a[i] > max) max = a[i];
            total += a[i];
        }
        printf("%d %d\n", max, total);   // 9 21
        return 0;
    }
    
    5.3

    מערךים בעלי ממד 2

    English

    A 2-D array is a grid of rows 行 and columns 列: grid[row][col]. Use two nested loops to visit every cell.

    Common mistakes

    • C does NOT check array bounds: writing a[n] in a size-n array is undefined behaviour.
    • Valid indexes run from 0 to n - 1.
    • The array name is a pointer to its first element; sizeof only gives the size in the array's own scope.
    עברית

    מערך בעל ממד 2 הוא טבלה של שורות ועמודות: grid[row][col]. השתמש בשני לולאות מקוננות כדי לבקר בכל תא.

    #include <stdio.h>
    
    int main(void) {
        int grid[2][3] = {{1, 2, 3}, {4, 5, 6}};
        printf("%d\n", grid[1][2]);    // 6
        for (int r = 0; r < 2; r++) {
            for (int c = 0; c < 3; c++) {
                printf("%d ", grid[r][c]);
            }
        }
        printf("\n");                  // 1 2 3 4 5 6
        return 0;
    }
    

    שגיאות נפוצות

    • C אינו בודק גבולות מערכת: כתיבה בa[n] במערכת בגודל n היא התנהגות לא מוגדרת (undefined behaviour).
    • אינדקסים תקפים רצים מהערך 0 עד הערך n - 1.
    • שם המערכת הוא נקודת היפנית אל האלמנט הראשון שלה; sizeof נותן את הגודל רק בטווח הפנימי של המערכת.
  • 6 Pointers · ⁨איشارות⁩
    6.1

    &, * והעברה באמצעות נקודת היפנית

    English

    A pointer 指针 stores the address 地址 of a variable. &x gives the address of x; *p dereferences 解引用 the pointer — it reads or writes the value stored there. Passing a pointer lets a function change the caller's variable (pass-by-pointer).

    The classic use is a swap function. Passing values only copies them — the swap is lost. Passing pointers lets the function reach the caller's variables:

    An array name acts as a pointer to its first element, and pointer arithmetic 指针运算 steps by whole elements:

    • NULL is the pointer that points at nothing — check for it before you dereference.

    Common mistakes

    • &x is the address of x; *p is the value stored at p.
    • Never use *p on an uninitialised or NULL pointer — it crashes or corrupts memory.
    • To change a caller's variable, pass its address and write through the pointer.
    עברית

    נקודת היפנית אחסנת כתובת של משתנה. &x נותן את הכתובת של x; *p מבצע פירוק (dereference) לנקודת ההיפנית — הוא קורא או כותב את הערך האחסן שם. העברת נקודת היפנית מאפשרת לפונקציה לשנות את המשתנה של הקורא (pass-by-pointer).

    נקודת היפנית אחסנת כתובת; פירוקה עוקב אחרי החץ לערך
    מצביע מאחסן כתובת; גישה דרכו עוקבת אחרי החץ לערך
    #include <stdio.h>
    
    void addOne(int *p) {     // p holds an address
        *p = *p + 1;          // change the value at that address
    }
    
    int main(void) {
        int x = 10;
        int *ptr = &x;        // & takes the address of x
        printf("%d\n", *ptr); // * reads the value: 10
        addOne(&x);
        printf("%d\n", x);    // 11 — changed through the pointer
        return 0;
    }
    

    השימוש הקלאסי הוא בפונקציית החלפת ערכים. העברת ערכים מייצרת רק העתקה — ההחלפה אבדה. העברת מצביעים מאפשרת לפונקציה לגשת למשתנים של הקורא:

    #include <stdio.h>
    
    void swap_values(int a, int b) {      // copies: the caller sees nothing
        int t = a; a = b; b = t;
    }
    
    void swap_pointers(int *a, int *b) {  // addresses: the swap is real
        int t = *a; *a = *b; *b = t;
    }
    
    int main(void) {
        int x = 1, y = 2;
        swap_values(x, y);
        printf("%d %d\n", x, y);   // 1 2  (unchanged!)
        swap_pointers(&x, &y);
        printf("%d %d\n", x, y);   // 2 1  (swapped)
        return 0;
    }
    

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

    #include <stdio.h>
    
    int main(void) {
        int a[] = {10, 20, 30};
        int *p = a;                 // same as &a[0]
        printf("%d\n", *p);         // 10
        printf("%d\n", *(p + 2));   // 30 — same as a[2]
        return 0;
    }
    
    • NULL הוא המצביע שמצביע ללא כלום — בדק אותו לפני הגישה.

    שגיאות נפוצות

    • &x היא הכתובת של x; *p הוא הערך הארוז בp.
    • לעולם אל תשתמש ב*p על מצביע לא מוזמן או NULL — זה יגרם לקריסה או להפרעת זיכרון.
    • כדי לשנות משתנה של קורא, העבר את הכתובת שלו וכתוב דרך המצביע.
  • 7 Strings · ⁨מחרוזות⁩
    7.1

    מערכי Char ומסוף נול

    English

    A C string 字符串 is an array of char. Every string ends with a hidden null terminator 空终止符 '\0', which marks where it stops. strlen (from <string.h>) counts characters up to that '\0'. Print a whole string with %s and one character 字符 with %c.

    You can traverse a string by looping until you reach '\0'.

    עברית

    מחרוזת C היא מערך של char. כל מחרוזת מסתיימת במסוף נול נסתר '\0', שמסמן היכן היא נפסקת. strlen (מ-<string.h>) סופר תווים עד מסוף זה '\0'. הדפס מחרוזת שלמה עם %s ותווה אחד עם %c.

    #include <stdio.h>
    #include <string.h>
    
    int main(void) {
        char name[] = "Mei";            // 'M', 'e', 'i', '\0'
        printf("%s\n", name);           // Mei
        printf("%zu\n", strlen(name));  // 3 (stops at '\0')
        printf("%c\n", name[0]);        // M
        return 0;
    }
    
    מחרוזת C היא מערך char הנסתיים במסוף נול נסתר
    מחרוזת C היא מערך char הנסתיים במסוף נול נסתר

    ניתן לעבור על מחרוזת באמצעות לולאה עד שתגיע ל-'\0'.

    #include <stdio.h>
    
    int main(void) {
        char word[] = "banana";
        int count = 0;
        for (int i = 0; word[i] != '\0'; i++) {
            if (word[i] == 'a') count++;
        }
        printf("%d\n", count);   // 3
        return 0;
    }
    
    7.2

    הספרייה string.h

    English

    #include <string.h> gives you the everyday string tools:

    Function Does
    strlen(s) the length, not counting the terminator
    strcpy(dst, src) copy — dst must be big enough
    strcat(dst, src) append src onto the end of dst
    strcmp(a, b) compare: 0 when equal, else negative / positive
    • strcmp returns 0 for equal, so the test is strcmp(a, b) == 0 — never a == b.
    • The destination array must have room for the result plus the terminator.

    Common mistakes

    • A C string needs one extra byte for the \0 terminator: a 5-letter word needs char[6].
    • Copy and compare strings with strcpy / strcmp, not = / ==.
    • Forgetting the \0 makes printf("%s", ...) run past the end of the text.
    עברית

    #include <string.h> מספק לך את כלים שגרתיים למחרוזות:

    פונקציה ביצוע
    strlen(s) האורך, בלי לספור את המסוף
    strcpy(dst, src) העתקה — dst חייב להיות גדול מספיק
    strcat(dst, src) הוספת src בסוף dst
    strcmp(a, b) השוואה: 0 כאשר שוות, אחרת שלילי / חיובי
    #include <stdio.h>
    #include <string.h>
    
    int main(void) {
        char full[40];
        strcpy(full, "Mei");           // full is now "Mei"
        strcat(full, " Chen");         // append -> "Mei Chen"
        printf("%s (%zu)\n", full, strlen(full));       // Mei Chen (8)
        printf("%d\n", strcmp("apple", "apple") == 0);  // 1 (equal)
        return 0;
    }
    
    • strcmp מחזירה 0 עבור שוויון, ולכן הבדיקה היא strcmp(a, b) == 0 — לעולם לא a == b.
    • מערך היעד חייב להכיל מקום לתוצאה בנוסף למסוף.

    שגיאות נפוצות

    • מחרוזת C דורשת בייט נוסף למסייר \0: מילה בעלת 5 אותיות דורשת char[6].
    • העתק והשווה מחרוזות עם strcpy / strcmp, לא עם = / ==.
    • שכחון את המסייר \0 גורם לprintf("%s", ...) להמשיך מעבר לסוף הטקסט.
  • 8 Structs · ⁨מבנים (structs)⁩
    8.1

    מבנה (struct), typedef, . מול ->

    English

    A struct 结构体 groups related values into one type. Each value is a member 成员. typedef gives the struct a short name so you can write Dog instead of struct Dog. Use . on a struct value, but -> on a pointer to a struct.

    Common mistakes

    • Use . on a struct value and -> on a struct pointer.
    • typedef lets you drop the word struct when declaring; without it you write struct Point p;.
    • Assigning one struct to another copies all its fields.
    עברית

    מבנה (struct) מקבץ ערכים קשורים לסוג אחד. כל ערך הוא חבר. typedef נותן למבנה שם קצר כך שתוכל לכתוב Dog במקום struct Dog. השתמש ב. על ערך מבנה, אך ב-> על מצביע למבנה.

    #include <stdio.h>
    
    typedef struct {
        char name[20];
        int age;
    } Dog;
    
    int main(void) {
        Dog d = {"Rex", 3};
        printf("%s is %d\n", d.name, d.age);   // Rex is 3   (. on a value)
    
        Dog *p = &d;
        p->age = 4;                            // -> on a pointer
        printf("%s is %d\n", d.name, d.age);   // Rex is 4
        return 0;
    }
    

    שגיאות נפוצות

    • השתמש ב-. על ערך מבנה, וב--> על רמז למבנה.
    • typedef מאפשר לך לוותר על המילה struct בהצהרת סוג; ללא זה תכתוב struct Point p;.
    • החלפת מבנה אחד באחר מעתיקה את כל השדות שלו.
    . עבור ערכי מבנה; -> עבור מצביעים למבנים
    . עבור ערכי מבנה; -> עבור מצביעים למבנים
  • 9 Dynamic memory · ⁨זיכרון דינמי⁩
    9.1

    malloc, free & realloc

    English

    malloc allocates 分配 memory on the heap 堆 at run time and returns a pointer to it. realloc resizes that block; free gives it back. Every malloc needs a matching free, or you get a memory leak 内存泄漏. These live in <stdlib.h>.

    • calloc(n, size) allocates an array like malloc AND fills it with zeros.

    Common mistakes

    • Every malloc needs a matching free; forgetting to free leaks memory.
    • Using memory after free (a "use-after-free") is a serious bug.
    • Check that malloc did not return NULL before you use the memory.
    עברית

    malloc מקצה זיכרון על הגוש בזמן הרצה וחוזר עליו עם מצביע. realloc משנה את גודל חסימה זו; free מחזירה אותו בחזרה. כל malloc זקוק ל-free התואם לו, אחרת תקבלו דליפת זיכרון. אלו חיים ב-<stdlib.h>.

    משתנים מקומיים גרים בערימה; זיכרון malloc גר בגרעין עד שתשחרר אותו
    משתנים מקומיים גרים בערימה; זיכרון malloc גר בגרעין עד שתשחרר אותו
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void) {
        int n = 3;
        int *a = malloc(n * sizeof(int));    // room for 3 ints
        for (int i = 0; i < n; i++) a[i] = i * 10;
    
        a = realloc(a, 4 * sizeof(int));     // grow to 4 ints
        a[3] = 30;
    
        for (int i = 0; i < 4; i++) printf("%d ", a[i]);
        printf("\n");                        // 0 10 20 30
    
        free(a);                             // hand the memory back
        return 0;
    }
    
    • calloc(n, size) הקצית מערך כמו malloc AND ממלא אותו באפסים.

    שגיאות נפוצות

    • כל malloc זקוק ל-free התואם לו; שכחת הפקת זיכרון (free) גורמת לדליפת זיכרון.
    • שימוש בזיכרון לאחר free ("שימוש-אחרי-שחרור") הוא באג קשה.
    • בדוק שהmalloc לא החזיר NULL לפני שימוש בזיכרון.
  • 10 Data structures · ⁨מבני נתונים⁩
    10.1

    רשימות מקשרות

    English

    A linked list 链表 is a chain of nodes 节点. Each node holds a value and a pointer to the next node; the last one points to NULL. Unlike an array it grows one node at a time with malloc. Always free every node when done.

    עברית

    רשימה מקשרת היא שרשרת של צמתים. כל צומח מכיל ערך ומצביע לצומח הnext; האחרון מצביע לNULL. בניגוד למערכת, היא גדלה בצומח אחד בכל פעם עם malloc. תמיד free את כל הצמתים כשנסיימת.

    רשימה מקשרת: כל צומח מכיל ערך ומצביע הבא, מסתיים ב-NUL
    רשימה מקושרת: כל נקודה מחזירה ערך ומצביע לנקודה הבאה, והסיום הוא NULL
    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct Node {
        int value;
        struct Node *next;
    } Node;
    
    int main(void) {
        Node *head = NULL;
        for (int v = 10; v <= 30; v += 10) {   // prepend 10, 20, 30
            Node *n = malloc(sizeof(Node));
            n->value = v;
            n->next = head;
            head = n;
        }
        for (Node *p = head; p != NULL; p = p->next) {
            printf("%d ", p->value);           // 30 20 10
        }
        printf("\n");
    
        while (head != NULL) {                 // free the whole list
            Node *t = head;
            head = head->next;
            free(t);
        }
        return 0;
    }
    
    10.2

    ערימות ותורים

    English

    A stack 栈 is LIFO 后进先出 (last in, first out): push and pop at the same end. A queue 队列 is FIFO 先进先出 (first in, first out): add at the back, remove from the front. Both are easy to build on an array with index variables.

    Common mistakes

    • In a linked list, never lose the head pointer, or the whole list is unreachable.
    • Free every node when you are done, walking the list before you unlink.
    • Check for an empty list (a NULL head) before you pop.
    עברית

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

    #include <stdio.h>
    
    int main(void) {
        int stack[10];
        int top = 0;                       // next free slot
        stack[top++] = 1;                  // push
        stack[top++] = 2;
        stack[top++] = 3;
        while (top > 0) {
            printf("%d ", stack[--top]);   // pop: 3 2 1
        }
        printf("\n");
        return 0;
    }
    
    #include <stdio.h>
    
    int main(void) {
        int queue[10];
        int front = 0, back = 0;
        queue[back++] = 1;                       // enqueue
        queue[back++] = 2;
        queue[back++] = 3;
        while (front < back) {
            printf("%d ", queue[front++]);       // dequeue: 1 2 3
        }
        printf("\n");
        return 0;
    }
    

    שגיאות נפוצות

    • ברשימה מקושרת, לעולם אל תאבד את מצביע הhead, אלא כל הרשימה תהייה לא נגישה.
    • שחרר כל נקודה כשסיימת, תוך כדי העברה על הרשימה לפני ניתוק הקישורים.
    • בדוק רשימה ריקה (ראש NULL) לפני ביצוע הפעלת הוצאה.
  • 11 Searching, sorting & recursion · ⁨חיפוש, מיון ורצוריות⁩
    11.1

    חיפוש ליניארי וחיפוש בנארי

    English

    Linear search 线性查找 checks each element in turn — it works on any array. Binary search 二分查找 is far faster but needs a sorted 已排序 array: it checks the middle and discards half each step. Both return the index, or -1 if missing.

    עברית

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

    #include <stdio.h>
    
    int linear(int a[], int n, int target) {
        for (int i = 0; i < n; i++)
            if (a[i] == target) return i;
        return -1;
    }
    
    int binary(int a[], int n, int target) {
        int lo = 0, hi = n - 1;
        while (lo <= hi) {
            int mid = (lo + hi) / 2;
            if (a[mid] == target) return mid;
            else if (a[mid] < target) lo = mid + 1;
            else hi = mid - 1;
        }
        return -1;
    }
    
    int main(void) {
        int a[] = {2, 5, 8, 12, 16, 23};
        int n = sizeof(a) / sizeof(a[0]);
        printf("%d %d %d\n", linear(a, n, 12), binary(a, n, 12), binary(a, n, 9));
        return 0;   // 3 3 -1
    }
    
    סריקה ליניארית בודקת הכל; בינארית מחצית טווח ממוין
    חיפוש ליניארי סורק הכל; בנארי חוצה טווח ממוין
    11.2

    מיון

    English

    Bubble sort 冒泡排序 repeatedly compares neighbours and swaps 交换 any pair that is out of order. After each pass the largest value "bubbles" to the end.

    עברית

    מיון בועות מבצע השוואות חוזרות בין שכנים ומחליף כל זוג שאינו במצב מסודר. לאחר כל מעבר, הערך הגדול ביותר "עולה" לקצה.

    #include <stdio.h>
    
    int main(void) {
        int a[] = {5, 2, 9, 1, 7};
        int n = sizeof(a) / sizeof(a[0]);
        for (int i = 0; i < n - 1; i++) {
            for (int j = 0; j < n - 1 - i; j++) {
                if (a[j] > a[j + 1]) {
                    int t = a[j]; a[j] = a[j + 1]; a[j + 1] = t;
                }
            }
        }
        for (int i = 0; i < n; i++) printf("%d ", a[i]);
        printf("\n");   // 1 2 5 7 9
        return 0;
    }
    
    11.3

    רקורסיה

    English

    Recursion 递归 is a function that calls itself. It needs a base case 基准情形 to stop, and a recursive call that steps toward it. Without a base case it never ends.

    Common mistakes

    • Binary search needs a sorted array; recursion needs a base case.
    • Each recursive call must move closer to the base case, or the stack overflows.
    • Bubble and insertion sort are O(n²) — fine to learn, slow at scale.
    עברית

    רקורסיה היא פונקציה הקוראת לעצמה. היא דורשת מקרה בסיסי להפסקה, וקריאה רקורסיבית שמקרב אותה אליו. ללא מקרה בסיסי, היא לעולם לא תסתיים.

    #include <stdio.h>
    
    int factorial(int n) {
        if (n <= 1) return 1;          // base case
        return n * factorial(n - 1);   // recursive call
    }
    
    int main(void) {
        printf("%d\n", factorial(5));  // 120
        return 0;
    }
    

    שגיאות נפוצות

    • חיפוש בנארי דורש מערך ממוין; רקורסיה דורשת מקרה בסיסי.
    • לכל קריאה רקורסיבית יש להתקרב יותר למקרה הבסיסי, אלא תתרחש התפרצות ערימה.
    • מיון בועות ומיון הכנסה הם O(n²) — טוב ללמידה, איטי בקנה מידה גדול.
  • 12 Files & errors · ⁨קבצים ושגיאות⁩
    12.1

    קבצי טקסט

    English

    fopen returns a file pointer 文件指针; the mode 模式 string says what to do — "w" write, "r" read, "a" append. Write with fprintf, read with fscanf, and always fclose when done.

    עברית

    fopen מחזירה מצביע לקובץ; מחרוזת המצב אומרת מה לעשות — "w" כתיבה, "r" קריאה, "a" הצרפה. כתוב עם fprintf, קרא עם fscanf, ובכל פעם סיים עם fclose.

    #include <stdio.h>
    
    int main(void) {
        FILE *out = fopen("scores.txt", "w");   // open for writing
        fprintf(out, "Alice 80\nBob 95\n");
        fclose(out);
    
        FILE *in = fopen("scores.txt", "r");    // open for reading
        char name[20];
        int score;
        while (fscanf(in, "%s %d", name, &score) == 2) {
            printf("%s -> %d\n", name, score);
        }
        fclose(in);
        return 0;
    }
    
    fopen → קריאה/כתיבה → fclose
    fopen → קריאה/כתיבה → fclose
    12.2

    טיפול בשגיאות עם קודי חזרה

    English

    C has no exceptions. Instead a function signals failure with a return code 返回码 — by convention 0 means success and non-zero means an error. The caller checks the code before trusting the result. (fopen follows the same idea: it returns NULL when it fails.)

    Common mistakes

    • Check that fopen did not return NULL before reading or writing.
    • Always fclose a file when you are done.
    • Return a non-zero code from main to signal an error to the caller.
    עברית

    C אינה תומכת בשיבולים (exceptions). במקום זאת, פונקציה מסמלת כשל באמצעות קוד חזרה — לפי המוסכמה 0 מעיד על הצלחה ואי-אפס מעיד על שגיאה. הקורא בודק את הקוד לפני שהוא סומך לתוצאה. (fopen עוקב אחר אותה רעיון: הוא מחזיר NULL כאשר נכשל.)

    #include <stdio.h>
    
    // returns 0 on success, -1 if the divisor is 0
    int safe_divide(int a, int b, int *result) {
        if (b == 0) return -1;          // error code
        *result = a / b;
        return 0;                       // success
    }
    
    int main(void) {
        int r;
        if (safe_divide(10, 2, &r) == 0)
            printf("10 / 2 = %d\n", r);          // 10 / 2 = 5
        if (safe_divide(10, 0, &r) != 0)
            printf("cannot divide by zero\n");   // error reported
        return 0;
    }
    

    שגיאות נפוצות

    • לוודא ש-fopen לא החזיר NULL לפני הקריאה או הכתיבה.
    • תמיד סגור fclose קובץ לאחר השלמת העבודה.
    • החזר קוד שאינו אפס מmain כדי לסמן שגיאה לקורא.
  • 13 Bits & data · ⁨ביטים ומידע⁩
    13.1

    ביטים, בינארי ותפעולי ביט

    English

    A bit 位 is a single 0 or 1; numbers are stored in binary 二进制. Bitwise 按位 operators work on the bits directly: & AND, | OR, ^ XOR, << shift left (×2 each step), >> shift right (÷2).

    Hexadecimal 十六进制 (base 16) writes binary compactly: one hex digit is exactly four bits. Write hex literals with 0x; print with %x:

    עברית

    ביט הוא 0 או 1 בודד; מספרים מאוחסנים בבינארי. תפעולי ביט פועלים ישירות על הביטים: & AND, | OR, ^ XOR, << הזזה שמאלה (×2 בכל שלב), >> הזזה ימינה (÷2).

    #include <stdio.h>
    
    int main(void) {
        int a = 12;              // 1100
        int b = 10;              // 1010
        printf("%d\n", a & b);   // 8   AND  -> 1000
        printf("%d\n", a | b);   // 14  OR   -> 1110
        printf("%d\n", a ^ b);   // 6   XOR  -> 0110
        printf("%d\n", a << 1);  // 24  left shift
        printf("%d\n", a >> 1);  // 6   right shift
        return 0;
    }
    

    מערכת מצומצמת (בסיס 16) כותבת בינארי בצורה דחוסה: דיgit אחד במצומצת הוא בדיוק ארבעה ביטים. כתוב ליטרלים מצומצמים עם 0x; הדפס עם %x:

    #include <stdio.h>
    
    int main(void) {
        printf("%d\n", 0xFF);   // 255  (0x marks a hex literal)
        printf("%x\n", 255);    // ff
        printf("%x\n", 12);     // c
        return 0;
    }
    
    תפעולי ביט פועלים על הביטים של שלמים
    תפעולי ביט פועלים על הביטים של שלמים
    13.2

    ריצות-לונג'ית אנקודינג

    English

    Run-length encoding (RLE) is a simple compression 压缩 method: replace each run 游程 of repeated characters with a count and the character. It is lossless 无损 — the original is fully recoverable.

    Common mistakes

    • & is bitwise AND and && is logical AND — do not confuse them.
    • A left shift << 1 doubles a value; a right shift >> 1 halves it.
    • Bit n has value 1 << n (C has no ** power operator); check a bit with (x >> n) & 1.
    עברית

    הצפנת אורך-רוץ (RLE) היא שיטת דחיסה פשוטה: החלף כל רצף של תווים חוזרים בספנית ובאות. השיטה היא ללא איבוד נתונים — המקורי ניתן לשחזור במלואו.

    #include <stdio.h>
    #include <string.h>
    
    int main(void) {
        char *s = "aaabbc";
        int n = strlen(s);
        for (int i = 0; i < n; ) {
            char c = s[i];
            int run = 0;
            while (i < n && s[i] == c) { run++; i++; }
            printf("%d%c", run, c);     // 3a2b1c
        }
        printf("\n");
        return 0;
    }
    

    שגיאות נפוצות

    • & הוא AND בינארי ו&& הוא AND לוגי — אל תבלבנו ביניהם.
    • הזזה שמאלה << 1 מכפילה בערך; הזזה ימינה >> 1 מחלקת בערך למחצה.
    • ביט n יש לו ערך 1 << n (C אין לה תפעול ** חזקה); בדוק ביט עם (x >> n) & 1.
  • 14 Preprocessor & qualifiers · ⁨מעבד קדם-שלב ומוגבלים⁩
    14.1

    Preprocessor, const, static, enum

    English

    The preprocessor 预处理器 runs before compiling. #define makes a macro 宏 — plain text replaced everywhere. const makes a constant 常量 that cannot change. static inside a function keeps a variable's value between calls. An enum (enumeration 枚举) names a set of integers starting at 0.

    Bigger programs split across files: declarations go in a header 头文件 file (mine.h), included with #include "mine.h" — quotes mean your own file, < > means the standard library. An include guard (#ifndef MINE_H / #define MINE_H / #endif) stops a header being included twice.

    Common mistakes

    • #define does plain text replacement with no type checking; wrap macro bodies and arguments in parentheses.
    • A const value cannot be changed after it is set.
    • A static local variable keeps its value between calls to the function.
    עברית

    ה-preprocessor פועל לפני ההרכבה. #define יוצר מקרו — החלפת טקסט פשוטה בכל מקום. const יוצר קבועה שלא ניתן לשנות. static בתוך פונקציה שומר על ערך משתנה בין קריאות. ערך enum (enum) מיימר קבוצה של שלמים התחילים ב0.

    #include <stdio.h>
    
    #define MAX 100                     // macro: text replaced before compiling
    
    enum Color { RED, GREEN, BLUE };    // named integers 0, 1, 2
    
    int next_id(void) {
        static int count = 0;           // keeps its value between calls
        count++;
        return count;
    }
    
    int main(void) {
        const double PI = 3.14;         // cannot be changed
        printf("%d %.2f\n", MAX, PI);            // 100 3.14
        printf("%d %d %d\n", RED, GREEN, BLUE);  // 0 1 2
        int a = next_id();
        int b = next_id();
        printf("%d %d\n", a, b);                 // 1 2
        return 0;
    }
    

    תוכניות גדולות מחולקות בין קבצים: הכרזות הולכות בקובץ כותרת (mine.h), שנכלל עם #include "mine.h" — סימני ציטוט מתכוונים לקובץ שלך, < > מתכוון לספריית הסטנדרט. מגן כליל (#ifndef MINE_H / #define MINE_H / #endif) מונע כתיבת כותרת פעמיים.

    שגיאות נפוצות

    • #define מבצע החלפת טקסט פשוטה ללא בדיקת סוגים; עטוף גופי מקרו וארגומנטים בסוגריים.
    • ערך const לא ניתן לשינוי לאחר שהוגדר.
    • משתנה מקומי static שומר על ערכו בין קריאות לפונקציה.
    #define, const, enum, וstatic שומרים על קוד ברור
    #define, const, enum, וstatic שומרים על קוד ברור

Log in or create account · ⁨היכנס או צור חשבון⁩

IGCSE, A-Level & AP