마음의 안정을 찾기 위하여 - 가변인자와 Printf 그리고 Wrapping 함수 만들기.
2401011
28
340
관리자새글쓰기
태그위치로그방명록
별일없다의 생각
dawnsea's me2day/2010
색상(RGB)코드 추출기(Color...
Connection Generator/2010
최승호PD, '4대강 거짓말 검...
Green Monkey**/2010
Syng의 생각
syng's me2DAY/2010
천재 작곡가 윤일상이 기획,...
엘븐킹's Digital Factory/2010
가변인자와 Printf 그리고 Wrapping 함수 만들기.
리눅스/리눅스 프로그래밍 | 2010/05/06 09:58
대학시절에 재미삼아 만들기 시작했던 텍스트 머드를 지금도 개인적으로 운영을 하고 있다.

사실 그당시 오픈소스(무한대전/Mordor)를 가져다가 짜깁기 한 정도에 지나지 않지만 그래도 아직까지 일부 유저들이 플레이를 해주고 있기에 해당 서버를 닫지 못하고 그 명맥을 유지해오고 있는 셈인데....

게임을 플레이하는 유저들이 업데이트를 해달라는 성화가 있음에도 불구하고, 눈에 보이는 업데이트는 많이 이뤄지지 못하고 있는게 현실.....

머드 퀘스트를 위한 "LUA" 스크립트 적용과 더불어 무한대전 소스에서 쉽게 볼 수 있는 아래와 같은 형태의 함수를 가변 인자로 바꾸기 위한 작업을 진행하고 있다.

void function_name(fmt, i1, i2, i3, i4, i5, i6)
char *fmt;
int i1,i2,i3,i4,i5,i6;
{


위와 같은 함수 형태를 아래와 같이 적용하려는 계획.....

void function_name(char *format, ....){ ... }


단순하게 함수를 Wrapping하는 역할만이라면 아래와 같이 간단하게 처리가 가능하겠으나...

int custom_printf(const char *fmt, ...)
{
  va_list argptr;
  int     ret;

  va_start(argptr, fmt);
  ret = vprintf(fmt, argptr);
  va_end(argptr);

  return ret;
}


사용자 정의 Format까지 추가해주어야 하기 때문에 처음에 잠깐.. (아니 많이..) 당황했다.
추가하려는 사용자 정의 포맷은

'M' - creature* 형태의 인자를 넘겨받아 멤버변수 name의 값을 출력해준다.
'A'  - 무한대전의 특징인 안시처리 문자를 넘겨받아 처리 한다. ({빨/{노/{파/{하... 등)
'I' - object* 형태의 인자를 넘겨받아 멤버변수 name의 값을 출력한다.
'J' - 한글 조사를 출력한다. ("은"/"는", "이"/"가"....등)
'C' - 지정 숫자에 해당하는 안시 코드를 처리하는 인자
'D' - 지정 숫자에 해당하는 안시 코드를 처리하는 인자

넘겨받은 포맷 스트링에서 위에 해당하는 포맷이 있는지 확인하고 해당 포맷을 처리한후 문자열 형태로 다시 넘겨줘 처리해주는 형태로 작업을 하고 있다.

현재 테스트 작업을 진행하고 있고, 조만간 실제 운영서버에도 적용할 수 있을것 같다. 그냥 혼자서 흐뭇 -_-;

■ 가변인자를 이용한 Log 남기기 함수의 예
#include <stdarg>

static int Log(LogLevel aLogLevel, const char* aFormat, ...)
{
  va_list argptr;
  int rv = OK;

  va_start(argptr, aFormat);

  FILE* f = fopen("c:/xxx.txt", "a+");
  if(!f) {
    rv = ERROR_FAILURE;
  } else {
    if(rv = vfprintf(f, aFormat, argptr) < 0){
      rv = ERROR_FAILURE;
    }
    fclose(f);
  }
  va_end(argptr);

  return rv;
}


그리고 웹 서핑중 누군가 올려놓은 custom printf 소스 (가져온곳 : http://kldp.org/node/2799#comment-7211)

#include // for i/o library
#include // for variable argument library

#define my_va_start(VA_LIST,LAST_NAMED_ARG) \
        ((VA_LIST) = ( (char *)(&(LAST_NAMED_ARG)) + sizeof
        (LAST_NAMED_ARG) ))
#define my_va_arg(VA_LIST, SOME_TYPE) \
        ((VA_LIST) = (char *)(VA_LIST) + sizeof(SOME_TYPE), \
        *(SOME_TYPE*)((char *)(VA_LIST) - sizeof(SOME_TYPE)))
#define my_va_end(VA_LIST) ()

void my_printf(char *fmt, ...);
void my_printf_and_va(char *fmt, ...); // same as my_printf(),

// except uses my va_arg stuff
int main(int argc, char *argv[])
{
  const double x = 3.4;
  const int q    = 4;
  char a[]       = "hey guy!";

  printf("Here's version with standard va_arg\n");
  my_printf("%f %d %s\n", x, q, a);
  printf("Here's version with my_va_arg\n");
  my_printf_and_va("%f %d %s\n", x, q, a);
  return 0;
}

void my_printf(char *fmt, ...)
{ 
  // initialize pass over arguments
  va_list argl;

  va_start(argl, fmt); // beginning after last named argument fmt
  for (char *p = fmt; *p; ++p) // format string controls parsing of args
  {
    if (*p == '%')
    { 
      switch (*++p)
      { 
      case 'f' : 
        double fval=va_arg(argl,double); // get arg as double
        cout << fval; break;
      case 'd' : 
        int ival=va_arg(argl,int);
        cout << ival;
        break;
      case 's' : 
        char *sval = va_arg(argl,char *);
        cout << sval; break;
      default : 
        cout << *p;
        break;
      }
    }
    else cout << *p;
  }
  va_end(argl);
}

void my_printf_and_va(char *fmt, ...)
{
  // initialize pass over arguments
  my_va_list argl;
  my_va_start(argl, fmt); // beginning after last named argument fmt

  // this loop is identical to that in my_printf() except
  // that it uses non-portable version of va_start(),va_arg(),va_end
  for (char *p = fmt; *p; ++p) // format string controls parsing of args
  {
    if (*p == '%') {
      switch (*++p)
      {
      case 'f' :
        double fval= my_va_arg(argl,double); // get arg as double
        cout << fval; break;
      case 'd' :
        int ival=my_va_arg(argl,int);
        cout << ival; break;
      case 's' :
        char *sval = my_va_arg(argl,char *);
        cout << sval; break;
      default :
        cout << *p;
        break;
     }
    } else cout << *p;
  }
  va_end(argl);
}


2010/05/06 09:58 2010/05/06 09:58
Article tag list Go to top
View Comment 0
Trackback URL :: 이 글에는 트랙백을 보낼 수 없습니다
 
 
 
 
: [1] ... [270][271][272][273][274][275][276][277][278] ... [1323] :
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        
전체 (1323)
출판 준비 (0)
My-Pro... (41)
사는 ... (933)
블로그... (22)
My Lib... (32)
게임 ... (23)
개발관... (3)
Smart ... (1)
Delphi (93)
C Builder (0)
Object... (0)
VC, MF... (10)
Window... (1)
Open API (3)
Visual... (0)
Java, JSP (2)
ASP.NET (0)
PHP (6)
Database (12)
리눅스 (29)
Windows (25)
Device... (1)
Embedded (1)
게임 ... (0)
Web Se... (2)
Web, S... (21)
잡다한... (7)
프로젝트 (0)
Personal (0)
대통령... (13)
Link (2)