qsort함수 질문 드리겠습니다.
진솔
질문 제목 : 표준 라이브러리에서 제공하는 qsort함수에 대해서 질문드립니다.다음의 소스코드는qsort함수를 이용해서 학번 순으로 정렬하였습니다.
qsort함수에서qsort( (void *)student_arr, (size_t)10, sizeof(student), compare); 이렇게 구조체 자체로 들어가는데
사실 제 생각에는 id를 비교(student_arr[0].id)해야하는데 왜 구조체 자체로서 시작 주소를 넘겨 받아야 정렬이 되는지 이해가 잘 되지 않습니다.
또한 만약 이 코드를 중심으로 성적 순으로 할려면 저부분에 어떤식으로 코드를 넣어야할까요?
질문 내용 :
/*학생 20명의 자료를 아래의 구조체를 이용하여 입력하고,
학번 순으로 정렬하고 임의의 학번을 입력하여 학번, 이름, 성적을 출력하시오.typedef struct score_tag{
char title[32]; // 과목
char qpa[3]; //점수
}score; //학생 점수typedef struct student_tag{
int id; // 아이디
char name[64]; //이름
score score[2]; // 점수 구조체 변수
}student;교재 377~378 쪽에 설명된 c언어 라이브러리qsort(void *base, size_tnum, size_twidth, int(*compare)(const void *, const void*));
int compare(const void *left, const void *rite);를 이용하라.*/#include stdio.h
#include stdlib.h
#include string.htypedef struct score_tag{
char title[32]; // 과목
char qpa[3]; //점수
}score; //학생 점수typedef struct student_tag{
int id; // 아이디
char name[64]; //이름
score score[2]; // 점수 구조체 변수
}student;//void qsort(void *base, size_t num, size_t width, int(*compare)(const void *, const void*));
int compare( const void *left, const void *right );void main()
{
int i,n;
//double list[5]={3.4,2.3,4.3,2.2,2.0}; // 퀵정렬 예제
student student_arr[10]={ // 초기화
{2011154057, 홍길동,{ {미술의이해,100}, {사람과 이해,90} }},
{2011154158, 김홍영,{{미술감상법,100}, {음악의이해,50}}},
{2011154029, 오길동,{{음악의이해,50}, {사진의이해,80}}},
{2011154040, 팔만두,{{음악감상법,70}, {음악의이해,70}}},
{2011154031, 김민수,{{사진의이해,80}, {음악의이해,70}}},
{2011154112, 고만수,{{컴퓨터의이해,55}, {음악의이해,70}}},
{2011154013, 네네네,{{화학의이해,77}, {음악의이해,70}}},
{2011154064, 크크크,{{생물학의이해,74}, {음악의이해,70}}},
{2011154015, 헤헤헤,{{물리의이해,56}, {음악의이해,70}}},
{2011154086, 테스트,{{전기의이해,59}, {음악의이해,70}}},
}; for(i=0;i10;i++)
{
for(n=0;n2;n++)
{
printf(%d %s , student_arr[i].id,student_arr[i].name); // 구조체 출력
printf(%s %d\n, student_arr[i].score[n].title, student_arr[i].score[n].qpa[0]); // 점수 출력
}
}
printf(\n------------밑에서 부터 학번 순으로 정렬된 학생 정보입니다.---------------\n);
//qsort( (void *)list, (size_t)5, sizeof(student), compare); // 퀵정렬 예제 qsort( (void *)student_arr, (size_t)10, sizeof(student), compare); for(i=0;i10;i++)
{
for(n=0;n2;n++)
{
printf(%d %s , student_arr[i].id,student_arr[i].name); // 구조체 출력
printf(%s %d\n, student_arr[i].score[n].title, student_arr[i].score[n].qpa[0]); // 점수 출력
}
} //for(i=0;i5;i++) printf(%.1f , list[i]);}
int compare( const void *left, const void *right )
{
if ( *(int *)left *(int *)right ) return 1;
else if ( *(int *)left == *(int *)right ) return 0;
else return -1;
}
/* qsort( (void *)데이터의 시작 주소, (size_t) 리스트의 갯수, 바꿀 데이터의 길이, 비교함수 );
데이터는 여러 변수의 형태를 사용할 수 있다. 따라서 소트의 길이 및 비교는 모두 다르다. 이것을 처리하기 위해 위와 같은 함수의 모양을 갖는다.
- 데이터의 시작 주소 : 데이터의 형태는 소트할 상황에 따라 다르므로 데이터가 존재하는 시작 주소를 넣으면 된다.
int 일수도 있고, struct 일수도 있다. 따라서 이것은 void 포인트 변수로 타입 변환하여 넣어주면 된다.
- 리스트의 갯수 : 소트해야할 데이터의 갯수를 넣는다.
- 바꿀 데이터의 길이 : 데이터의 상황에 따라 변수의 형태와 길이가 다르므로 가급적 포인터등을 사용하려 교환하는 길이를 줄이는 것이 소트 시간을 단축할 수 있을 것이다.
- 비교함수 : 두 개의 데이터 엘리먼트를 비교하는 함수를 작성하고 함수 포인터로 넣어 주면, sort 과정 상 비교할 때 호출 된다. 이때 역시 데이터의 형태를 모르므로 void 포인터로 넘어 온다. 비교할 2개의 데이터의 위치를 포인터로 받는다.
*/
-
천칭자리
아 그렇군요 자세한 설명까지 더해주셔서 감사합니다!! 정말 도움이 많이 되었어요
-
소아
다행히 Student 구조체 맨위가 int형의 id라서 인자로 들어온 포인트를 int* 로 형변환을 하면 id값이 나와서 정상적으로 비교가 수행되었습니다. 하지만 저런 사용법은 추천드리고 싶지 않습니다.
compare함수를 이렇게 바꿔도 위 소스랑 똑같이 작동될겁니다.
return (Student *)left-id - (Student *)right-id;
이정도면 이제 점수크기로 정렬하는 방법도 쉽게 알 수 있을겁니다. -
혁민
qsort함수 관점에서 보자면 주어진 자료형의 크기와 배열크기를 모르고 있습니다. 따라서 어느 자료형의 배열이 있을 경우, 그 배열의 시작주소와 자료형의 크기, 배열의 크기를 인자로 받아야 모든 배열의 원소에 접근을 할수 있습니다. 사실 이부분을 이해하실려면 포인터를 좀더 공부하셔야 할겁니다.
qsort는 자료를 비교하기위해 맨 마지막 인자로 int(void*, void*)형의 함수의 이름을 받습니다. 그러면 내부에서 비교를 할 때 비교함수에 각 배열
번호 | 제 목 | 글쓴이 | 날짜 |
---|---|---|---|
2695626 | 피보나치수열 과제 때문에 질문 드립니다. (6) | 옆집언니 | 2025-05-22 |
2695595 | 포인트공부중입니다 int형에서 4=1 인가요? (3) | 족장 | 2025-05-22 |
2695567 | 드라이브 고유번호를 가져오는 함수 (2) | 초코맛사탕 | 2025-05-21 |
2695533 | 음수의 산술변환! 질문이요 ㅠㅠ... (4) | 꽃여름 | 2025-05-21 |
2695506 | 구조체 배열 이용 도서목록 출력 프로그램 (1) | 가을귀 | 2025-05-21 |
2695450 | c언어 함수 질문이요.... | 이슬비 | 2025-05-20 |
2695403 | VirtualAlloc함수 및 메모리 질문 | 크리에이터 | 2025-05-20 |
2695355 | c언어 for함수 | 미쿡 | 2025-05-19 |
2695327 | 안녕하세요 제가 이번에 좀 큰 프로그램을.. | 악당 | 2025-05-19 |
2695295 | mutex동기화의 thread기반 채팅 서버소스 질문입니다 | 그루터기 | 2025-05-19 |
2695270 | 질문이요..swap 관한겁니다..ㅠㅠ (3) | 콩알녀 | 2025-05-19 |
2695244 | 노땅초보궁금한게 하나 있는데요..반복문(while문)초보자질문 (6) | 큰꽃늘 | 2025-05-18 |
2695166 | do while 문 어떤것이잘못된건지 모르겠어요 (2) | 아이폰 | 2025-05-18 |
2695122 | 구조체에 대해 물어보고 싶은게 있습니다 ^^^.. (7) | 수련 | 2025-05-17 |
2695091 | txt 파일 입출력 후 2차 배열에 저장하기입니다. (3) | 헛장사 | 2025-05-17 |
2695063 | 수도요금 프로그램좀 짜주세요. | 시내 | 2025-05-17 |
2695033 | 답변좀요ㅠㅠ (1) | 비사벌 | 2025-05-16 |
2695010 | C++의 STL은 왜 굳이 템플릿화 시켜서 라이브러리를 만드나요? (초보수준의 질문..) (2) | 엘보어 | 2025-05-16 |
2694958 | 로직이 변한다는 것에 대해서 궁금합니다. | 튼동 | 2025-05-16 |
2694929 | 열혈강의 25-2 두번째 문제 질문 | 지우개 | 2025-05-15 |