検索用の文字列比較関数をリファクタリングしてたんです。
最初こんなんでした。
int compare(char *a, char *b) {
int length_a;
int length_b;
int min_length;
int i;
int result = 0;
length_a = strlen(a);
length_b = strlen(b);
min_length = min(length_a, length_b);
for (i = 0; i < min_length; i++) {
if (a[i] > b[i]) {
result = 1;
break;
} else if (a[i] < b[i]) {
result = -1;
break;
}
}
if (result == 0) {
if (length_a > length_b) {
result = 1;
}
}
return result;
}
なんか変なことやってるなーと思い、「要は文字列比較だろ?」っていうわけで以下のように『リファクタリング』しました。
int compare(char *a, char *b) {
int result = 0;
for (i = 0; ; i++) {
if (a[i] == '\0') {
if (b[i] == '\0') {
break;
} else {
result = -1;
break;
}
} else if ( b[i] == '\0') {
result = 1;
break;
} else if (a[i] > b[i]) {
result = 1;
break;
} else if (a[i] < b[i]) {
result = -1;
break;
}
}
return result;
}
うむ、合っているはずだ!というか、こんな比較関数を作るくらいならstrcmp使えって話なんだけど、そのときは気づかず。勝利を確信し動かしてみたらちゃんと動かねえ。CppUnitがFalseを出しまくりやがります。テストコードを見ると、なんとこの関数のテストコードがない。「いっけね、忘れてた」ってわけで早速テストコードを作成しテストしてみると、どうやらこの関数は正しく動いとる。むしろ元のコードは新しく作ったテストコードを通過しない。「このプログラムはバグの上に成り立っているのかぁ!?」と、ふとコメントを見ると
『前方一致に対応するためaの長さまでで比較する』
と書いてある。なにぃ!そうだったのか!つまり、a=”abc”, b=”abcde”の場合、0を返さないといけない。・・・ああ、だから最初あんな変なコードになっていたのか。というわけで最終的に下記のようになりました。
int compare(char *a, char *b) {
int result = 0;
for (i = 0; ; i++) {
if (a[i] == '\0') {
break;
} else if ( b[i] == '\0') {
result = 1;
break;
} else if (a[i] > b[i]) {
result = 1;
break;
} else if (a[i] < b[i]) {
result = -1;
break;
}
}
return result;
}
ちゃんと動いた。すごく微妙に早くもなった。CppUnitが役に立ったな。
以上