1. callback 

  • 라이브러리 에서 우리가 만든 함수를 호출하는 경우...
  • 이렇게 역방향으로 호출되는 함수를 Callback 함수라고 한다.
  • 예를 들어 라이브러리에 생일축하 노래불러주는 함수가 있다고 해보자.
  • 사랑하는 땡땡땡~ 이부분은 우리의 목소리를 넣고 싶다.
  • 그러면, 땡땡땡에 무엇을 넣어야할지를 라이브러리에 알려주기 위해,
  • 만드는 함수가 Callback 함수이다.
  • 우리는 callback 함수를 만들고 , 이 힘수의 포인터를 라이브러리에 알려주면,
  • 라이브러리는 땡땡땡이 나오는 순간, Callback 함수를 호출하여 생일축하 노래를 완성한다.,
  • 그 예로 표준함수중, 데이터를 정렬하는 기능을 수행하는 qsort()가 있다.
  • 퀵소트 함수인데.
  • 데이터타입은 개발자가 정할 수 있다.
  • 그래서 데이터를 비교하는 기능은 개발자가 Callback 함수로 만들어 라이브러리에 제공하도록 하였다.
  • 정렬시 어떤 데이터가 앞으로, 어떤 데이터가 뒤로 갈지를 라이브러리에서 결정하는 것이 아니라, 개발자가 정한다.
  • 이렇게 하면 기본 데이터 타입 뿐 아니라 , 개발자가 정의 한 구조체에 대해서도 정렬을 할 수 있고, 오름 차순인지, 내림차순정렬인지 등을 개발자 마음대로 변경할 수 있어 유연성이 엄청나게 증가한다.


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

#define  NUM 10

int ascending(const void*a , const void*b)
{
    if (*(int*) a > *(int*) b)
        return 1;      
    else if (*(int*) a < *(int*) b)
        return -1;           
    else           
        return 0;                 
}

int descending(const void*a , const void*b)
{
    if (*(int*) a < *(int*) b)
        return 1;       
    else if (*(int*) a > *(int*) b)
        return -1;           
    else           
        return 0;                 
}

void output(int *data, int size)
{
    for (int i=0; i<size; i++) 
        printf("%d ", data[i]);
    puts(""); 
}

void main()
{
    int data[NUM]= { 10,20,30,40,9023,1231,2345,343,123,532 };
    qsort(data, NUM, sizeof(int) , ascending);
    output(data, NUM);
    qsort(data, NUM, sizeof(int) , descending);
    output(data, NUM);       
}


#include <stdio.h>
void test_func(void (*func)(int aa,int bb), int a, int b)
{
    printf("I am Test Function\n");

    //callback function call
    func(a, b);
}

void call_back_func_1(int a, int b)
{
    printf("I am CallBack Function1 -- a=%d,b=%d\n", a,b);
}

void call_back_func_2(int a,int b)
{
    printf("I am CallBack Function2 -- a=%d,b=%d\n", a,b);
}

int main(int argc, char **argv)
{
        int answer1;
        int answer2;

        if (argc != 3) {
                printf("err argc = %d\n",argc);
                return -1;
        }
    answer1 = atoi(*(argv + 1));
    answer2 = atoi(*(argv + 2));
        switch (answer1)
        {
        case 1:
                 test_func(call_back_func_1, answer1,answer2);
                 break;
        case 2:
                 test_func(call_back_func_2, answer1,answer2);
                 break;
        }
        return 0;
}


'dev > C' 카테고리의 다른 글

가변 인자 함수(va_list, va_start, va_arg, va_end)  (0) 2013.02.19
시간 측정을 위한 gettimeofday 사용예제  (0) 2012.12.19
[C언어] assert()  (0) 2010.11.09
문자열 처리 함수  (0) 2010.11.05

가변 인자 함수 : 함수의 전달값(파라미터)(인수) 의 개수가 변경될수있는 함수.

ex) printf, scanf


예제

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

void va_fct(int nFix, ...); //가변 인자 함수 선언

int main(void)
{
    va_fct(3, 1, 2, 3);
    return 0;
}

void va_fct (int nFix, ...);
{
    int i;
    va_list    list; //list 포인터

    va_start (list, nFix); //list 포인터 초기화

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

    va_end(list); //list reset
}

 1 2 3


  •  va_list : 전달된 인수들은 스택에 저장되고 함수는 스택에서 인수를 꺼내쓴다.  va_list 타입은 char*형으로 정의되어 있고 가변인수를 읽기 위한 포인터 변수다.
  • va_start(list, 마지막고정인수) :  list 포인터 변수가 첫번째 가변인수를 가리키도록 초기화한다. 마지막 고정인수의 번지에 길이를 더해서 가변인수가 시작되는 번지를 계산한다.
  • va_arg(list, 인수타입) : 가변인수를 실제로 읽는 명령어, list 위치에서 인수타입에 맞는 값을 읽고 리턴하여 list를  다음 가변인수의 위치로 옮겨준다. va_arg는 매크로 함수이기 때문에 타입명이 내부적으로 sizeof 연산자와 캐스트연산자로 전달되어 인수로 받을 수 있다.
  • va_end(list) 가변인수를 다 읽은후 reset.


