2

argv[1] から文字列を取得して、文字列を反転する単純な C プログラムを作成しています。コードは次のとおりです。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* flip_string(char *string){
    int i = strlen(string);
    int j = 0;

    // Doesn't really matter all I wanted was the same size string for temp.
    char* temp = string;
    puts("This is the original string");
    puts(string);
    puts("This is the \"temp\" string");
    puts(temp);

    for(i; i>=0; i--){
        temp[j] = string[i]
        if (j <= strlen(string)) {
            j++;
        }
    }

    return(temp);
}

int main(int argc, char *argv[]){
    puts(flip_string(argv[1]));
    printf("This is the end of the program\n");
}

基本的にはそれだけです。プログラムはコンパイルされますが、最後に一時文字列は返されません (空白のみ)。最初は、文字列と等しい場合に temp fine を出力します。さらに、for ループで temp の文字ごとに printf を実行すると、印刷された ie 文字列の正しい一時文字列が逆になります。標準出力に出力しようとすると( for ループの後またはメインで)何も起こらず、空白だけが出力されます。

ありがとう

4

3 に答える 3

3

あなたの関数は「インプレースリバーサル」を行うように見えます。つまり、メモリ内の指定された文字列を置き換えます。その際、末尾のゼロを前に移動しないように注意してください。関数の簡単な実装を次に示します。

#include <assert.h>
#include <string.h>

void flip_string(char *s)
{
    assert(s);
    char *t = strchr(s, '\0') - 1;
    for (; s < t; ++s, --t) {
        char tmp = *s;
        *s = *t;
        *t = tmp;
    }
}

この関数は、文字列を取得する (つまり、null ポインターではない) こと、およびメモリが書き込み可能であることをアサートします。t次に、文字列の最後の文字を指すポインタを設定します -strchr手動ループを書く代わりにこれを行うことにstrchrは、通常、高度に最適化された関数であるという利点があります。一度に 4 バイト以上。また、表現力も高いと言えます。

次に、メイン ループはsandによって参照される文字t(つまり、最初は最初と最後の文字) を交換し、ポインターが一致するまで前後に移動します。

sこの関数は、渡された元のポインターを保持する必要がなく、代わりに直接変更できるため、もう少し簡潔です。これは、関数がその引数を変更する、新しい値を返すかのいずれかを決定する必要がありますが、両方を決定する必要はありません両方を実行すると、次のように関数を呼び出すことができます

printf("%s", flip_string(s));

s...そして、これは実際に変更されていることを完全に覆い隠します。

flip_string(s);
printf("%s", s);

その点でより明確です。

于 2013-10-27T23:56:00.777 に答える
2

tempここでは、明らかに以外の変数になりたいと考えていますstring。ただし、行った初期化により、2 つのポインターが同じ場所を指すようになります。

代わりにすべきことは次のとおりです。

char *flip_string(const char *string)
{
    char *tmp = NULL;
    size_t len = strlen(string);
    int i = 0;
    /*
     * Don't forget that strlen() returns the length of the string
     * **WITHOUT** counting the ending '\0' character.
     * Thus, you have to add the extra space when you're allocating
     */
    if (!(tmp = malloc(len + 1))) {
        printf("Allocation failed ...\n");
        return NULL;
    }
    /*
     * The newly created string must have an ending character
     * Which is '\0'
     */

    tmp[len] = '\0';

    /*
     * Here, you want to reverse the "true content" of your string.
     * That is why you ignore the ending '\0' of the string by
     * setting the upper bound to strlen (with a strict '<') **AND**
     * it is also the reason a '- 1' just pops in the index choice.
     */
    for(i = 0; i < len; i++) {
        tmp[i] = string[len - i - 1];
    }
    return tmp;
}

WhozCraig によって強調されているように、メモリ割り当てを必要とせずに引数文字列を単純に変更する代替ソリューションがあります。

void flip_string(char *s)
{
    size_t len = strlen(s);
    char *p = s + len - 1;
    while (s < p) {
        *p ^= *s;
        *s ^= *p;
        *p ^= *s;
        p--;
        s++;
    }
}

XORスワップされた文字に一時ストレージ変数を使用しないようにするためのトリックに注意してください( ^is is the XORoperator in C )

于 2013-10-27T22:34:23.537 に答える