// bsearch de la biblioteca, y una versión propia con la misma firma.
#include <stdio.h>
#include <stdlib.h>

#define COUNT 5

typedef int (*Compare)(const void *, const void *);

typedef struct {
    int code;
    int grade;
} Student;

// El primer parámetro es la clave, y el segundo un elemento del arreglo.
int compare_code_with_student(const void *key, const void *element) {
    int code = *(const int *) key;
    const Student *student = element;
    return (code > student->code) - (code < student->code);
}

void *any_search(const void *key, const void *base, size_t count, size_t size, Compare compare) {
    const unsigned char *bytes = base;
    size_t low = 0;
    size_t high = count;
    while (low < high) {
        size_t middle = low + (high - low) / 2;
        const unsigned char *element = bytes + middle * size;
        int order = compare(key, element);
        if (order == 0) {
            return (void *) element;
        }
        if (order < 0) {
            high = middle;
        } else {
            low = middle + 1;
        }
    }
    return NULL;
}

void report(const Student *found, int code) {
    if (found == NULL) {
        printf("%d: no está\n", code);
    } else {
        printf("%d: nota %d\n", code, found->grade);
    }
}

int main(void) {
    // Ordenado por código: bsearch lo exige.
    Student students[COUNT] = {{1040, 14}, {1187, 17}, {1203, 9}, {1311, 12}, {1450, 20}};
    int wanted[2] = {1311, 1312};

    for (int i = 0; i < 2; i++) {
        const Student *from_library =
            bsearch(&wanted[i], students, COUNT, sizeof(students[0]), compare_code_with_student);
        const Student *from_ours =
            any_search(&wanted[i], students, COUNT, sizeof(students[0]), compare_code_with_student);
        report(from_library, wanted[i]);
        report(from_ours, wanted[i]);
    }
    return 0;
}
