Skip to content · ⁨ข้ามไปยังเนื้อหา⁩
Subjects · ⁨รายวิชา⁩
  • 1 C basics
    1.1

    main, printf & functions

    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> ดึง header เข้ามาเพื่อให้คุณใช้ 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;
    }
    
    Every C program runs from main after including headers
    โปรแกรม C ทุกตัวจะทำงานจาก main หลังจากรวม header เข้าไป
    1.2

    Variables, types & arithmetic

    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 ใช้ format specifier — %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;
    }
    

    ข้อผิดพลาดที่พบบ่อย

    Specifier Type Example output
    %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) อ่านข้อมูลจากคีย์บอร์ดโดยใช้ specifiers เหมือนกัน (โปรดสังเกต &). พี่น้องของ它 sscanf วิเคราะห์ค่าออกจาก string, ดังนั้นจึงทำงานได้ทุกที่:

    #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

    Comments & style

    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.
    ไทย

    Comment คือหมายเหตุสำหรับมนุษย์; compiler จะ.Record它. ใช้ // สำหรับหนึ่งบรรทัดและ /* ... */ สำหรับบล็อก. การจัดย่อหน้าที่ดีและชื่อที่ชัดเจนทำให้โค้ดอ่านง่าย

    #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 ไม่มีชนิดข้อมูล boolean ที่แท้จริงโดยมาตรฐาน: 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 จะ "ตกหล่น" (fall through) ไปยัง case ถัดไป 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

    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

    Accumulation

    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

    ลูปซ้อนและรูปแบบ

    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 ครั้ง; จุดกึ่งคั่นต่อท้าย for (...) ทำให้เกิดลูปว่างเปล่า
    • while ที่มีเงื่อนไขไม่เป็นเท็จตลอดกาลจะทำให้วนลูปไม่สิ้นสุด
    • ประกาศตัวนับ (int i) ก่อนหรือภายในหัวของ for
  • 4 Functions · ⁨ฟังก์ชัน⁩
    4.1

    พารามิเตอร์และค่าที่ส่งกลับ

    English

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

    ไทย

    ฟังก์ชันรับพารามิเตอร์ (อินพุต) และส่งค่ากลับออกมา返回值 type มาไว้ก่อน (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 อ่านจากบนลงล่าง ดังนั้นฟังก์ชันต้องถูกรู้จักก่อนจะถูกเรียกใช้ โปรโตไทป์ — บรรทัดหัวพร้อม ; — ประกาศมันล่วงหน้าเพื่อให้คุณสามารถวาง 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;
    }
    

    ข้อผิดพลาดที่พบบ่อย

    • ฟังก์ชันที่ถูกเรียกใช้ก่อนการนิยามจำเป็นต้องมี prototype ด้านบน main
    • อาร์กิวเมนต์ถูกส่ง BY VALUE — การเปลี่ยนแปลงภายในฟังก์ชันจะไม่ส่งผลต่อผู้เรียกใช้เว้นแต่คุณจะส่งพอยน์เตอร์
    • ตัวแปรที่ประกาศภายในฟังก์ชันจะเป็นแบบท้องถิ่นของมัน
  • 5 Arrays · ⁨Arreglo⁩
    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 เป็นพฤติกรรมที่ไม่กำหนด
    • ดัชนีที่ใช้ได้วิ่งจาก 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 คลายพอยน์เตอร์ — อ่านหรือเขียนค่าที่เก็บไว้นั้น การส่งพอยน์เตอร์ช่วยให้ฟังก์ชันเปลี่ยนตัวแปรของผู้เรียกใช้ได้ (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 · ⁨สตริง (Strings)⁩
    7.1

    อาเรย์ char และตัวลงท้าย null

    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 ทุกสตริงลงท้ายด้วยตัวลงท้าย null ที่ซ่อนอยู่ '\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 ที่ลงท้ายด้วยตัวลงท้าย null ที่ซ่อนอยู่
    สตริง C คืออาเรย์ char ที่ลงท้ายด้วยตัวลงท้าย null ที่ซ่อนอยู่

    คุณสามารถ traverses สตริงด้วยการวนลูปจนกว่าจะเจอ '\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 ต้องการ字节เพิ่มหนึ่ง byte สำหรับตัวลงท้าย \0: คำที่มี 5 ตัวอักษรต้องใช้ char[6]
    • คัดลอกและเปรียบเทียบสตริงด้วย strcpy / strcmp ไม่ใช่ = / ==
    • การลืมตัวลงท้าย \0 ทำให้ printf("%s", ...) วิ่งเกินข้อความ
  • 8 Structs
    8.1

    struct, typedef, . vs ->

    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 ให้ชื่อสั้นแก่ struct เพื่อให้คุณสามารถเขียน Dog แทนที่จะเป็น struct Dog ใช้ . กับค่า struct แต่ใช้ -> กับพอยน์เตอร์ไปยัง struct

    #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;
    }
    

    ข้อผิดพลาดที่พบบ่อย

    • ใช้ . กับ Value ของ struct และ -> กับ Pointer ของ struct
    • typedef ช่วยให้คุณละคำ struct ได้ในการประกาศ; หากไม่มีให้เขียน struct Point p;
    • การ assign struct หนึ่งไปยังอีก struct หนึ่งจะคัดลอกฟิลด์ทั้งหมดของมัน
    . สำหรับค่า struct; -> สำหรับพอยน์เตอร์ไปยัง structs
    . สำหรับค่า struct; -> สำหรับพอยน์เตอร์ไปยัง structs
  • 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 allocate หน่วยความจำบน heap运行时 return a pointer to it. realloc ปรับขนาดบล็อกนั้น; free คืนมันให้ Every malloc ต้องมี matching free มิฉะนั้นจะได้ memory leak. เหล่านี้อยู่ใน <stdlib.h>.

    ตัวแปรท้องถิ่น resides on the stack; ความจำจาก malloc resides on the heap จนกว่าคุณจะ free()
    ตัวแปรท้องถิ่น resides on the stack; ความจำจาก malloc resides on the heap จนกว่าคุณจะ free()
    #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) จัดสรร array เหมือน malloc AND เติมด้วยเลขศูนย์ทั้งหมด.

    ข้อผิดพลาดที่พบบ่อย

    • ทุกครั้งที่มี malloc จำเป็นต้องมี free ที่จับคู่กัน; ลืม free() จะเกิด memory leak.
    • การใช้หน่วยความจำหลังจาก free (เรียกว่า "use-after-free") เป็นข้อผิดพลาดร้ายแรง
    • ตรวจสอบให้แน่ใจว่า malloc ไม่ได้ return NULL ก่อนที่จะใช้ความจำนั้น.
  • 10 Data structures
    10.1

    Linked lists

    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.

    ไทย

    ลิงก์edList คือชุดของโหนดที่เรียงต่อกัน Each โหนดมีค่าและพอยเตอร์ไปยังโหนด next ตัวสุดท้ายชี้ไปที่ NULL ต่างจากอาร์เรย์ที่มันขยายได้ทีละโหนดด้วย malloc ต้อง free ทุกโหนดเมื่อใช้งานเสร็จ

    Linked list: แต่ละ node เก็บค่าและ pointer ไปยัง node ถัดไป สิ้นสุดที่ NULL
    Linked list: แต่ละ node เก็บค่าและ pointer ไปยัง node ถัดไป สิ้นสุดที่ 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

    Stacks & queues

    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.
    ไทย

    Stack เป็น LIFO (last in, first out): push และ pop ที่ปลายเดียวกัน Queue เป็น FIFO (first in, first out): เพิ่มที่ท้าย ลบที่หน้า ทั้งสองสร้างง่ายบน array โดยใช้ index variables.

    #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;
    }
    

    ข้อผิดพลาดที่พบบ่อย

    • ใน linked list ห้ามปล่อยให้ head指针หาย หรือทั้งรายการจะเข้าถึงไม่ได้.
    • Free() ทุก node เมื่อใช้งานเสร็จ โดยเดิน遍历 list ก่อนที่จะ unlink.
    • ตรวจสอบว่า list ว่างหรือไม่ (head เป็น NULL) ก่อนที่จะ pop.
  • 11 Searching, sorting & recursion
    11.1

    Linear & binary search

    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.

    ไทย

    Linear search ตรวจสอบแต่ละ element ตามลำดับ — ใช้ได้กับ array ใดก็ได้ Binary search เร็วกว่ามากแต่ต้องต้องการ array ที่เรียงลำดับแล้ว: ตรวจสอบกลางและตัดครึ่งออกทุกขั้นตอน ทั้งสอง return index หรือ -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
    }
    
    Linear scan ทั้งหมด; binary ลดเหลือครึ่งหนึ่งของช่วงที่เรียงแล้ว
    Linear scan ทั้งหมด; binary ลดเหลือครึ่งหนึ่งของช่วงที่เรียงแล้ว
    11.2

    Sorting

    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.

    ไทย

    Bubble sort เปรียบเทียบเพื่อนบ้านซ้ำๆ และสลับ pair ที่ผิดลำดับ ทุกรอบ的大型ที่สุดจะ "bubble" ไปที่ท้าย.

    #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.
    ไทย

    Recursion คือฟังก์ชันที่เรียกตัวเอง มี base case เพื่อหยุด และมี recursive call ที่ก้าวเข้าหา base case ถ้าไม่มี base case จะไม่สิ้นสุด.

    #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;
    }
    

    ข้อผิดพลาดที่พบบ่อย

    • Binary search ต้องการ sorted array; recursion ต้องการ base case.
    • ทุก recursive call ต้องเคลื่อนใกล้ base case ขึ้น มิฉะนั้น stack จะ overflow.
    • Bubble และ insertion sort เป็น O(n²) — ดีสำหรับการเรียนรู้ แต่ช้าเมื่อข้อมูล量大.
  • 12 Files & errors
    12.1

    Text files

    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

    Error handling with return codes

    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. แทนที่จะใช้ return code เพื่อแสดงว่าล้มเหลว — ตามธรรมเนียม 0 หมายถึงสำเร็จ และค่าที่ไม่ใช่ศูนย์หมายถึง error. Caller ตรวจสอบโค้ดก่อนเชื่อถือผลลัพธ์. (fopen遵循相同的理念:它返回NULL when it fails.)

    #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 ไฟล์ทุกเมื่อใช้งานเสร็จ
    • Return non-zero code จาก main เพื่อ signal error ให้ caller.
  • 13 Bits & data
    13.1

    Bits, binary & bitwise operators

    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:

    ไทย

    Bit คือ 0 หรือ 1 เดี่ยว; numbers เก็บใน binary. Bitwise operators ทำงานกับ bits โดยตรง: & AND, | OR, ^ XOR, << shift left (×2 ทุกขั้น), >> shift right (÷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;
    }
    

    Hexadecimal (base 16) เขียน binary แบบกระชับ: หนึ่ง hex digit เท่ากับ 4 bits พอดี. เขียน hex literals ด้วย 0x; print ด้วย %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;
    }
    
    Bitwise operators ทำงานกับ bits ของ integers
    Bitwise operators ทำงานกับ bits ของ integers
    13.2

    Run-length encoding

    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.
    ไทย

    Run-length encoding (RLE) เป็นวิธี compression แบบง่าย: แทนที่ run ของ characters ซ้ำๆ ด้วย count และ character. It is lossless — สามารถกู้คืนต้นฉบับได้เต็มที่.

    #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;
    }
    

    ข้อผิดพลาดที่พบบ่อย

    • & คือ bitwise AND และ && คือ logical AND —อย่าสับสนกัน
    • การเลื่อนซ้าย << 1 ทำให้ค่าเป็นสองเท่า; การเลื่อนขวา >> 1 ทำให้ค่าเป็นครึ่งหนึ่ง.
    • Bit n มีค่า 1 << n (C ไม่มี ** power operator); ตรวจสอบ bit ด้วย (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 ทำงานก่อน compile. #define สร้าง macro — ข้อความธรรมดาที่ถูกแทนที่ทุกที่. const สร้าง constant ที่เปลี่ยนไม่ได้. static ภายในฟังก์ชันคงค่าตัวแปรไว้ระหว่าง calls. An enum (enumeration) ตั้งชื่อชุดของ integers เริ่มที่ 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;
    }
    

    โปรแกรมใหญ่แบ่งข้ามไฟล์: declarations อยู่ใน header file (mine.h), include ด้วย #include "mine.h" —เครื่องหมายคำพูดหมายถึงไฟล์ของคุณเอง, < > หมายถึง standard library. Include guard (#ifndef MINE_H / #define MINE_H / #endif) ป้องกันการ include header ซ้ำ.

    ข้อผิดพลาดที่พบบ่อย

    • #define ทำ plain text replacement โดยไม่มี type checking; ห่อหุ้ม macro bodies และ arguments ไว้ในวงเล็บ.
    • ค่าของ const ไม่สามารถเปลี่ยนแปลงได้หลังจากตั้ง.
    • ตัวแปร local ของ static คงค่าไว้ระหว่าง calls ของฟังก์ชัน.
    #define, const, enum, และ static ทำให้โค้ดชัดเจน
    #define, const, enum, และ static ทำให้โค้ดชัดเจน

Log in or create account · ⁨เข้าสู่ระบบหรือสร้างบัญชี⁩

IGCSE, A-Level & AP