가변 인자 함수의 조건

  • 반드시 하나이상의 고정인수를 가져야한다. 가변인수를 읽기위해 포인터 list를 초기화하기위해 마지막 고정 인수의 번지를 알아야하기때문이다. 고정인수가 없으면 vs_start매크로가 동작하지않는다.
  • 함수 내부에서 자신에게 전달된 가변인수의 개수를 알수있어야한다. 인수의 개수에는 제한이없고 컴파일러가 인수의 개수를 점검하지않으므로 함수가 인수의 개수를 파악할수있게 정보를 제공해야한다.
  • 함수 내부에서 각각의 가변인수타입을 알 수 있어야한다. va_arg매크로가 list번지에서 가변 인수를 읽을때 얼만큼 어떤 타입으로 해석할지를 알아야하기때문이다. 하나의 고정인수를 통해서 모든 가변인수의 타입을 알수있게하는 방식이 가장 좋다.


'dev > C' 카테고리의 다른 글

callback  (0) 2013.05.29
시간 측정을 위한 gettimeofday 사용예제  (0) 2012.12.19
[C언어] assert()  (0) 2010.11.09
문자열 처리 함수  (0) 2010.11.05
#include <sys/time.h>
#include <unistd.h>
struct timeval
{
    long tv_sec;       // 초
    long tv_usec;      // 마이크로초
}
int gettimeofday(struct timeval *tv, struct timezone *tz);


long gettimeofday_d(void)
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return (tv.tv_sec*1e6) + tv.tv_usec;
}


long getTimeGap(struct timeval *s_t, struct timeval *e_t)
{
    struct timeval rt;
    long et = 0L;

    rt.tv_sec = e_t->tv_sec - s_t->tv_sec;
    rt.tv_usec = e_t->tv_usec - s_t->tv_usec;

    if(rt.tv_usec < 0)
    {
        rt.tv_sec--;
        rt.tv_usec += 1000000L;
    }
    et = (rt.tv_sec*1000000L) + rt.tv_usec;
    return et;
}


'dev > C' 카테고리의 다른 글

callback  (0) 2013.05.29
가변 인자 함수(va_list, va_start, va_arg, va_end)  (0) 2013.02.19
[C언어] assert()  (0) 2010.11.09
문자열 처리 함수  (0) 2010.11.05
표준 라이브러리 헤더파일인 assert.h 에서 정의하고있다.
이 매크로는 프로그램에 임의의 표현식을 추가해 검사할수 있게 해주며, 표현식의 값이 0이면(거짓) 메시지를 출력하고 프로그램을 종료한다
 
assert(a==b) 에서 a==b가 거짓이면 메시지가 출력하고 프로그램을 종료한다
  
assert.h를 포함하는 #include 앞에 기호 NDEBUG를 정의해주면 assert()가 실행되지않는다
 
#define NDEBUG         // assert()가 실행되지 않게함
#include <assert.h>
 
몇몇 프로그램에선 기본적으로 assert를 사용할수없도록 하고있다.. 이경우에는
 
#undef NDEBUG         // assert()가 사용할수있도록함
#include <assert.h>

'dev > C' 카테고리의 다른 글

callback  (0) 2013.05.29
가변 인자 함수(va_list, va_start, va_arg, va_end)  (0) 2013.02.19
시간 측정을 위한 gettimeofday 사용예제  (0) 2012.12.19
문자열 처리 함수  (0) 2010.11.05


** 문자열 처리 함수 **

#include <string.h>

 1) 문자열의 길이 측정(strlen)

    strlen(문자열)

 

2) 문자열 결합(strcat)

    char *ptr;

    ptr = strcat(문자열, 문자열2)

 

3) 문자열 비교(strcmp)

    int i;

    i = strcmp(문자열, 문자열2)

    i == 0 <--- 같다.

    i != 1 같지 않다.

 

4) 문자열 복사(strcpy)

    char *ptr;

    strcpy(문자열, 문자열2)

    문자열2를 문자열로 복사

 

5) 문자열 변환(atoi, atol, atof)

    atoi -> 정수

    atol -> long

    atof -> 부동 소수점.

   

    long b; float c;

    int a;

    a = atoi("1234");

    b = atol("-544334");

    c = atof("43.5456);

 

6) 문자열 교환 함수 (str_swap)

    void str_cpy(char *ptr1, char *ptr2)

    {

       while(*ptr2)

        *ptr1++ = *ptr2++;

       *ptr1 = NULL;

    }

 

    void str_swap(char *a, char *b)

    {

       char temp[255];

 

       str_cpy(temp, a)

       str_cpy(a, b);

       str_cpy(b, temp);

    }


7) 문자열 내에서 특정 문자의 개수를 카운트 하는 함수(char_cnt)

    int char_cnt(char *ptr, char ch)

    {

        int i = 0;

        wile(*ptr)

        if(*ptr++ == ch)

        i++;

        return(i);

    } 

 

