C언어 mysql DB 데이터 구조체로 옮겨오기

harion01의 이미지

C mysql api 를 사용해서 DB의 데이터를 구조체로 옮겨오고는 작업중입니다.

C의 구조체는 mysql 의 테이블과 동일하며, 구조체의 멤버변수 이름들은 칼럼명과 같습니다.

mysql api 에서 제공하는 함수를 이용해서 칼럼명, row , 길이 등은 알수 있습니다.

칼럼명과 구조체 멤버변수가 같은점을 이용해서 데이터를 가져와서 자동으로 구조체로 저장하려합니다.

예를들어 table 사원 이고 칼럼이 이름, 주소 이면 구조체도 사원구조체에 이름, 주소 가 있는식입니다.

시도한 내용은 아래와 같습니다.

typedef struct _사원{
char 이름[100];
char 주소[100];
}사원;

#define POINTER(x,y) x->y

int DBtoSTRUCT( 사원 *sawon){

...
//mysql api 를 이용해서 calum_name 에 칼럼이름을, row 에 로우 데이터를 얻어온 상태입니다.
...

sprintf( POINTER(sawon, calum_name) , "%s" , row) ;

}

의도는 POINTER(sawon, calum_name) 부분이 define 을 거치면서 sprintf( sawon->이름 , "%s" , row ) 형태로 바뀌면서 이름에 row 를 저장하고,
calum_name 변경에 따라 sprintf( sawon->주소 , "%s", row) 형태로 인식해서 주소에 row 를 저장시키려 했습니다.

그런데 define 이 컴파일러에 인식되버리면서 컴파일 과정에서 calum_name 이 사원 구조체에 없다는 오류가 나버리더군요.

C에서 하나하나 변수이름을 입력하지 않고 가져온 데이터를 이용해서 구조체에 매핑시켜서 저장하는 방법이 없을까요?

raymundo의 이미지

이러면 어떨까요.

일단 구조체 자체도 동적으로 구성되진 않겠지요...? (그런 게 가능하기나 한 건지도 모르겠지만)

그러면 각 필드 변수들의 순서는 정해져 있을 거고, 각 필드가 구조체에서 차지하는 오프셋도 고정되어 있겠네요.
"이름"은 오프셋이 0이고, "주소"는 100 이고... 이것도 또 구조체의 필드 정렬을 위한 패딩도 신경써야겠습니다만.

그러면 이제 칼럼 이름과 오프셋을 매핑하는 함수를 만들 수 있겠네요.

offset("이름") => 0
offset("주소") => 100
등등.

offset()의 구현은... 스크립트언어의 hash나 dictionary 같은 식이니 그런 라이브러리를 쓰셔도 될 거고... 효율을 좀 떨어뜨려도 된다면 그냥 문자열의 배열과 int의 배열 두 개에 각각 이름과 오프셋을 같은 순서로 저장해놓고 문자열 배열에서 검색한 후 int 배열에서 값을 얻으면 되겠군요.

이제 calum_name 이 있으면 offset(calum_name)을 하면 오프셋이 나오고,

sprintf(
   (char *) ( (char *) sawon + offset(calum_name) ),   // 바깥쪽 캐스트는 없어도 될지도?
   "%s",
   row
);

이런 식으로 가능하지 않을까 싶은데요.

좋은 하루 되세요!

raymundo의 이미지

검색해보니, 패딩 등을 걱정하지 않고 각 멤버의 오프셋을 알 수 있는 offsetof() 매크로가 있더군요. 이것 역시 매크로라서 변수를 인자로 줄 수야 없습니다만, 그래도 일일이 오프셋 세어보며 검사하지 않고도 테이블을 만들어 둘 수 있겠네요.

그러면 offset()의 구현은, 미리 테이블을 만들어놓고

// 사원 구조체
typedef struct _member {
    char name[100];
    char addr[100];
} member;
 
#define NUM_FIELD 2  // 사원 구조체의 필드 갯수
struct {
    char *column;
    int  offset;
}
offset_table[NUM_FIELD] = {
    { "name",   offsetof( member, name ) },
    { "addr",   offsetof( member, addr ) }
};

offset()은 컬럼 이름을 인자로 받고 이 테이블의 각 원소를 검색해서 column 필드가 일치하면 그 원소의 offset 필드값을 반환하면 되겠네요.

좋은 하루 되세요!

harion01의 이미지

void * GetPointer(SAWON *sawon, char * column){

if (strcasecmp(column , "name") == 0) return POINTER(sawon,name);
if (strcasecpm(column , "addr") == 0) return POINTER(sawon, addr);
}

이런 함수를 만들어서 미리 포인터를 얻어서 데이터를 구조체에 넣고있습니다.

어느정도 하드코딩을 하긴해야되지만 뭐 일단 일처리를 해야되니 이정도에서 타협하고 나중에 좀더 연구해봐야겠네요.

답변 감사합니다.

raymundo의 이미지

음 생각해보니 결국 필드갯수만큼의 테이블을 코드에 나열해서 만드는 거나,
쓰신 것처럼 if 문을 쭈욱 나열하는 거나,
똑같지 싶습니다. ^^;

그럴 거면 그냥 쓰신 것처럼 하는게 제가 한 것처럼 오프셋 변환하고 난리치는 것보다 낫겠네요.

좋은 하루 되세요!

댓글 달기

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 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <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].
  • 사용할 수 있는 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>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <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].
  • You can use Textile markup to format text.
  • 사용할 수 있는 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>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <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].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 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>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.