설명 #

"함수포인터"는 C언어에서 자주 쓰이는 기본 용법중 하나입니다. 정의는 다음과 같습니다.
선언된 함수가 저장된 메모리 번지값을 담고 있는 포인터 변수
하지만 이것을 왜 보통의 포인터와는 달리 특별취급하냐면 다음과 같은 이유 때문입니다.
  1. 일반 포인터 변수와는 조금 다르게 보이는 문법으로 선언됩니다. 예를 들어 함수 포인터 변수는 다음과 같이 선언합니다. (functionPtr이 포인터 변수명이 됩니다)
    void (*functionPtr)(const char *s_)
    
  2. 함수포인터는 실행부분을 가리키는 포인터 변수인탓에 () 연산자를 사용할 수 있습니다. 즉, 위의 functionPtr은 아래와 같이 실행가능합니다.
    functionPtr("바보나라~")
    

주로 함수포인터는 콜백(callback)을 구현하는데 사용됩니다. 어떤 라이브러리를 제작할 때 개발자가 어떤 "경우"에 대한 반응을 함수로 작성하고 이를 다시 라이브러리에서 호출하도록 작성하고자 할 때, 개발자가 작성한 함수의 포인터를 넘겨받아 실행하도록 하면 아주 유용할 때가 많습니다. (대표적인 예가 win32 api에서 윈도우 프로시져를 WNDCLASS의 lpfnWndProc맴버에 등록하는 부분을 들 수 있습니다) 즉, 함수를 마치 변수와 같이 취급하는 것이 가능해집니다.

예제 #

아래 예제는 함수포인터를 활용한 간단한 예제입니다.
#include <stdio.h>

void testout1(const char *s) {
  printf("시험출력1:%s\n", s);
}

void testout2(const char *s) {
  printf("시험출력2:%s\n", s);
}

// 함수포인터 변수
void (*funcPtr)(const char *s);

int main() {
  // 함수포인터를 testout1, testout2로 각각 대입해보고 실행해본다.
  funcPtr = testout1;
  funcPtr("테스트");
  funcPtr = testout2;
  funcPtr("테스트");
}

실행결과는 아래와 같습니다.
시험출력1:테스트 시험출력2:테스트
main()안에서는 funcPtr만 실행했지만 마치 testout1, testout2를 각각 실행한 것과 같은 효과가 있음을 알 수 있습니다.

typedef 거는 법 #

함수포인터를 어떤 포인터 변수로서 활용하고 싶을 때 typedef를 활용하면 매우 편리합니다. 실제로 win32 API에서는 윈도우 프로시저 함수포인터형으로 WNDPROC라는 타입이 있습니다. (이부분을 보면 어느정도 사용법에 대한 느낌이 올겁니다) winuser.h 헤더화일에서 검색해보면 다음과 같이 선언되어있습니다.
typedef LRESULT(CALLBACK *WNDPROC)(HWND,UINT,WPARAM,LPARAM);
실제로 사용될 때에는 다음과 같이 사용됩니다.
LRESULT CALLBACK winproc1(HWND,UINT,WPARAM,LPARAM) { }; ... WNDPROC winprocPtr = winproc1; ...
꽤 유용한 문법이니 알아두시면 좋습니다.

주의사항 #

함수포인터는 알아두면 상당히 유용한 기법이지만 사용시에는 다음과 같은 부분을 주의해야합니다.
  1. 대입되지 않은 (NULL값상태의) 함수포인터를 실행하지 않도록 주의해야합니다. 초기화를 항상 NULL로 해두고 실행전에 검사하는 것도 좋은 방법입니다.
  2. "같은 함수 포인터 타입"이라는 것을 증명하려면, 반환값, 매개변수의 타입 및 개수가 모두 일치해야합니다. 보통 하나라도 다른 함수포인터값을 대입하면 컴파일시 오류가 나게 됩니다.


출처 : http://www.redwiki.net/wiki/wiki.php/%C7%D4%BC%F6%C6%F7%C0%CE%C5%CD

#include <stdio.h>
#include <errno.h>
#include <mysql.h>

MYSQL mysql;

// 쿼리 질의를 한다
void sql_qur(char *sql_query)
{
     printf("input sql query is %s\n", sql_query);
     if( mysql_real_query(&mysql, sql_query, strlen(sql_query)) )
     {
          perror( mysql_error(&mysql) );
          exit( 1 );
     }
}

