Skip to content · ⁨コンテンツへスキップ⁩
Subjects · ⁨科目⁩
  • 1 C basics · ⁨C 基礎⁩
    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".

    日本語

    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".

    #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
    Every C program runs from main after including headers
    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 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 余数.

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

    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:

    #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.
    日本語

    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.

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

    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.
  • 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 は整数値に基づいて1つの case を選びます。各 case には break が必要で、なければCは次のケースへと"Fall through"します。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;が必要であり、指定しない場合次のケースへ fall through する。
    • 条件式中では0が false、それ以外の非ゼロ値は true とみなされる。
  • 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.

    日本語

    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.

    #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 checks a condition; for counts with a step
    while checks a condition; for counts with a step
    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.

    日本語

    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.

    #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.
    日本語

    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.

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

    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.
  • 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.

    日本語

    関数はパラメータ(入力)を受け取り、戻り値を返します。戻り型の記述が先に来ます(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;
    }
    

    ** 一般的なミス **

    • 定義前に使用される関数には、 main の上にプロトタイプ宣言が必要です。
    • 引数は BY VALUE で渡される。関数内部での変更はポインタを渡さなければ呼び出し側には影響しない。
    • 関数内部で宣言された変数はその関数に限定されるローカル変数である。
  • 5 Arrays · ⁨配列⁩
    5.1

    1-D arrays

    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]).

    日本語

    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]).

    #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;
    }
    
    Array slots are indexed from 0
    Array slots are indexed from 0
    5.2

    Array algorithms

    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.

    日本語

    Traverse 遍历 an array with a for loop to find a max, a total, or a count. Always loop from 0 up to 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-D arrays

    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.
    日本語

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

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

    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.
  • 6 Pointers · ⁨ポインタ⁩
    6.1

    &, * and pass-by-pointer

    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.
    日本語

    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).

    A pointer stores an address; dereferencing it follows the arrow to the value
    A pointer stores an address; dereferencing it follows the arrow to the value
    #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;
    }
    

    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:

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

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

    #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 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.
  • 7 Strings · ⁨文字列⁩
    7.1

    Char 配列と nullTerminator

    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を、1文字だけ出力するには%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の文字列は隠れたnullTerminatorで終わるchar配列です
    Cの文字列は隠れたnullTerminatorで終わる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) 長さ(terminator を含まない)
    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としてはいけません。
    • 目的の配列には結果のためのスペース加上 terminator のスペースが必要である。

    ** 一般的なミス **

    • C文字列には \0 終端マーカーのために追加の1バイトが必要です: 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;
    }
    

    ** 一般的なミス **

    • structの値には . を、structのポインタには -> を使用します。
    • typedef を使うと宣言時にstruct という語を省略できる。使わない場合はstruct Point p; を書く。
    • 一つのstruct をもう一つに代入すると、すべてのフィールドがコピーされる。
    . はstruct 値用;-> はstruct ポインタ用
    . はstruct 値用;-> はstruct ポインタ用
  • 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 が必要であり、否则 memory leak Occur。これらは<stdlib.h> にある。

    ローカル変数はスタックに、mallocで確保したメモリはfreeするまでヒープ上に存在します
    ローカル変数はスタックに、mallocで確保したメモリは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) は malloc と同様に配列を割り当てるとともに、すべての要素をゼロで初期化します。

    ** 一般的なミス **

    • 各 malloc には対応する free が必要です;freeを忘れるとメモリリークが発生します。
    • free 後のメモリ使用("use-after-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 でノードを1つずつ拡張します。完了したら必ず free するまで全ノードを確認してください。

    リンクリスト:各ノードは値と次のノードへのポインタを持ち、最後はNULLで終わります
    リンクリスト:各ノードは値と次のノードへのポインタを持ち、最後は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(後入れ先出し)で、pushとpopは同じ端で行います。キューは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 ポインタを失ってはいけません。そうするとリスト全体にアクセスできなくなります。
    • 完了したら、リストをトレースしながらすべてのノードをfreeしてください。
    • popする前に、リストが空か(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.
    日本語

    再帰は関数が自身を呼び出すことです。停止するための基本ケース(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;
    }
    

    ** 一般的なミス **

    • 二分探索には並べ替え済み配列が必要で、再帰には基本ケースが必要です。
    • 各再帰呼び出しは基本ケースに近づかなければならず、そうでないとスタックオーバーフローになります。
    • バブルソートと挿入ソートは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には例外処理がありません。代わりに関数は戻り値で失敗を通知します。慣例として 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 のファイルをcloseしてください。
    • main から非ゼロのコードを返して、呼び出し側にエラーを通知してください。
  • 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:

    日本語

    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).

    #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) writes binary compactly: one hex digit is exactly four bits. Write hex literals with 0x; print with %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 work on the bits of integers
    Bitwise operators work on the bits of 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) 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.

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

    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.
  • 14 Preprocessor & qualifiers · ⁨プリプロセッサ & 修飾子⁩
    14.1

    プリプロセッサ、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.
    日本語

    プリプロセッサはコンパイル前に実行されます。#define はマクロを作成し、あらゆる場所で純粋なテキストが置換されます。const は変更できない定数を定義します。関数内の static は、関数呼び出し間の値を保持します。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" でincludeします。引用符は自分のファイル、< > は標準ライブラリを意味します。インクルードガード(#ifndef MINE_H / #define MINE_H / #endif)はヘッダーファイルが重複してincludeされるのを防ぎます。

    ** 一般的なミス **

    • #define は型チェックなしの純粋なテキスト置換を行うため、マクロ本体と引数を括弧で囲む必要があります。
    • const の値は設定後に変更できません。
    • static ローカル変数は関数呼び出し間で値を保持します。
    #define, const, enum, staticはコードを明確に保ちます
    #define, const, enum, staticはコードを明確に保ちます

Log in or create account · ⁨ログインまたはアカウント作成⁩

IGCSE, A-Level & AP