'qsort 함수 사용법'에 해당되는 글 1건

  1. 2013.02.15 qsort 함수 사용법

qsort 함수 사용법

Programming/C 2013. 2. 15. 02:58 |

qsort 사용 예

 

실제 이것을 사용할 때는 이미 작성되어 라이브러리로 제공하는 함수를 사용하면 된다. 기본적인 리얼타임 라이브러리이다. 따라서 어떻게 호출하는가만 알면 사용은 쉽다.

 

qsort( (void *)데이터의 시작 주소, (size_t) 리스트의 갯수, 바꿀 데이터의 길이, 비교함수 );

 

데이터는 여러 변수의 형태를 사용할 수 있다. 따라서 소트의 길이 및 비교는 모두 다르다. 이것을 처리하기 위해 위와 같은 함수의 모양을 갖는다.

- 데이터의 시작 주소 : 데이터의 형태는 소트할 상황에 따라 다르므로 데이터가 존재하는 시작 주소를 넣으면 된다. int 일수도 있고, struct 일수도 있다. 따라서 이것은 void 포인트 변수로 타입 변환하여 넣어주면 된다.

- 리스트의 갯수 : 소트해야할 데이터의 갯수를 넣는다.

- 바꿀 데이터의 길이 : 데이터의 상황에 따라 변수의 형태와 길이가 다르므로 가급적 포인터등을 사용하려 교환하는 길이를 줄이는 것이 소트 시간을 단축할 수 있을 것이다.

- 비교함수 : 두 개의 데이터 엘리먼트를 비교하는 함수를 작성하고 함수 포인터로 넣어 주면, sort 과정 상 비교할 때 호출 된다. 이때 역시 데이터의 형태를 모르므로 void 포인터로 넘어 온다. 비교할 2개의 데이터의 위치를 포인터로 받는다.

 

#include <stdlib.h>
#include <string.h>
//#include <conio.h>

 

#include <stdio.h>

 

 

struct student {
    char name[20];
    char tel[20];
    char id[15];

    char stid[10];
    char part[20];
    char etc[100];
};

 

struct student gStudent[] = {
   { "홍길동", "010-3234-2344", "840305-1373848", "200341056", "전자공학과", "" },
   { "김홍영", "010-3344-2675", "840505-1365648", "200341057", "전자공학과", "" },
   { "박수만", "010-5234-4644", "840305-1453848", "200341066", "전자공학과", "" },
   { "송석만", "011-564-1345",  "640305-1375468", "200351056", "컴퓨터공학과", "" },
   { "전승혁", "010-3344-2334", "340305-1566648", "200351012", "컴퓨터공학과", "" },
   { "김만수", "016-764-5664",  "740311-1454568", "200351016", "컴퓨터공학과", "" },
};

 

struct student *gpStudent[] = {
    &gStudent[0],
    &gStudent[1],
    &gStudent[2],
    &gStudent[3],
    &gStudent[4],
    &gStudent[5]
};
 
#define SZ_STUDENT sizeof(gStudent)/sizeof(gStudent[0])
 
int compareName( const void *arg1, const void *arg2 )
{
   return strcmp( ((struct student *)arg1)->name, ((struct student *)arg2)->name);
}

 

int compareSiId( const void *arg1, const void *arg2 )
{
   return strcmp( (*(struct student **)arg1)->stid, (*(struct student **)arg2)->stid);
}


int main(int argc, char* argv[])
{

    qsort( (void *) &gStudent, (size_t)SZ_STUDENT, sizeof(struct student), compareName);

 

   int cnt;

    printf("구조체에서 이름으로...\n");
    for (cnt = 0;cnt < SZ_STUDENT;cnt++) {
        printf("[%s] %s - %s\n", gStudent[cnt].stid, gStudent[cnt].name, gStudent[cnt].tel );
    }
 
    printf("\n포인터에서 학번으로...\n");
    qsort( (void *) gpStudent, (size_t)SZ_STUDENT, sizeof(struct student*), compareSiId);

    for (cnt = 0;cnt < SZ_STUDENT;cnt++) {
       printf("[%s] %s - %s\n", gpStudent[cnt]->stid, gpStudent[cnt]->name, gpStudent[cnt]->tel );
    }

    //getch();
    return 0;
}


실행을 하면 :

구조체에서 이름으로...
[200351016] 김만수 - 016-764-5664
[200341057] 김홍영 - 010-3344-2675
[200341066] 박수만 - 010-5234-4644
[200351056] 송석만 - 011-564-1345
[200351012] 전승혁 - 010-3344-2334
[200341056] 홍길동 - 010-3234-2344

 

포인터에서 학번으로...
[200341056] 홍길동 - 010-3234-2344
[200341057] 김홍영 - 010-3344-2675
[200341066] 박수만 - 010-5234-4644
[200351012] 전승혁 - 010-3344-2334
[200351016] 김만수 - 016-764-5664
[200351056] 송석만 - 011-564-1345

 

 