8) 문자열 내의 특정 문자를 다른 문자로 바꾸는 함수(str_chg)

    int str_chg(char *ptr, char ch1, char ch2)

    {

       while(*ptr)

       {

        if(*ptr == ch1)

           *ptr = ch2;

        ptr++;

       }

    }

 

9) 문자열 내의 특정 문자를 탐색(str_fine)

    char *str_find(char *ptr, char ch)

    {

       while(*ptr)

       {

        if(*ptr == ch)

           return(ptr);

        ptr++;

       }

       return((char *)(-1));

    }

 

10) 문자열 내의 소문자를 대문자로 바꾸는 함수(str_upp)

    void str_upp(char *ptr)

    {

       while(*ptr)

       {

        if(islower(*ptr))

           *ptr = toupper(*ptr);

        ptr++;

        }

    }

 

11) 문자열 내의 대문자를 소문자로 바꾸는 함수(str_low)

    void str_low(char *ptr)

    {

       while(*ptr)

       {

        if(isupper(*ptr))

           *ptr = tolower(*ptr);

        ptr++;

       }

    }

 

12) 대문자와 소문자 상호 교환 함수(str_case)

    void str_case(char *ptr)

    {

       while(*ptr)

       {

        if(isupper(*ptr))

           *ptr = tolower(*ptr);

        else if(islower(*ptr)

           *ptr = toupper(*ptr);

        ptr++;

       }

    }

 

13) 각 문장의 첫 문자만 대문자로 교환하는 함수(str_fst)

    void str_fst(char *ptr)

    {

        if(islower(*ptr))

        *ptr = toupper(*ptr);

        while(*ptr)

        {

        if(*ptr == '.')

        {

           ptr++;

           while(*ptr == ' ')

            ptr++;

           if(islower(*ptr))

            *ptr = toupper(*ptr);

        }

        }

        ptr++;

    }

 

14) 문자열 내의 지정한 위치에 다른 문자열을 삽입하는 함수(str_ins)

    char *str_ins(char ptr1[], char ptr2[],int t)

    {

       char temp[255];

       int i, j, k;

       if(t>=str_len(ptr1) return (-1);

      

       for(k=0; i=0; i<t; i++; k++)

        temp[k] = ptr1[i];

   

       for(j=0; ptr2[j] !=NULL; j++, k++)  

        temp[k] = ptr2[j];

 

       while(ptrl1[i])

        temp[k++] = ptr1[i++];

       temp[k] = NULL;

    }

 

15) 문자열 앞에 지정한 개수 만큼의 공백을 추가하는 함수(str_blk)

    void str_blk(char ptr[], int t)

    {

       static char temp[255];

       int i;

       for(i = 0; i<t; i++)

        temp[i] = BLANK;

       temp[i] = NULL;

       str_cat(temp ptr);

       str_cpy(ptr, temp);

    }

 

16) 문자열 내의 모든 공백을 삭제하는 함수(rmv_blk)

    void rmv_blk(char ptrp[])

    {

       char temp[255];

       int i, k;

 

       for(i=0, k=0; ptr[i] != NULL; i++)

        if(ptr[i] != BLANK)

           temp[k++] = ptr[i];

       temp[k] = NULL;

       str_cpy(ptr, temp);

    }

 

17) 문자열 내에서 원하는 개수 만큼 문자를 삭제하는 함수(str_rmv)

    void str_rmv(char *ptr, int loc, int count)

    {

       int len, i, j;

       len = str_len(ptr);

       if(loc >= len)

        return (-1);

       if(loc + count <= len)

       {

        j = loc + count;

        for(i=loc; ptr[j] != 0; i++)

        {

           ptr[i] = ptr[j];

           j++;

        }

            ptr[i] = NULL

       }

       else

        ptr[loc] = NULL;

    }

 

18) 특정한 문자열이 기억된 위치를 계산하는 함수(str_loc)

    int str_loc(char ptr1[], char ptr2[])

    {

       int i, j, k;

       for(i=0; ptr1[i] != NULL; i++)

        for(j=i, k=0; ptr2[k] == ptr1[j]; k++, j++)

           return (i);

       return (-1);

    }

 

19) 특정한 문자열이 나온 개수를 카운트 하는 함수(str_cnt)

    int str_cnt(char ptr1[], char ptr2[])

    {

       int i, j, k;

       int count = 0;

       for(i=0; ptr1[i] != NULL; i++)

        for(j=i, k=0; ptr2[k] == ptr1[j]; k++, j++)

           if(ptr2[k+1] == NULL)

           {

            count++;

            break;

           }

        return ((count == 0) ? -1 : count);

    }

'dev > C' 카테고리의 다른 글

callback  (0) 2013.05.29
가변 인자 함수(va_list, va_start, va_arg, va_end)  (0) 2013.02.19
시간 측정을 위한 gettimeofday 사용예제  (0) 2012.12.19
[C언어] assert()  (0) 2010.11.09

+ Recent posts