Pythonで学ぶC言語

PythonからC言語のプログラムを実行します。
###  1. 基本文法と入出力

| 項目 | 内容例 | Cコード例 |
|------|--------|-----------|
| `main()`の構造 | `int main(void)` | `printf("Hello, world!\n");` |
| `printf`と`scanf` | `%d %f %s %c` | `%d`で整数出力、`scanf`でユーザー入力 |
| エスケープ文字 | `\n`, `\t`, `\\` | `"line1\nline2\t\t\\path"` |

---

###  2. 演算子と式

| 演算子種類 | 使用例 | 備考 |
|------------|--------|------|
| 算術演算子 | `a + b` | `%`は剰余 |
| 代入演算子 | `x += 2` | 連続代入にも注意 |
| 比較演算子 | `x == y` | `!=`, `<`, `>=`など |
| 論理演算子 | `&&`, `||`, `!` | 短絡評価 |
| ビット演算 | `a & b`, `a << 2` | フラグ操作に活用 |
| 優先順位 | `a + b * c` | 括弧で明示化推奨 |

---

###  3. 条件分岐と制御構文

| 項目 | 使用例 |
|------|--------|
| `if`, `else` | 基本の分岐処理 |
| `switch-case` | `switch(choice)`で複数分岐 |
| 三項演算子 | `x = (a > b) ? a : b;` |
| 論理演算の代入ミス | `if (x = 0)` ←間違い、`==`にすべき |

---

###  4. 繰り返し構文（ループ処理）

| 構文 | 特徴 |
|------|------|
| `for` | インデックス変数付き |
| `while`, `do-while` | 条件評価の位置が異なる |
| 無限ループ | `while(1)` |
| `break`, `continue`, `goto` | ループ制御 |

---

### 5. 変数とデータ型

| 型 | 例 |
|----|----|
| `int`, `short`, `long`, `unsigned` | 整数の大きさと符号 |
| `float`, `double` | 小数表現と精度 |
| `char` | ASCIIコードとの関係 |
| `#define` vs `const` | 定数定義の違い |
| `enum` | 状態管理に便利 |
| 型変換 | `float x = (float)3 / 2;` |

---

###  6. 関数の定義と利用

| 項目 | 内容 |
|------|------|
| プロトタイプ宣言 | `int add(int a, int b);` |
| 値渡し vs アドレス渡し | `int*`, `&変数名` |
| `void`型関数 | 戻り値なし |
| 再帰関数 | `factorial(n)` |
| `.h`と`.c`の分離 | モジュール管理 |
| `static`, グローバル変数 | スコープと保持期間 |

---

###  7. 配列と文字列操作

| 内容 | 使用関数 |
|------|----------|
| 一次元・二次元配列 | `int a[3][4]` |
| `sizeof`で配列要素数取得 | `sizeof(arr) / sizeof(arr[0])` |
| 文字列終端`\0` | `"Hello\0"` |
| `<string.h>`関数 | `strcpy`, `strlen`, `strcmp`, `strstr`, `strchr`, `strncpy` |
| 安全な入力 | `fgets()`推奨 |
| 境界チェック | `for (i < sizeof(arr))` |

---

###  8. ポインタの基礎と応用

| 概念 | 例 |
|------|----|
| `&`, `*` | アドレス取得と間接参照 |
| `char *`で文字列処理 | `"Hello"`は配列と同じ |
| 配列の同一性 | `arr == &arr[0]` |
| 多重ポインタ | `int **ptr` |
| 関数へのポインタ渡し | `void modify(int *x)` |
| `NULL`安全チェック | `if (p != NULL)` |
| `const *`修飾 | 読み取り専用ポインタ |

---

###  9. 構造体と共用体

| 項目 | 内容 |
|------|------|
| `struct` | ユーザー定義型 |
| 配列・ポインタ | `struct Point *p = arr;` |
| `typedef struct` | 簡潔な記述 |
| `union` | メモリ共有型 |
| `enum + struct` | 状態管理の組み合わせ |
| 関数引数渡し | `void print(Point p)` |