이 프로그램에서 쏘트의 방법상 다음 2가지 방법을 생각해 본다.

 

(1) qsort( (void *) &gStudent, (size_t)SZ_STUDENT, sizeof(struct student), compareName);

(2) qsort( (void *) gpStudent, (size_t)SZ_STUDENT, sizeof(struct student*), compareSiId);

 

1번은 struct 전부를 바꾸어야 하고

2번은 struct 포인터만을 바꾼다.

 

이렇게 되면 2가지의 쏘트에서 실행 시간이 다르게 된다. 비교 후 데이터의 교환 조건이 되면 교환을 수행할 때

- 1번 : struct의 전 사이즈를 수행 한다. 따라서 sizeof(struct student) 바이트 수 만큼 교환 된다. 

- 2번 : 단순히 포인터 4바이트(32비트 CPU에서)만을 바꾸면 끝이다.

따라서 데이터 교환을 줄이려면 이런 경우 포인터가 유용하다.

 

 

프로그램 예


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

char *msg[] = {
    "Hello",
    "홍길동",
    "우리집에",
    "computer",
    "TV",
    "12345"
};
 
int compareAlpha( const void *arg1, const void *arg2 );
int compareLength( const void *arg1, const void *arg2 );

void printList(char **msg, int szlist);

 

int main(int argc, char* argv[])
{
   int szlist;

     szlist = sizeof(msg) / sizeof(msg[0]);

     printf("원래 리스트...\n");
     printList(msg, szlist);
 
  // 알파벳 순서 소트
     qsort( (void *)msg, (size_t)szlist, sizeof( char * ), compareAlpha );

     printf("\n알파벳 순서 소트 결과...\n");
     printList(msg, szlist);

  // 문자의 길이 순서 소트
     qsort( (void *)msg, (size_t)szlist, sizeof( char * ), compareLength );

     printf("\n문자의 길이 순서 소트 결과...\n");
     printList(msg, szlist);

 

     getch();
     return 0;
}

void printList(char **msg, int szlist)
{
   int cnt;

     for (cnt = 0;cnt < szlist;cnt++)
          printf("[%d] %s\n", cnt+1, msg[cnt]);
}

// 알파벳 순서 비교
int compareAlpha( const void *arg1, const void *arg2 )
{
   return _stricmp( * ( char** ) arg1, * ( char** ) arg2 );
}

// 문자의 길이 비교
int compareLength( const void *arg1, const void *arg2 )
{
   return strlen( *( char** ) arg1) - strlen ( *( char** ) arg2 );
}

 

 

결과 :

 

원래 리스트...
[1] Hello
[2] 홍길동
[3] 우리집에
[4] computer
[5] TV
[6] 12345

 

알파벳 순서 소트 결과...
[1] 12345
[2] computer
[3] Hello
[4] TV
[5] 우리집에
[6] 홍길동

 

문자의 길이 순서 소트 결과...
[1] TV
[2] Hello
[3] 12345
[4] 홍길동
[5] 우리집에
[6] computer

 


올림순, 내림순하는 경우의 비교는 다음과 같은 비교함수를 바꾸면 된다.



// 알파벳 순서 비교
int compareAlpha2( const void *arg1, const void *arg2 )
{
   return _stricmp( * ( char** ) arg2, * ( char** ) arg1 );
}


[1] 홍길동
[2] 우리집에
[3] TV
[4] Hello
[5] computer
[6] 12345



// 문자의 길이 비교
int compareLength2( const void *arg1, const void *arg2 )
{
   return strlen( *( char** ) arg2) - strlen ( *( char** ) arg1 );
}


[1] computer
[2] 우리집에
[3] 홍길동
[4] Hello
[5] 12345
[6] TV

 

 

Linux에서 예

Linux man page
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>

static int
cmpstringp(const void *p1, const void *p2)
{
    /* The actual arguments to this function are "pointers to
       pointers to char", but strcmp() arguments are "pointers
       to char", hence the following cast plus dereference */

   return strcmp(* (char * const *) p1, * (char * const *) p2);
}

int
main(int argc, char *argv[])
{
    int j;

   assert(argc > 1);

   qsort(&argv[1], argc - 1, sizeof(char *), cmpstringp);

   for (j = 1; j < argc; j++)
        puts(argv[j]);
    exit(EXIT_SUCCESS);
}


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

bsearch 함수 사용법.  (0) 2013.02.15
assert 문 사용하기  (0) 2013.02.15
qsort (Quick Sort) 함수.  (0) 2013.02.15
atexit 함수, exit 함수, abort 함수  (2) 2013.02.15
함수 포인터를 반환하는 함수의 정의  (0) 2013.02.15
Posted by scii
: