0

Brian Kernighanの「C プログラミング言語演習 1-19の簡単な解決策を書きました。これは、文字列を逆にします。reverse(char[])機能は以下のとおりで、すべて問題ありません。

void reverse(char src[])
{   
    int len = 0;
    while( src[len] != '\0')
        len++;

    for(int i = 0; i < len/2; i++)
    {
        char temp = src[i];
        src[i] = src[len - 1 - i];
        src[len - 1 - i] = temp;
    }
}

ただし、while ループ内で後置インクリメント (++) 演算子を使用すると、関数は失敗します。

void reverse(char src[])
{   
    int len = 0;
    while( src[len++] != '\0')      // this fails
        ;

    for(int i = 0; i < len/2; i++)
    {
        char temp = src[i];
        src[i] = src[len - 1 - i];
        src[len - 1 - i] = temp;
    }
}

唯一の違いは、while ループ内で変数lenをインクリメントする代わりに、後置 ++ 演算子を使用したことです。これは、「インクリメントが終了したら、条件付きチェックに古い値を使用する」という動作が期待されるはずです。

期待どおりに動作しないのはなぜですか。どこが間違っているのですか? Windows 10 Mingw/gcc コンパイラーでコンパイルしています。これがテストコード全体です。

テストコード

#include <stdio.h>

#define STR_NUM     5
#define STR_SIZE    20

void reverse(char[]);   // declaration

int main()
{   
    char str[STR_NUM][STR_SIZE] =
    {
        { "A"     },
        { "AB"    },
        { "ABC"   },
        { "ABCD"  },
        { "ABCDE" }
    };

    for(int i = 0; i < STR_NUM; i++)
        reverse(str[i]);

    for(int i = 0; i < STR_NUM; i++)
        printf("%s\n", str[i]);

    return 0;
}

// this is working
void reverse(char src[])
{   
    int len = 0;
    while( src[len] != '\0')
        len++;

    for(int i = 0; i < len/2; i++)
    {
        char temp = src[i];
        src[i] = src[len - 1 - i];
        src[len - 1 - i] = temp;
    }
}

// this is failing
/*
void reverse(char src[])
{   
    int len = 0;
    while( src[len++] != '\0')      // this fails
        ;

    for(int i = 0; i < len/2; i++)
    {
        char temp = src[i];
        src[i] = src[len - 1 - i];
        src[len - 1 - i] = temp;
    }
}
*/
4

1 に答える 1

5

後置インクリメント演算子は、元の値を返し、1 ずつインクリメントします。

while( src[len] != '\0')
    len++;

作業バージョンでは、 while ループは がsrc[len]のときに終了し\0ます。while ループのテスト条件が失敗すると、ループ内のステートメントは実行されません。ループの後、次のlenような値が含まれますsrc[len] == '\0'

while (src[len++] != '\0');

変更されたバージョンでは、最終テストが実行さlenれると、さらに 1 回インクリメントされます。ループの後、配列の末尾を 1 つ過ぎlenた値が含まれます。src[len]

ただし、forループはそれlenが文字列の長さであると想定しているため、オフバイワンエラーが発生します。

于 2016-04-14T20:44:00.890 に答える