---

###  10. メモリ管理と動的確保

| 操作 | 関数 |
|------|------|
| 動的確保 | `malloc`, `calloc`, `realloc` |
| 解放 | `free()` |
| `NULL`チェック | `if (ptr == NULL)` |
| 構造体の動的確保 | `malloc(sizeof(Person))` |
| メモリリーク防止 | 解放順に注意 |
| `valgrind`, `gdb` | メモリ監視とデバッグ（ローカルで） |

---

###  11. ファイル入出力

| 操作 | 関数 |
|------|------|
| オープン・クローズ | `fopen`, `fclose` |
| 読み書き | `fprintf`, `fscanf`, `fputs`, `fgets` |
| モード | `"r"`, `"w"`, `"a"`, `"rb"` |
| エラー処理 | `feof`, `ferror` |

---

###  12. ビット演算と低レベル操作

| 操作 | 例 |
|------|----|
| AND, OR, XOR | `a & b`, `a | b`, `a ^ b` |
| ビット反転 | `~a` |
| 左右シフト | `a << 2`, `a >> 1` |
| マスク | `x & 0x0F` |
| ビットフィールド構造体 | `struct Flags { unsigned a:1; ... };` |

---



```Python
import subprocess
# === ステップ1: C言語プログラムを作成 ===
c_code = r"""
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    if(argc != 3) {
        printf("Usage: %s num1 num2\n", argv[0]);
        return 1;
    }
    int a = atoi(argv[1]);
    int b = atoi(argv[2]);
    printf("%d\n", a + b);
    return 0;
}
"""

# Cファイルとして保存
with open("add.c", "w") as f:
    f.write(c_code)

# === ステップ2: gccでコンパイル ===
import subprocess

compile_result = subprocess.run(["gcc", "add.c", "-o", "add"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)

if compile_result.returncode != 0:
    print(" コンパイルエラー:")
    print(compile_result.stderr)
else:
    print(" Cプログラムのコンパイル成功")

# === ステップ3: PythonからCを実行 ===
a = 12
b = 30

try:
    result = subprocess.run(["./add", str(a), str(b)], stdout=subprocess.PIPE, text=True, check=True)
    print(f" Cの計算結果: {a} + {b} = {result.stdout.strip()}")
except subprocess.CalledProcessError as e:
    print(" 実行エラー:", e)

```



```Python
# プログラム名: run_basic_io_fixed.py
# 概要 / Description:
# C言語で入力値を固定した基本I/Oプログラム（basic_io_fixed.c）をPythonで自動的に書き込み・コンパイル・実行する

import subprocess

# --- C言語コード定義 / Define C code ---
c_code = r"""
// プログラム名: basic_io_fixed.c
// Program Name: basic_io_fixed.c

// 固定値によるCの基本構文デモ
// Basic I/O example with predefined values

#include <stdio.h>

int main(void) {
    // --- 変数を初期化 / Initialize variables ---
    int age = 23;
    float height = 175.5;
    char initial = 'S';
    char name[] = "Saito";

    // --- 結果表示 / Output Results ---
    printf("こんにちは！C言語へようこそ。\n");
    printf("Welcome to C programming!\n\n");

    printf("------ 結果 / Result ------\n");
    printf("名前 / Name: %s\n", name);
    printf("年齢 / Age: %d 歳\n", age);
    printf("身長 / Height: %.2f cm\n", height);
    printf("イニシャル / Initial: %c\n", initial);
    printf("ありがとう！ / Thank you!\n");

    // --- エスケープシーケンスの例 / Escape sequences ---
    printf("\n--- エスケープ例 / Escape Sequences ---\n");
    printf("タブ\t区切り / Tab\tdelimiter\n");
    printf("バックスラッシュ： \\\n");

    return 0;
}
"""

# --- ファイルに保存 / Save C code to file ---
with open("basic_io_fixed.c", "w") as f:
    f.write(c_code)

# --- コンパイル ---
compile_result = subprocess.run(["gcc", "basic_io_fixed.c", "-o", "basic_io_fixed"],
                                stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)

# --- 結果出力 ---
if compile_result.returncode != 0:
    print(" コンパイルエラー / Compilation Error:")
    print(compile_result.stderr)
else:
    print(" Cプログラムのコンパイル成功 / Compilation succeeded")

    # --- 実行 ---
    result = subprocess.run(["./basic_io_fixed"], stdout=subprocess.PIPE, text=True)
    print("\n 実行結果 / Program Output:\n")
    print(result.stdout)

```



