🐷

C 言語で Command パターン

2021/02/01に公開

queue で Command パターン

queue で実装してみる。queue というかリングバッファというか。

#include <stdio.h>
#include <stdarg.h>

#define QUEUE_MAX 4
typedef void (*command)(int argc, ...);
command queue[QUEUE_MAX];

int start_index;
int end_index;

void enqueue(command cmd)
{
  if(queue[end_index] != NULL)
  {
    printf("queue is full\n");
    return;
  }

  queue[end_index] = cmd;
  end_index++;
  if(end_index >= QUEUE_MAX)
  {
    end_index = 0; 
  }
}

command dequeue(void)
{
  command cmd;
  cmd = queue[start_index];
  queue[start_index] = NULL;
  start_index++;
  if(start_index >= QUEUE_MAX)
  {
    start_index = 0; 
  }
  return cmd;
}

void initialize(void)
{
  int i;
  for(i = 0; i < QUEUE_MAX; i++)
  {
    queue[i] = NULL;
  }
  start_index = 0;
  end_index = 0;
}

void command1(int argc, ...)
{
  int i;
  va_list args;
  va_start(args, argc);

  printf("command1\n");

  for(i = 0; i < argc; i++)
  {
    int n;
    n = va_arg(args, int);
    printf("%d\n", n);
  }
  va_end(args);
}


void command2(int argc, ...)
{
  int i;
  va_list args;
  va_start(args, argc);

  printf("command2\n");

  for(i = 0; i < argc; i++)
  {
    int n;
    n = va_arg(args, int);
    printf("%d\n", n);
  }
  va_end(args);
}

void test_queue(void)
{
  int i;

  printf("test_queue start\n");

  initialize();
  enqueue(command1);
  enqueue(command2);
  for(i = 0; i < 16; i++)
  {
    command v = dequeue();
    if(v != NULL)
    {
      v(1, i);
    }
  }
  printf("test_queue end\n");
}


int main(int ac, char** av)
{
  test_queue();
  return 0;
}
test_queue start
command1
0
command2
1
test_queue end

連結リストで Command パターン

連結リストで実装してみる。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>

typedef void (*command_t)(int argc, ...);

struct node_t
{
  struct node_t* next;
  command_t cmd;
} root;

/* 先頭に追加 */
void put(command_t cmd)
{
  struct node_t* _p;
  struct node_t* _q;

  for(_p = &root; _p->next != NULL; _p = _p->next)
    ;

  _q = (struct node_t*)malloc(sizeof(struct node_t));
  if(_q == NULL)
  {
    perror("put");
    exit(0);
  }
  _q->cmd = cmd;
  _q->next = _p->next;
  _p->next = _q;
}

/* 先頭を削除 */
void get(void)
{
  struct node_t* _p;

  _p = root.next;
  if(_p == NULL)
  {
    printf("root is empty\n");
    return;
  }

  root.next = _p->next;
  free(_p);
}

void command1(int argc, ...)
{
  int i;
  va_list args;
  va_start(args, argc);

  printf("command1\n");

  for(i = 0; i < argc; i++)
  {
    int n;
    n = va_arg(args, int);
    printf("%d\n", n);
  }
  va_end(args);
}


void command2(int argc, ...)
{
  int c;
  int n;
  va_list args;

  printf("command2\n");

  va_start(args, argc);
  c = va_arg(args, int);
  n = va_arg(args, int);
  printf("c:%d n:%d\n", c, n);

  va_end(args);
}

void run(void)
{
  int n;
  struct node_t* _p;

  n = 0;
  for(_p = &root; _p->next != NULL; _p = _p->next)
  {
    if(_p->next != NULL)
    {
      _p->next->cmd(2, n, n * 10);
      n++;
    }
  }
}

void test_command(void)
{
  printf("test_command start\n");
  put(command1);
  put(command2);
  run();
  printf("test_command end\n");
}

int main(int ac, char** av)
{
  test_command();
  return 0;
}
test_command start
command1
0
0
command2
c:1 n:10
test_command end

連結リストで優先度あり Command パターン

連結リストの配列にしただけです。0 が優先度高くて、20 が優先度低いです。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>

#define PRI_MAX 20

typedef void (*command_t)(int argc, ...);

struct node_t
{
  struct node_t* next;
  command_t cmd;
} root[PRI_MAX];

/* 先頭に追加 */
void put(int pri, command_t cmd)
{
  int i;
  struct node_t* _p;
  struct node_t* _q;

  for(_p = &root[pri]; _p->next != NULL; _p = _p->next)
    ;

  _q = (struct node_t*)malloc(sizeof(struct node_t));
  if(_q == NULL)
  {
    perror("put");
    exit(0);
  }
  _q->cmd = cmd;
  _q->next = _p->next;
  _p->next = _q;
}

void command0(int argc, ...)
{
  int pri;
  int n;
  va_list args;

  va_start(args, argc);
  pri = va_arg(args, int);
  n = va_arg(args, int);
  printf("command0 pri:%d n:%d\n", pri, n);

  va_end(args);
}

void run(void)
{
  int pri;
  int n;
  struct node_t* _p;

  n = 0;

  for(pri = 0; pri < PRI_MAX; pri++)
  {
    for(_p = &root[pri]; _p->next != NULL; _p = _p->next)
    {
      if(_p->next != NULL)
      {
        _p->next->cmd(2, pri, n);
        n++;
      }
    }
  }
}

void test_command(void)
{
  printf("test_command start\n");
  put(19, command0);
  put(19, command0);
  put(0, command0);
  put(0, command0);
  put(1, command0);
  put(2, command0);
  run();
  printf("test_command end\n");
}

int main(int ac, char** av)
{
  test_command();
  return 0;
}
test_command start
command0 pri:0 n:0
command0 pri:0 n:1
command0 pri:1 n:2
command0 pri:2 n:3
command0 pri:19 n:4
command0 pri:19 n:5
test_command end

Discussion