0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonで学ぶC言語

Last updated at Posted at 2025-04-16

PythonからC言語のプログラムを実行します。

1. 基本文法と入出力

項目 内容例 Cコード例
main()の構造 int main(void) printf("Hello, world!\n");
printfscanf %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
ビット反転 ~a
左右シフト a << 2, a >> 1
マスク x & 0x0F
ビットフィールド構造体 struct Flags { unsigned a:1; ... };

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)

# プログラム名: 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)

# プログラム名: 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)

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)

# ---  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())

# ---  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())

0
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?