```Python
# プログラム名: run_operator_and_control.py
# 概要: Cプログラム（演算子・条件分岐・ループ）の自動実行

import subprocess

# --- C言語コードを定義 ---
c_code = r"""
// プログラム名: operator_and_control_demo.c
// 演算子、条件分岐、ループ処理の基本例を網羅

#include <stdio.h>

int main(void) {
    int a = 10, b = 3;
    printf("\n--- 演算子と式 / Operators ---\n");
    printf("算術: a + b = %d\n", a + b);
    printf("代入: a += b → %d\n", (a += b));
    printf("比較: a > b → %d\n", a > b);
    printf("論理: (a > 5 && b < 10) → %d\n", (a > 5 && b < 10));
    printf("ビット: a & b = %d\n", a & b);
    printf("優先順位: a + b * 2 = %d\n", a + b * 2);
    printf("カッコ: (a + b) * 2 = %d\n", (a + b) * 2);

    printf("\n--- 条件分岐 / if, else if, switch ---\n");
    int score = 85;
    if (score >= 90) {
        printf("評価: 優\n");
    } else if (score >= 70) {
        printf("評価: 良\n");
    } else {
        printf("評価: 可\n");
    }

    int pass = (score >= 60) ? 1 : 0;
    printf("合格判定: %s\n", pass ? "合格" : "不合格");

    int day = 3;
    switch(day) {
        case 1: printf("月曜\n"); break;
        case 2: printf("火曜\n"); break;
        case 3: printf("水曜\n"); break;
        default: printf("その他\n");
    }

    printf("\n--- 繰り返し構文 / Loops ---\n");

    for (int i = 0; i < 3; i++) {
        printf("for: i = %d\n", i);
    }

    int i = 0;
    while (i < 3) {
        printf("while: i = %d\n", i);
        i++;
    }

    i = 0;
    do {
        printf("do-while: i = %d\n", i);
        i++;
    } while (i < 3);

    i = 0;
    while (1) {
        if (i >= 2) break;
        printf("無限ループ中: i = %d\n", i);
        i++;
    }

    for (int j = 0; j < 5; j++) {
        if (j == 2) continue;
        printf("continue例: j = %d\n", j);
    }

    printf("goto前\n");
    goto skip;
    printf("この行はスキップされる\n");
    skip:
    printf("goto後\n");

    return 0;
}
"""

# --- Cファイルとして保存 ---
with open("operator_and_control_demo.c", "w") as f:
    f.write(c_code)

# --- コンパイル ---
compile_result = subprocess.run(["gcc", "operator_and_control_demo.c", "-o", "operator_and_control_demo"],
                                stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)

if compile_result.returncode != 0:
    print("❌ コンパイルエラー:")
    print(compile_result.stderr)
else:
    print("✅ コンパイル成功")

    # --- 実行 ---
    result = subprocess.run(["./operator_and_control_demo"], stdout=subprocess.PIPE, text=True)
    print("\n🖥️ 実行結果:\n")
    print(result.stdout)

```



