Quick Reference
비교 함수는 앞이면 음수, 같으면 0, 뒤면 양수를 같은 기준으로 반환합니다. bsearch는 그 비교 함수로 이미 정렬된 배열에서만 사용합니다.
#include <stdlib.h>
int cmp_int(const void *a, const void *b) {
int ia = *(const int *)a;
int ib = *(const int *)b;
return (ia > ib) - (ia < ib);
}
int values[] = {42, 7, 19, 7};
size_t count = sizeof values / sizeof values[0];
qsort(values, count, sizeof values[0], cmp_int);
int key = 19;
int *found = bsearch(&key, values, count, sizeof values[0], cmp_int);qsort와 bsearch에는 같은 비교 함수를 넘깁니다. bsearch의 반환값은 찾지 못하면 NULL이고, 중복 값 중 어느 원소를 돌려줄지는 정해져 있지 않습니다.
문법
int arr[] = {5, 2, 8, 1, 9};
qsort(arr, 5, sizeof(arr[0]), cmp_int);각 인자의 의미는 이렇습니다.
- 배열 시작 주소
- 원소 개수
- 원소 하나의 크기
- 비교 함수
실전에서 자주 깨지는 부분은 sizeof(arr) 전체 바이트 수를 세 번째 인자로 넣는 실수입니다. 세 번째는 원소 하나의 크기입니다.
bsearch는 배열이 이미 같은 기준으로 정렬되어 있어야 합니다.
int key = 8;
int *found = bsearch(&key, arr, 5, sizeof(arr[0]), cmp_int);이 코드는 배열이 cmp_int 기준으로 이미 정렬돼 있을 때만 맞습니다.
qsort로 오름차순 정렬- 같은 비교 함수로
bsearch
정렬 기준과 검색 기준이 다르면 찾지 못해도 이상한 일이 아닙니다.
중복 원소가 있으면 bsearch는 일치한 원소 하나를 돌려줄 뿐, 첫 번째나 마지막 원소를 보장하지 않습니다. 그 위치가 중요하면 이진 탐색 범위를 직접 구현하거나, 정렬 뒤 인접 원소를 추가로 확인합니다.
비교 함수
typedef struct {
char name[32];
int score;
} Student;
int cmp_score_desc(const void *a, const void *b) {
const Student *sa = (const Student *)a;
const Student *sb = (const Student *)b;
return (sb->score > sa->score) - (sb->score < sa->score);
}구조체에서 중요한 것은 "무엇을 기준으로 정렬하느냐"를 카드 하나에 명확히 적는 것입니다.
- 점수 정렬
- 이름 정렬
- 날짜 정렬
기준이 달라지면 비교 함수도 달라집니다.
비교 함수는 같은 두 값에는 항상 0을, 같은 입력 쌍에는 같은 부호를 반환해야 합니다. 전역 상태나 시간에 따라 결과가 달라지는 비교 함수는 정렬과 검색의 전제를 깨뜨립니다.
빠른 점검
return ia - ib;로 비교해서 오버플로우bsearch전에 정렬하지 않음qsort와bsearch가 서로 다른 비교 함수를 씀- 원소 크기에
sizeof(arr)를 넣음 - 문자열 정렬에서
strcmp대신 주소 비교를 해버림
주의할 점
bsearch는 실패하면 NULL을 돌려주지만, 정렬되지 않은 배열에서는 "실패"가 아니라 "전제가 깨진 상태"입니다. 찾지 못했다고 바로 key가 없다고 단정하지 말고, 먼저 정렬 여부와 비교 함수 일치 여부를 확인하세요.
참고 링크
3 sources