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,
%