C

続々・ C言語で文字列を逆にする

More than 3 years have passed since last update.


これまでのあらすじ

前々回の日記: Joel on Software を紙で読んでいた。その中の「ゲリラ的雇用面接のすすめ」にて出されていた試験例題「C言語の文字列をその場で逆にする」に挑戦した。

前回の日記:文字列長が INT 型の最大値に依存しなくなった。

今回の記事はその改善。


C 言語で文字列を逆にする


strrev.c

// 文字列を逆にする

// どうせなら string.h なしで
#include <stdio.h>

// 文字列を逆順にする
void strrev(char s[]){
char temp = '\0';
char *first = s;
char *last = s;

// 長さ0の文字列なら操作せず返す
if(*first == '\0'){ return; }

// 文字列の最後の文字のポインタを取得する
while( *(last+1) != '\0'){ last++; }

// 外側から逆にする
while(first < last){
temp = *first;
*first = *last;
*last = temp;

// 一つずつ範囲を小さくする
first++;
last--;
}
return;
}

// a.out の後に続く文字列を操作する
int main(int argc, char* argv[]){
char *s = argv[1];
// 引数が足りないなら比較しない
if(argc <= 1){ return 0; }

// 操作前
printf("Input: %s\n", s);
// 文字列を逆にする
strrev(s);
// 操作後
printf("Output: %s\n", s);
return 0;
}


実行結果はこちら

$ ./a.out a

Input: a
Output: a
$ ./a.out ab
Input: ab
Output: ba
$ ./a.out abc
Input: abc
Output: cba
$ ./a.out abcd
Input: abcd
Output: dcba
$ ./a.out what_a_wonderfull_world!
Input: what_a_wonderfull_world!
Output: !dlrow_llufrednow_a_tahw


前回からの改善点

ポインタ演算の比較を改善した。

完全一致を条件にするのではなく、大小を比較するようにした。

ポインタでもアドレスの大小を比較することはできる。同じ配列のどこかを指しているポインタ同士なら、その場所が配列上での前か後ろかで比較する。

(先頭からのオフセット値を比較している?)

とても基本的な改善。そもそも最初からこのように書いておけば、最初のバージョンのデバッグに30分近く取られることはなかった。

しかも当時、ぼんやりと、面倒くさいし == でいいや、とか考えていた気がする。

バグは油断したところにすかさず潜り込んでくる。

そんなことを感じました。おわり。

追記2014/07/12:

ループ途中の break 文を消した。動作は変わらず。

これもポインタでの大小比較ができるようになった恩恵。