동적 분기의 구현에 대해서.

shint의 이미지

데이터에 따라 if() 조건문을 동적으로 제어 할 수있을까요?

보통
#define PACKET1 10
#define PACKET2 120
#define PACKET3 140

#define PACKET_A 1
#define PACKET_B 2

if(PACKET1 == recv[0])
{
if(PACKET2 == recv[1])
{
if(PACKET_A == recv[2])
{
}
if(PACKET_B == recv[2])
{
}
}
}

보통 이런식으로 구현하는걸로 알고 있습니다.

정의된 PACKET을 데이터(or DB)에서 불러와서 동적인 분기를 하고 싶습니다.
어떻하면 가능할까요?

M.W.Park의 이미지

function pointer를 사용해보세요.
-----
오늘 나의 취미는 끝없는, 끝없는 인내다. 1973 法頂

-----
오늘 의 취미는 끝없는, 끝없는 인내다. 1973 法頂

shint의 이미지

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

M.W.Park의 이미지

1. 메서드(함수) 추출: if 절 밑의 처리들을 함수들로 만들어 밖으로 뺍니다.
2. 로직 저장: 조건에 따른 수행할 함수들의 리스트를 맵 같은 곳에 저장합니다. key=조건, value=실행할 함수 포인터(들).

사용은 대충 다음과 같은 pseudo code 같이....

key = gen_key(...);
funs = map.get(key);
for (fun : funs) invoke(fun);

-----
오늘 나의 취미는 끝없는, 끝없는 인내다. 1973 法頂

-----
오늘 의 취미는 끝없는, 끝없는 인내다. 1973 法頂

grassman의 이미지

처리할 수 있는 방법에는 제한이 있을 것이고 각 경우에 대해 label을 붙입니다.
그리고 DB나 별도의 Table로 packet이 달라지는 영역에 대한 signature와 label에 대한
map을 만듭니다. 그리고 signature 비교후 label 값에 대해 switch문으로 처리합니다.

구현해 보면 다음과 같은 형태가 되겠죠.
(가정을 간단하게 한 겁니다만.. 실제로는 따져야 할 것이 더 많을겁니다.)

#include <stdio.h>
#include <string.h>
 
/* enumeration of all possible conditions */
typedef enum
{
  CASE_1 = 0,
  CASE_2,
  CASE_3,
  NO_CASE
} label_t;
 
/* structure for storing signature & its condition */
typedef struct
{
  char *signature;
  label_t label;
} dynamic_comparison_table_t;
 
/* comparison length */
#define COMPARISON_LENGTH     4
 
/* comparison table (may be in DB) */
const dynamic_comparison_table_t comp_table[] =
{
  {"\x01\x00\x02\x00", CASE_1},
  {"\x02\x01\x00\x00", CASE_2},
  {"\x02\x02\x00\x00", CASE_3}
};
 
/* check if appropriate signature is found */
label_t compare_signature(char *packet)
{
  int i;
 
  for( i = 0; i < sizeof(comp_table)/sizeof(dynamic_comparison_table_t); i++ )
  {
    if( memcmp(comp_table[i].signature, packet, COMPARISON_LENGTH) == 0 )
      return comp_table[i].label;
  }
 
  return NO_CASE;
}
 
/* how to use */
int main(void)
{
   char *packet = "\x01\x00\x02\x00\x11\x22\x33\x44";
 
   /* jump by signature */
   switch( compare_signature(packet) )
   {
     case CASE_1:
       /* blah blah */
       break;
 
     case CASE_2:
       /* blah blah */
       break;
 
     case CASE_3:
       /* blah blah */
       break;
 
     case NO_CASE:
       fprintf(stderr, "ERROR!\n");
       break;
   }
 
   return 0;
}

shint의 이미지

동적인 조건 분기는 데이터 자체를 비교해야한다는 말이되네요.
한가지 걱정되는건. 저런 데이터 테이블이 크면 클수록. 비교시간이 늘어나서요.
한번에 해당하는 데이터 루틴으로 가게 하기위한 조건으로 동적인 분기를 스크립트로 구현하려고 생각했습니다.
생각보다 어렵네요.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

grassman의 이미지

1단계에서 hash로 비교 대상의 수를 줄여둔 다음에 작은 테이블에서 최종 비교를 하는 방법도 생각해 볼 수 있습니다. 결론적으로 데이터의 특징을 보고 최적화를 하면 되겠습니다만 현재로서는 데이터에 대한 단서가 전혀 없으므로 일반적인 방법 밖에는 설명할 수가 없군요.

shint의 이미지

해시를 사용해도 되겠네요.
해시 생성시에 비용도 만만찮겠어요 ㅋ_ㅋ

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

shyblue의 이미지

패킷에서 읽은 특정한 명령에 반응하는 분기라면, 콜백함수 즉 함수포인터를 사용하는것이 더 효율적일 수 있다에 한표던집니다.

그런식으로 잘 만들어논 코드는 ngIRCd라는 IRC Server에서 참조하실 수 있습니다.

時日也放聲大哭

時日也放聲大哭

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.