課題18: 標準ライブラリ

マンダトリー要件 (80点)

Part 1: ファイル処理ユーティリティ (20点)

ファイル名: part1_file_utils.zig

const std = @import("std");

// TODO: 以下の関数を実装してください

// 1. ファイルの内容を読み込む
pub fn readFileContent(allocator: std.mem.Allocator, path: []const u8) ![]u8 {
    // ここに実装
}

// 2. ファイルに書き込む
pub fn writeFileContent(path: []const u8, content: []const u8) !void {
    // ここに実装
}

// 3. ファイルをコピー
pub fn copyFile(src_path: []const u8, dst_path: []const u8) !void {
    // ここに実装
}

// 4. ディレクトリ内のファイル数をカウント
pub fn countFiles(dir_path: []const u8) !usize {
    // ここに実装
}

// 5. 指定された拡張子のファイルを検索
pub fn findFilesByExtension(
    allocator: std.mem.Allocator,
    dir_path: []const u8,
    extension: []const u8,
) ![][]const u8 {
    // ここに実装
}

pub fn main() !void {
    const allocator = std.heap.page_allocator;

    // テスト
    try writeFileContent("test.txt", "Hello, Zig!");
    
    const content = try readFileContent(allocator, "test.txt");
    defer allocator.free(content);
    std.debug.print("Content: {s}\n", .{content});

    try copyFile("test.txt", "test_copy.txt");

    const count = try countFiles(".");
    std.debug.print("File count: {}\n", .{count});
}

Part 2: JSON設定マネージャー (20点)

ファイル名: part2_config_manager.zig

const std = @import("std");

pub const AppConfig = struct {
    name: []const u8,
    version: []const u8,
    server: ServerConfig,
    features: []const []const u8,

    pub const ServerConfig = struct {
        host: []const u8,
        port: u16,
        ssl: bool,
    };
};

// TODO: 以下の関数を実装してください

// 1. JSON設定ファイルを読み込む
pub fn loadConfig(allocator: std.mem.Allocator, path: []const u8) !AppConfig {
    // ここに実装
}

// 2. 設定をJSON形式で保存
pub fn saveConfig(config: AppConfig, path: []const u8) !void {
    // ここに実装
}

// 3. 設定の検証
pub fn validateConfig(config: AppConfig) bool {
    // ここに実装
    // ポート番号が有効範囲か、名前が空でないかなど
}

pub fn main() !void {
    const allocator = std.heap.page_allocator;

    const config = AppConfig{
        .name = "MyApp",
        .version = "1.0.0",
        .server = .{
            .host = "localhost",
            .port = 8080,
            .ssl = false,
        },
        .features = &[_][]const u8{ "api", "web", "logging" },
    };

    try saveConfig(config, "config.json");

    const loaded = try loadConfig(allocator, "config.json");
    std.debug.print("Loaded: {s} v{s}\n", .{ loaded.name, loaded.version });

    const valid = validateConfig(loaded);
    std.debug.print("Valid: {}\n", .{valid});
}

Part 3: ロギングシステム (20点)

ファイル名: part3_logging.zig

const std = @import("std");

pub const LogLevel = enum {
    debug,
    info,
    warn,
    err,
};

pub const Logger = struct {
    level: LogLevel,
    file: ?std.fs.File,
    allocator: std.mem.Allocator,

    // TODO: 以下のメソッドを実装してください

    pub fn init(allocator: std.mem.Allocator, level: LogLevel, file_path: ?[]const u8) !Logger {
        // ここに実装
    }

    pub fn deinit(self: *Logger) void {
        // ここに実装
    }

    pub fn log(self: *Logger, level: LogLevel, message: []const u8) !void {
        // ここに実装
        // タイムスタンプ、レベル、メッセージを出力
    }

    pub fn logFmt(
        self: *Logger,
        level: LogLevel,
        comptime format: []const u8,
        args: anytype,
    ) !void {
        // ここに実装
    }
};

pub fn main() !void {
    const allocator = std.heap.page_allocator;

    var logger = try Logger.init(allocator, .debug, "app.log");
    defer logger.deinit();

    try logger.log(.info, "Application started");
    try logger.logFmt(.debug, "Processing {} items", .{10});
    try logger.log(.warn, "Resource usage high");
    try logger.log(.err, "Failed to connect");
}

Part 4: テキスト処理ツール (20点)

