LoginSignup
5
4

More than 5 years have passed since last update.

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

Last updated at Posted at 2014-07-11

これまでのあらすじ

前々回の日記: 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 文を消した。動作は変わらず。
これもポインタでの大小比較ができるようになった恩恵。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4