// 쿼리 질의로 온 결과를 모두 출력한다.
void sql_print_result(char *result)
{
     MYSQL_RES *res;
     MYSQL_ROW row;
     MYSQL_FIELD *fld;
     int fields;

     if( !(res=mysql_store_result(&mysql)) )
     {
          perror( mysql_error(&mysql) );
          exit( 1 );
     }
 
     sprintf(result, "");

     while( (row=mysql_fetch_row(res)) )
     {
          int     i;
     
          for( i=0 ; i<mysql_num_fields(res) ; i++ )
          {
              fld = mysql_fetch_field_direct( res, i );

              if(i == 0)
                  sprintf( result, "%s%20s: %s", result, fld->name, row[i] );
              else
                  sprintf( result, "%s\n%20s: %s", result, fld->name, row[i] );

              if( !strlen(row[i]) )
              {
                  mysql_free_result(res);
                  mysql_close(&mysql);
                  exit(0);
              }
          }
          sprintf( result, "%s\n\n", result );
      }

      mysql_free_result(res);
}

// 쿼리를 받음 단, 한줄에 한개의 쿼리가 찍힌다
void sql_get_result(char *result)
{
        MYSQL_RES *res;
        MYSQL_ROW row;
        int line = 0;
 
        if( !(res=mysql_store_result(&mysql)) )
        {
                perror( mysql_error(&mysql) );
                exit( 1 );
        }
 
        sprintf(result, "");
 
        while( (row=mysql_fetch_row(res)) )
        {
                int     i;
 
                for( i=0 ; i<mysql_num_fields(res) ; i++ )
                {
                        if(i == 0 && line == 0)
                               sprintf( result, "%s", row[i] );
                        else
                               sprintf( result, "%s\n%s", result, row[i] );
 
                        if( !strlen(row[i]))
                        {
                                mysql_free_result(res);
                                mysql_close(&mysql);
                                exit(0);
                         }
                 }
                ++line;
        }
        result[strlen(result)] = '\0';
        mysql_free_result(res);
}

void main(void)
{
        char input_query[100];
        mysql_init( &mysql );

        if( !mysql_real_connect(&mysql,
           "localhost",            // host
           "user",          // user
           "pw",       // passwd
           "db_name",          // db
           3306,                   // port
           NULL,
           0) )
        {
         perror( mysql_error(&mysql) );
         exit( 1 );
        }

        // user 테이블을 출력한다.
        sql_qur("select * from user;");
        sql_print_result(&input_query);
        printf("sql result %s\n", input_query);
 
        // test01 ID에 대한 password 값을 구한다.
        sql_qur("select password from user where ID='test01';");
        sql_get_result(&input_query);
        printf("sql result %s\n", input_query);
 
        // 질의를 입력 받아서 그 결과를 계속 출력
        while(1)
        {
                printf("input sql query! : ");
                sql_qur(gets(input_query));

                sql_get_result(&input_query);
                printf("\nsql result %s\n", input_query);
        }

        mysql_close(&mysql);
}


 출처 카페 > 세은파파의 프로그래밍 하자 .. | 세은파파
원문 http://cafe.naver.com/cyberzone/172
MySQL C API

 1) my_ulonglong mysql_affected_rows(MYSQL* mysql)
        INSERT, UPDATE, DELETE 등의 query로 영향을 받은 ROW의 수를 리턴한다.

2) void mysql_close(MYSQL* mysql) 서버와의 연결을 종료한다.

3) void mysql_data_seek(MYSQL_RES* result, unsigned int offset)
        result에서 임의의 ROW에 접근을 하도록 하는 함수이다. offset이 row의 번호를
        나타낸다. 0이면 처음 ROW, mysql_num_rows( result ) - 1 은 마지막 row를 나타낸다.

4) unsigned int mysql_errno(MYSQL* mysql) 
    가장 최근에 mysql에 일어난 에러의 번호를 리턴한다.

5) char* mysql_error(MYSQL* mysql) 가장 최근에 일어난 에러 메시지를 리턴한다.

6) MYSQL_FIELD* mysql_fetch_field(MYSQL_RES* result)
        한번 호출할 때마다 한 나의 필드에 대한 정보를 리턴한다.

7) MYSQL_FIELDS* mysql_fetch_fields(MYSQL_RES* result)
        배열 형대로 result의 필드에 대한 정보를 한꺼번에 리턴한다.

8) MYSQL_FIELD_OFFSET mysql_field_seek(MYSQL* mysql, MYSQL_FIELD_OFFSET offset)
        임의의 필드에 접근을 하도록 한다.

9) MYSQL_FIELD_OFFSET mysql_field_tell(MYSQL_RES* result)
        현재 필드의 offset을 리턴한다.

10) void mysql_free_result(MYSQL_RES* result)
        result에 할당된 메모리를 해제한다.

11) MYSQL* mysql_init(MYSQL* mysql)
        mysql 객체를 초기화 한다. 인자가 NULL이면 새로운 MYSQL 객체를 생성하고, 초기화 하여 리턴한다.

