Menu
Coddy logo textTech

イベントシステム

CoddyのCジャーニー「Object Oriented Programming」セクションの一部 — レッスン 61/61。

challenge icon

チャレンジ

簡単

通知システムを構築しましょう。これは、複数のハンドラーがイベントを購読(サブスクライブ)し、イベントが発生したときに応答するイベント駆動型アーキテクチャです。このパターンは、リアクティブプログラミングやGUIフレームワークの根幹をなすものです。

コードは以下の3つのファイルに分けて構成します:

  • event.h: const char* のメッセージを受け取る Handler 関数ポインタ型を定義します。最大5つのハンドラーを保持する配列と、登録されたハンドラーの数を保持する Event 構造体を作成します。イベントの初期化、ハンドラーの購読、およびすべての購読者に通知するためにイベントを発生させる関数の宣言を行います。
  • event.c: イベントシステムを実装します:
    • init_event — Event ポインタを受け取り、ハンドラーのカウントを 0 に設定します。
    • subscribe — Event ポインタと Handler を受け取り、空きがある場合(カウントが5未満)は配列にハンドラーを追加し、カウントをインクリメントします。
    • fire — Event ポインタとメッセージ文字列を受け取り、登録された各ハンドラーを購読された順にそのメッセージで呼び出します。
  • main.c: イベントに対して独自の方法で応答する3つの異なるハンドラー関数を作成します:
    • logger[LOG] に続いてメッセージを出力します。
    • alert[ALERT] に続いてメッセージを出力します。
    • counter — 静的変数(static variable)を使用して呼び出された回数をカウントし、[COUNT] X(Xは現在のカウント)を出力します。
    購読するハンドラーの数を示す整数(1、2、または3)を読み取ります。その数だけ順番にハンドラーを購読します:最初に logger、次に alert(2以上の場合)、最後に counter(3の場合)。メッセージ文字列を読み取り、そのメッセージでイベントを発生(fire)させます。

プログラムは以下を受け取ります:

  1. 購読するハンドラーの数(1、2、または3)
  2. ブロードキャストするメッセージ

入力が 3System started の場合の出力例:

[LOG] System started
[ALERT] System started
[COUNT] 1

入力が 2Warning detected の場合の出力例:

[LOG] Warning detected
[ALERT] Warning detected

入力が 1Hello の場合の出力例:

[LOG] Hello

これは関数ポインタを通じたポリモーフィズムを示しています。同じ fire 呼び出しが、どのハンドラーが購読されているかに応じて、まったく異なる動作をトリガーします。各ハンドラーが同じイベントに対して独自の方法で応答しており、イベント駆動設計の疎結合な性質が示されています。

自分で試してみよう

#include <stdio.h>
#include <string.h>
#include "event.h"

// TODO: logger ハンドラーを実装する
// "[LOG] " に続いてメッセージを出力する
void logger(const char* message) {
    // TODO: 実装する
}

// TODO: alert ハンドラーを実装する
// "[ALERT] " に続いてメッセージを出力する
void alert(const char* message) {
    // TODO: 実装する
}

// TODO: counter ハンドラーを実装する
// static 変数を使用して呼び出し回数をカウントする
// "[COUNT] X" を出力する(X は現在のカウント)
void counter(const char* message) {
    // TODO: static 変数を使用して実装する
}

int main() {
    // 購読するハンドラーの数を読み取る
    int num_handlers;
    scanf("%d", &num_handlers);
    getchar(); // 改行文字を消費する
    
    // メッセージを読み取る
    char message[256];
    fgets(message, sizeof(message), stdin);
    message[strcspn(message, "\n")] = '\0'; // 改行文字を削除する
    
    // TODO: Event を作成して初期化する
    
    // TODO: num_handlers に基づいてハンドラーを購読する
    // ハンドラー1つ: logger
    // ハンドラー2つ: logger, alert
    // ハンドラー3つ: logger, alert, counter
    
    // TODO: メッセージと共にイベントを発生させる
    
    return 0;
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

Object Oriented Programmingのすべてのレッスン