```Python
import subprocess

# --- Cコードをファイルとして保存 ---
c_code = r"""
// プログラム名: types_functions_arrays.c
// データ型、関数、配列・文字列操作の基本例

#include <stdio.h>
#include <string.h> // 文字列操作用

// --- 定数定義 / Constants ---
#define MAX_NAME 50           // マクロ定義 / Macro constant
const float PI = 3.14f;       // const定数 / Constant variable

// --- enum定義 / Enumeration ---
enum Weekday { MON, TUE, WED, THU, FRI };

// --- 関数プロトタイプ宣言 / Function Prototypes ---
void greet(void);
int add(int a, int b);
void swap(int *x, int *y);
int factorial(int n);

int main(void) {
    // --- データ型の例 / Data Types ---
    int i = 10;
    short s = 100;
    long l = 10000;
    unsigned int u = 255;

    float f = 3.14f;
    double d = 2.71828;

    char c = 'A';
    printf("文字: %c, ASCII: %d\\n", c, c);

    printf("int: %d, short: %d, long: %ld, unsigned: %u\\n", i, s, l, u);
    printf("float: %.2f, double: %.5f\\n", f, d);
    printf("定数 PI: %.2f\\n", PI);

    enum Weekday today = WED;
    printf("今日は: %d (0=MON)\\n", today);

    // --- 型変換 / Type Conversion ---
    double result = (double)i / 3;
    printf("明示的キャスト: (double)i / 3 = %.2f\\n", result);

    // --- 関数利用 / Using Functions ---
    printf("わはは！Cへようこそ！\\n");
    greet();
    printf("加算: add(3, 4) = %d\\n", add(3, 4));

    int a = 5, b = 10;
    swap(&a, &b);
    printf("スワップ後: a = %d, b = %d\\n", a, b);

    printf("階乗: factorial(5) = %d\\n", factorial(5));

    // --- 配列と文字列操作 / Arrays and Strings ---
    int arr[5] = {1, 2, 3, 4, 5};
    int n = sizeof(arr) / sizeof(arr[0]);
    printf("配列要素数: %d\\n", n);

    char name[MAX_NAME] = "C Language";
    printf("文字列: %s, 長さ: %lu\\n", name, strlen(name));

    char copy[MAX_NAME];
    strcpy(copy, name);
    printf("コピー: %s\\n", copy);

    char added[MAX_NAME] = "Hello, ";
    strcat(added, "World!");
    printf("連結: %s\\n", added);

    printf("比較: strcmp(\\\"abc\\\", \\\"abd\\\") = %d\\n", strcmp("abc", "abd"));
    printf("検索 strchr: %s\\n", strchr("banana", 'n'));
    printf("検索 strstr: %s\\n", strstr("hello world", "world"));

    // 安全な文字列入力
    char input[20];
    printf("名前を入力: ");
    fgets(input, sizeof(input), stdin);
    printf("入力: %s\\n", input);

    return 0;
}

// --- 挨拶関数 / Simple function ---
void greet(void) {
    printf("わはは！関数からこんにちは！\\n");
}

// --- 加算関数 / Function with return ---
int add(int a, int b) {
    return a + b;
}

// --- スワップ関数 / Pass-by-address ---
void swap(int *x, int *y) {
    int temp = *x;
    *x = *y;
    *y = temp;
}

// --- 再帰関数 / Recursive function ---
int factorial(int n) {
    if (n <= 1) return 1;
    return n * factorial(n - 1);
}
"""

# 保存先ファイル名
c_filename = "types_functions_arrays.c"
exe_filename = "types_functions_arrays"

# --- ファイル書き出し ---
with open(c_filename, "w") as f:
    f.write(c_code)

# --- コンパイル ---
compile = subprocess.run(["gcc", c_filename, "-o", exe_filename],
                         capture_output=True, text=True)

if compile.returncode != 0:
    print("❌ コンパイルエラー:")
    print(compile.stderr)
else:
    print("✅ コンパイル成功")

    # --- 実行（fgets入力に対応）---
    input_data = "Yamada\n"
    result = subprocess.run([f"./{exe_filename}"],
                            input=input_data,
                            capture_output=True,
                            text=True)

    print("\n🖥️ 実行結果:\n")
    print(result.stdout)

```



