計算機科学のブログ

C - 高度な関数 - 関数を最大限に活用する - qsort関数, ポインターへのポインター, キャスト

Head First C ―頭とからだで覚えるCの基本David Griffiths(著)、 Dawn Griffiths(著)、 中田 秀基(監修)、 木下 哲也(翻訳)、 O’Reilly Media)の7章(高度な関数 - 関数を最大限に活用する)、p.329(長いエクササイズ)の解答を求めてみる。

Makefile

all: main.c
	cc main.c && ./a.out

コード

main.c

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

int scores[] = {543, 323, 32, 554, 11, 3, 112};
int scores_len = 7;
void print_scores(int scores[], int len)
{
    puts("scores");
    for (size_t i = 0; i < len; i++)
    {
        printf("%i, ", scores[i]);
    }
    puts("");
}
int compare_scores_desc(const void *score_a, const void *score_b)
{
    int a = *(int *)score_a;
    int b = *(int *)score_b;
    return b - a;
}
typedef struct
{
    int width;
    int height;
} rectangle;
int rect_area(rectangle *rect)
{
    return rect->width * rect->height;
}
void print_rect(rectangle *rect)
{
    printf("%i, %i\n", rect->width, rect->height);
}
void print_rects(rectangle rects[], int len)
{
    puts("rects");
    for (size_t i = 0; i < len; i++)
    {
        print_rect(&rects[i]);
    }
}
rectangle rects[] = {{543, 1}, {323, 1}, {32, 1}, {554, 1}, {11, 1}, {3, 1}, {112, 1}};
int rects_len = 7;

int compare_areas(const void *a, const void *b)
{
    rectangle *rect_a = (rectangle *)a;
    rectangle *rect_b = (rectangle *)b;
    int area_a = rect_area(rect_a);
    int area_b = rect_area(rect_b);
    return area_a - area_b;
}
char *names[] = {"e", "a", "d", "b", "c"};
int names_len = 5;
void print_names(char *names[], int len)
{
    puts("names");
    for (size_t i = 0; i < len; i++)
    {
        printf("%s, ", names[i]);
    }
    puts("");
}
int compare_names(const void *a, const void *b)
{
    char *name_a = *(char **)a;
    char *name_b = *(char **)b;
    return strcmp(name_a, name_b);
}
int compare_areas_desc(const void *a, const void *b)
{
    return -compare_areas(a, b);
}
int compare_names_desc(const void *a, const void *b)
{
    return -compare_names(a, b);
}
int main()
{
    print_scores(scores, scores_len);
    qsort(scores, scores_len, sizeof(int), compare_scores_desc);
    print_scores(scores, scores_len);
    print_rects(rects, rects_len);
    qsort(rects, rects_len, sizeof(rectangle), compare_areas);
    print_rects(rects, rects_len);
    print_names(names, names_len);
    qsort(names, names_len, sizeof(char *), compare_names);
    print_names(names, names_len);
    qsort(rects, rects_len, sizeof(rectangle), compare_areas_desc);
    print_rects(rects, rects_len);
    qsort(names, names_len, sizeof(char *), compare_names_desc);
    print_names(names, names_len);
}

入出力結果(Terminal, Zsh)

% make
cc main.c && ./a.out
scores
543, 323, 32, 554, 11, 3, 112, 
scores
554, 543, 323, 112, 32, 11, 3, 
rects
543, 1
323, 1
32, 1
554, 1
11, 1
3, 1
112, 1
rects
3, 1
11, 1
32, 1
112, 1
323, 1
543, 1
554, 1
names
e, a, d, b, c, 
names
a, b, c, d, e, 
rects
554, 1
543, 1
323, 1
112, 1
32, 1
11, 1
3, 1
names
e, d, c, b, a, 
%