7

プログラムの開始時に、charポインタの配列にメモリを割り当てます。

char **buffer = calloc( 20, sizeof(char *) );

次に、ユーザーは最大20語を入力できます。

buffer[i] = calloc( 40, sizeof(char) );
fgets( buffer[i], 40, stdin )`

その後、この配列を並べ替えたいと思います。スワップ関数を次のように使用すると、期待どおりに機能します。

void swap(char *args1, char *args2) {
    char tmp[40];
    strcpy( tmp, args1 );
    strcpy( args1, args2 );
    strcpy( args2, tmp );
}

void sort( char **args, int count ) {
    ...
    swap( args[i], args[j] );
    ...
}

これを検討した後、私がしなければならなかったのは実際にポインタを対応する文字列にリダイレクトすることだけだったので、これはCPUの無駄であることに気づきました。そこで、スワップ関数を書き直しました。

void swap(char **args1, char **args2) {
    char *tmp = *args1;
    *args1 = *args2;
    *args2 = tmp;
}

void sort( char **args, int count ) {
    ...
    swap( &args[i], &args[j] );
    ...
}

ただし、これはまったく機能せず、結果は非常に予想外であり、理由がわかりません(printf呼び出しなどをいくつか試しました)...ポインタがリダイレクトされてスワップされるだけで、メモリが見えると理解しました。このような:

(begin of char**):
100: *160
108: *200
116: *240
124: *280
...
(begin of char*):
160: Hello!\0
200: World!\0
...

私のアイデアは、CPUの労力を最小限に抑えるために、配列の代わりにポインターを変更することでした(ここでは、100のポインターを108のポインターと交換します)。

(begin of char**):
100: *200
108: *160
116: *240
124: *280
...
(begin of char*):
160: Hello!\0
200: World!\0
...

私はこれをできるだけ徹底的に説明しようとしました、そしてそれがあまりにも多くの説明であるならば申し訳ありません。誰かが私にこれについての洞察を与えて助けてくれるなら、私は最もうれしいです!

完全なコード(動作するstrcpyを含む)はここにあります:http://pastie.org/5361481

4

2 に答える 2

5

並べ替え関数は次のようになります。

void sort(char ** args, const int start, const int end) {
        char **pivot = &args[end];
        int i = start-1, j = start;
        while( j < end ) {
                int cmp = strcmp( *pivot, args[j] );
                if( cmp > 0 )
                        swap( &args[++i], &args[j] );
                j++;
        }
        swap( &args[++i], pivot );
        if( start + 1 < i )
                sort( args, start, i - 1 );
        if( end - 1 > i )
                sort( args, i + 1, end );
}

ピボットをにしたのではなくchar**、そのままにしておいたのではないかと思いますchar*。これを行うと、スワップを実行するたびに、実際には配列内の2つの要素をスワップするのではなく、配列の1つの要素をローカル変数とスワップします。ピボット変数は、最後の配列メンバーが別の文字列を指しているのではなく、別の文字列を指していることになります。

于 2012-11-11T17:56:10.353 に答える
3
    char *pivot = args[end];
...
    swap( &args[++i], &pivot );

これがあなたの問題です。ポインタをローカル変数と交換するのではなく、配列内の実際のピボット要素(つまり)と交換する必要がありますargs+endここでの実例

于 2012-11-11T18:05:43.753 に答える