```Python
# ---  Step 1: Cコードをファイルに保存 ---
c_code = r'''
#include <stdio.h>
#include <string.h>

// 構造体の定義 / Struct definition
struct Person {
    char name[32];
    int age;
};

// ポインタを使ったスワップ関数 / Swap function using pointers
void swap(int *a, int *b) {
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

int main() {
    // ポインタの例 / Pointer example
    int x = 10, y = 20;
    swap(&x, &y);
    printf("After swap: x=%d, y=%d\n", x, y);

    // 構造体の例 / Struct example
    struct Person p;
    strcpy(p.name, "Tetsurou");
    p.age = 26;
    printf("Name: %s\n", p.name);
    printf("Age: %d\n", p.age);

    return 0;
}
'''

with open("pointer_struct_demo.c", "w") as f:
    f.write(c_code)

# ---  Step 2: コンパイル ---
!gcc -o pointer_struct_demo pointer_struct_demo.c

# ---  Step 3: PythonからCプログラムを呼び出して出力を受け取る ---
import subprocess

# 実行ファイルを呼び出し / Run the binary
process = subprocess.Popen(
    ['./pointer_struct_demo'],
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE
)

stdout, stderr = process.communicate()

# 結果を整形して表示 / Format and print output
print("=== C Output ===")
print(stdout.decode())

if stderr:
    print("=== C Error ===")
    print(stderr.decode())

```




```Python
# ---  Step 1: Cコード（動的メモリ管理の例）を保存 / Write C code to file ---
c_code = r'''
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 構造体の定義 / Define struct
typedef struct {
    char *name;
    int age;
} Person;

int main() {
    // --- mallocでint配列を動的確保 / Dynamically allocate array of int ---
    int *arr = (int *)malloc(3 * sizeof(int));
    if (arr == NULL) {
        fprintf(stderr, "Memory allocation failed for arr\n");
        return 1;
    }

    // 値の代入 / Assign values
    for (int i = 0; i < 3; i++) {
        arr[i] = (i + 1) * 10;
    }

    // 出力 / Print
    printf("Dynamic array: ");
    for (int i = 0; i < 3; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    // --- callocでゼロ初期化された配列を確保 / Use calloc for zero-initialized memory ---
    int *zero_arr = (int *)calloc(3, sizeof(int));
    if (zero_arr == NULL) {
        fprintf(stderr, "Calloc failed\n");
        free(arr);  // mallocしたメモリを解放 / Free arr
        return 1;
    }
    printf("Zero-initialized array: ");
    for (int i = 0; i < 3; i++) {
        printf("%d ", zero_arr[i]);
    }
    printf("\n");

    // --- 構造体の動的確保 / Allocate struct dynamically ---
    Person *p = (Person *)malloc(sizeof(Person));
    if (p == NULL) {
        fprintf(stderr, "Person malloc failed\n");
        free(arr);
        free(zero_arr);
        return 1;
    }

    // nameフィールドのメモリ確保 / Allocate memory for name
    p->name = (char *)malloc(32 * sizeof(char));
    if (p->name == NULL) {
        fprintf(stderr, "Name malloc failed\n");
        free(p); free(arr); free(zero_arr);
        return 1;
    }

    strcpy(p->name, "Tetsurou");
    p->age = 26;
    printf("Person: name = %s, age = %d\n", p->name, p->age);

    // --- メモリ解放 / Free memory ---
    free(p->name);
    free(p);
    free(arr);
    free(zero_arr);

    return 0;
}
'''

with open("mem_manage_demo.c", "w") as f:
    f.write(c_code)

# ---  Step 2: コンパイル / Compile ---
!gcc -o mem_manage_demo mem_manage_demo.c

# ---  Step 3: Pythonで実行 / Execute via Python ---
import subprocess

process = subprocess.Popen(
    ['./mem_manage_demo'],
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE
)

stdout, stderr = process.communicate()

print("=== C Output ===")
print(stdout.decode())

if stderr:
    print("=== C Error ===")
    print(stderr.decode())

```