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*)형의 함수의 이름을 받습니다. 그러면 내부에서 비교를 할 때 비교함수에 각 배열
번호 | 제 목 | 글쓴이 | 날짜 |
---|---|---|---|
2685726 | 메뉴 만드는 소스를 해보고있는데여.. (2) | 벛꽃잎 | 2025-02-21 |
2685640 | 어디가 잘못된지 모르겠네요;; | 희미한눈물 | 2025-02-20 |
2685554 | 열혈강의 TCP/IP 책 24페이지 소스 오류가 나네요 ㅠㅠ (6) | Elfin | 2025-02-19 |
2685477 | 소수점이하 출력하는거요 | 널위해 | 2025-02-18 |
2685449 | printf배우고있는데요 궁금한게있어요 (8) | 꽃큰 | 2025-02-18 |
2685393 | c언어 질문이요.... | 붕붕 | 2025-02-18 |
2685365 | 윈도우7에서 visual studio c++6.0 (1) | 빛길 | 2025-02-17 |
2685317 | segmentation fault가 나요 | 가람 | 2025-02-17 |
2685292 | 다중스택질문 | 올해1살 | 2025-02-17 |
2685231 | C언어와 닷넷에 대해서 질문!! (2) | 설아 | 2025-02-16 |
2685206 | VisualBasic 과 DEV++ 의 장단점과 만든 파일 호환 가능하나요? | 에드워드 | 2025-02-16 |
2685154 | 배열 크기조절 | 해찬솔 | 2025-02-15 |
2685124 | 수정이거 제가 뭐가 잘못한거죠 ? | 아이돌 | 2025-02-15 |
2685096 | 포인터의 고수분들 모두 보세요!! 제발 ㅠ_ㅠ 헷갈려헷갈려..갈려헷.. (7) | 치킨마루 | 2025-02-15 |
2685045 | 전처리기 질문 | 치에미 | 2025-02-14 |
2685016 | 오류 좀 확인해 주시면 감사하겠습니다 | 초코맛사탕 | 2025-02-14 |
2684917 | 알고리즘을 이용한 행렬의 전치// 문제다운 문제네요. | 뿡뿡 | 2025-02-13 |
2684868 | 양방향 연결리스트에서 실행도중 죽는 이유좀 찾아주세요. (2) | 예다움 | 2025-02-13 |
2684844 | 시계프로그램인데 도저히 모르겠어요ㅠ (1) | 비내리던날 | 2025-02-12 |
2684812 | 레포트좀도와주세요ㅠㅠ (2) | 갈매빛 | 2025-02-12 |