12) MYSQL_RES* mysql_list_dbs(MYSQL* mysql, const char* wild)
        현재 서버에 있는 데이타베이스의 목록을 리턴한다. wild는 MySQL에서
        사용할 수 있는 정규식을 나타낸다.    
        result = mysql_list_dbs( &mysql,"%" )
        는 모든 데이타베이스를 리턴하는 예이다.(%는 '모든'을 나타낸다)

13) MYSQL_RES* mysql_list_tables(MYSQL* mysql, const char* wild)
        현재 데이타베이스에 있는 테이블들의 목록을 리턴한다.

14) unsigned int mysql_num_fields(MYSQL_RES*result) 혹은
    unsigned int mysql_num_fields(MYSQL* mysql)
 
    필드의 수를 리턴한다.

15) my_ulonglong mysql_num_rows(MYSQL_RES* result)
        result에 총 몇 개의 ROW가 있는지 리턴한다. query 수행 후
        mysql_store_result()를 호출하였을 경우에만 사용할 수 있고,  
        mysql_use_result()는 사용할 수 없다.

16) int mysql_ping(MYSQL* mysql) 
        서버에 연결 중인지를 리턴한다. 연결이 끊어 졌을 경우, 다시
        연결을 시도한다. 서버와 연결을 한 후 오랫동안 가만히 있으면
        서버가 연결을 끊어버리는데, 이런 경우에 사용한다.

17) int mysql_query(MYSQL* mysql, const char* query)
        query가 포인트 하는 쿼리를 수행한다. query의 끝은 NULL 문자이다.
        성공적으로 query를 수행하였으면 0을 리턴한다.

18) MYSQL* mysql_real_connect(MYSQL* mysql, const char* host, const char* user,
const char* passwd, const char* db, uint port, const char* unix_socket,
unit client_flag )
 
         host와의 연결을 시도한다.

19) int mysql_real_query(MYSQL* mysql, const char* query, unsigned int length)
         mysql_query()처럼 query를 수행하나, query의 끝이 legnth인 것이 다르다.

20) MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES* result) 
        현재 ROW의 offset을 리턴한다.

21) int mysql_select_db(MYSQL* mysql, const char* db)
        사용하고자 하는 database를 변경한다. mysql_query()를 이용하여 "use db이름"
        의 query를 수행해도 같은 결과를 얻는다.

22) int mysql_shutdown(MYSQL* mysql)
        서버를 종료시킨다. 현재 사용자에게 shutdown 권한이 있어야 한다.

23) MYSQL_RES* mysql_store_result(MYSQL* mysql)
        query의 수행 결과를 서버로부터 한 번에 모두 받아 온다.

24) MYSQL_RES* mysql_use_result(MYSQL* mysql)
        query의 수행 결과를 서버로부터 한 개의 ROW 씩 받아 온다.
   


간단한 예   
   
***********************************************************
1: #include <stdio.h>
2: #include <mysql.h>
3: #include <errno.h>
4:
5: void main(void)
6: {
7: MYSQL mysql ;
8: MYSQL_RES* res ;
9: MYSQL_ROW row ;
10: int fields ;
11:
12: mysql_init(&mysql) ;
13:
14: if(!mysql_real_connect(&mysql, NULL, "사용자","암호", "test" ,3306, (char *)NULL, 0))
15: {
16:     printf("%s\n",mysql_error(&mysql));
17:     exit(1) ;
18: }
19:
20: if(mysql_query(&mysql, "USE super") )
     // mysql_query()는 query 수행시에 에러가 나게 되면
     // 0이 아닌 값을 리턴한다.
     {
          printf("%s\n", mysql_error(&mysql) ;
          exit(1) ;
     }
21: if(mysql_query(&mysql, "SELECT * FROM dome") )
     {
          printf("%s\n", mysql_error(&mysql) ;
          exit(1) ;
     }
22:
23: res = mysql_store_result( &mysql ) ;
24: fields = mysql_num_fields(res) ;
25:
26: while( ( row = mysql_fetch_row( res ) ))
27: {
28:      for( cnt = 0 ; cnt < fields ; ++cnt)
29:      printf("%12s ", row[cnt]) ;
30:
31:      printf("\n") ;
32: }
33:
34: mysql_free_result( res ) ;
35: mysql_close(&mysql) ;
36: }

*****************************************************

#include <stdio.h>

void main()
{
     char str[] = "10.3454";         //string
     float a;

     sscanf(str, "%f", &a);         // string to float

     printf("string = %s\n", str);
     printf("converting float = %f\n", a);
}


쓰이는곳... 내가 못찾아서 그런거일지도 모르지만...
sql 쿼리에서 받는 값이 모두 string이라 float 값을 받아와도 string으로 리턴들어옴..

  1. Neon 2009.03.04 08:34

    man atof

+ Recent posts