ファイル名: part4_text_processor.zig

const std = @import("std");

// TODO: 以下の関数を実装してください

// 1. テキストファイルの行数をカウント
pub fn countLines(path: []const u8) !usize {
    // ここに実装
}

// 2. テキスト内の単語数をカウント
pub fn countWords(text: []const u8) usize {
    // ここに実装
}

// 3. 指定されたパターンを検索
pub fn searchPattern(
    allocator: std.mem.Allocator,
    text: []const u8,
    pattern: []const u8,
) ![]usize {
    // ここに実装
    // パターンが見つかった位置のインデックスを返す
}

// 4. テキストを指定された幅で折り返す
pub fn wrapText(
    allocator: std.mem.Allocator,
    text: []const u8,
    width: usize,
) ![]u8 {
    // ここに実装
}

// 5. CSVファイルをパース
pub fn parseCSV(
    allocator: std.mem.Allocator,
    csv_text: []const u8,
) ![][]const []const u8 {
    // ここに実装
}

pub fn main() !void {
    const allocator = std.heap.page_allocator;

    const text = "Hello World Hello Zig";
    
    const word_count = countWords(text);
    std.debug.print("Words: {}\n", .{word_count});

    const positions = try searchPattern(allocator, text, "Hello");
    defer allocator.free(positions);
    
    std.debug.print("Pattern found at: ", .{});
    for (positions) |pos| {
        std.debug.print("{} ", .{pos});
    }
    std.debug.print("\n", .{});
}

ボーナス課題 (20点)

Bonus 1: HTTPサーバー (10点)

ファイル名: bonus1_http_server.zig

const std = @import("std");

pub const HttpServer = struct {
    allocator: std.mem.Allocator,
    port: u16,

    pub fn init(allocator: std.mem.Allocator, port: u16) HttpServer {
        return HttpServer{
            .allocator = allocator,
            .port = port,
        };
    }

    pub fn start(self: *HttpServer) !void {
        // TODO: 実装
        // TCPソケットを作成してリクエストを処理
    }

    fn handleRequest(self: *HttpServer, stream: std.net.Stream) !void {
        // TODO: 実装
        _ = self;
        _ = stream;
    }
};

pub fn main() !void {
    const allocator = std.heap.page_allocator;
    var server = HttpServer.init(allocator, 8080);
    
    std.log.info("Starting server on port {}\n", .{server.port});
    try server.start();
}

Bonus 2: マークダウンパーサー (10点)

ファイル名: bonus2_markdown_parser.zig

const std = @import("std");

pub const MarkdownNode = union(enum) {
    heading: struct {
        level: u8,
        text: []const u8,
    },
    paragraph: []const u8,
    code_block: struct {
        language: ?[]const u8,
        code: []const u8,
    },
    list_item: []const u8,
};

pub fn parseMarkdown(
    allocator: std.mem.Allocator,
    markdown: []const u8,
) ![]MarkdownNode {
    // TODO: 実装
    // マークダウンをパースしてノードの配列を返す
    _ = allocator;
    _ = markdown;
    return &[_]MarkdownNode{};
}

pub fn markdownToHTML(
    allocator: std.mem.Allocator,
    markdown: []const u8,
) ![]u8 {
    // TODO: 実装
    _ = allocator;
    _ = markdown;
    return "";
}

pub fn main() !void {
    const allocator = std.heap.page_allocator;

    const md =
        \\# Hello
        \\
        \\This is a paragraph.
        \\
        \\
zig \\const x = 42; \\
    ;

    const html = try markdownToHTML(allocator, md);
    defer allocator.free(html);

    std.debug.print("HTML:\n{s}\n", .{html});
}

評価基準

項目 配点
Part 1: ファイル処理ユーティリティ 20点
Part 2: JSON設定マネージャー 20点
Part 3: ロギングシステム 20点
Part 4: テキスト処理ツール 20点
**マンダトリー合計** **80点**
Bonus 1: HTTPサーバー 10点
Bonus 2: マークダウンパーサー 10点
**ボーナス合計** **20点**

提出方法

exercise18/
├── part1_file_utils.zig
├── part2_config_manager.zig
├── part3_logging.zig
├── part4_text_processor.zig
├── bonus1_http_server.zig
└── bonus2_markdown_parser.zig

参考資料

  • Zig Standard Library: https://ziglang.org/documentation/master/std/