0

昨日、次の挿入ソートを書きました (3 日前に C を学び始めました)。何らかの理由で、ソートは配列AT ALLを変更しません。

#include <stdio.h>
int *insert(int arr[], int index, int item);
int *isort(int arr[]);
int main() {
    int a[17] = {1, 2, 9, 5, 3, 2, 1, 6, 5, 9, 0, 1, 3, 4, 2, 3, 4};
    int *b = isort(a);
    for (int i = 0; i < 17; i += 1) {
        printf("%d ", b[i]);
    }
    return 0;
}
int *insert(int arr[], int index, int item) {
    --index;
    while (index >= 0 && item < arr[index]) {
        arr[index + 1] = arr[index];
        --index;
    }
    arr[index + 1] = item;
    return arr;
}
int *isort(int arr[]) {
    for (int i = 1; i < sizeof(arr) - 1; i++) {
        arr = insert(arr, i, arr[i]);
    }
    return arr;
}

非UNIXマシンであるlcc-winでコンパイラを実行しているので、コンパイラである可能性があると考えていますが、よくわかりません。ここで欠けている基本的なものはありますか?

4

2 に答える 2

3
int *isort(int arr[]) {
    for (int i = 1; i < sizeof(arr) - 1; i++) {
        arr = insert(arr, i, arr[i]);
    }
    return arr;
}

この関数sizeof(arr)では、配列のサイズではなく、ポインターのサイズを実際に返します。

C では、配列パラメーターが実際には対応するポインター型のパラメーターに調整されるという特別な規則があります。

あれは:

int *isort(int arr[]) { /* ... */ }

これと同等です:

int *isort(int *arr) { /* ... */ }

これを修正するには、配列のサイズを取る新しいパラメーターを関数に追加します。

int *isort(int arr[], size_t size) { /* ... */ }
于 2012-08-14T20:49:36.697 に答える
1

指摘されているように、最初の問題は、 isort 関数がポインタに対して sizeof 演算子を使用することです。C の配列の扱い方は、一見すると少し奇妙です。配列の名前は、その最初の要素へのポインターです。したがって、次のように isort を呼び出すと:

int *b = isort(a);

配列へのポインターをスタックにプッシュするだけです。isort の定義では、

int *isort(int arr[])

arr を int へのポインタとして宣言します

int *isort(int *arr)

この点で、C はさらに混乱します。

int *isort(int arr[17])

arr 変数は、依然としてint への単なるポインタです ... ここの「17」は破棄されます! この構文を使用しても、sizeof(arr) は引き続き int へのポインターのサイズになります。

32 ビット システム (ILP32) では、sizeof(arr) は常に 4 になりますが、配列が大きくなります。

したがって、配列のサイズを isort に渡す必要があります。これを行う一般的な方法は、次のようなマクロを定義することです。

#define NITEMS(arr) (sizeof(arr)/sizeof(arr[0]))

これは、任意のタイプの配列の要素数を計算します。

次の問題は、実際のエラーよりもスタイルの問題です。

arr = insert(arr, i, arr[i]);

これは、「arr」への参照を使用して挿入関数を呼び出します。この参照によって配列が変更され、その配列へのポインタが返されます。最初に送信したのと常に同じポインターになるため、この割り当ては実際には何も害を及ぼすことはありません。私が言うように、スタイルの問題であり、コード エラーではありません。

最後の問題は、1 から sizeof-1 になったため、(sizeof 問題を修正した後) isort 関数が 1 つ短く停止することです。修正版は次のとおりです。

#include <stdio.h>
#define NITEMS(arr) (sizeof(arr)/sizeof(arr[0]))

int *insert(int arr[], int index, int item);
int *isort(int arr[], size_t nitems);
int main() {
    int a[17] = {1, 2, 9, 5, 3, 2, 1, 6, 5, 9, 0, 1, 3, 4, 2, 3, 4};
    int *b = isort(a, NITEMS(a));
    for (int i = 0; i < NITEMS(a); i += 1) {
        printf("%d ", b[i]);
    }
    printf("\n");
    return 0;
}

int *insert(int arr[], int index, int item) {
    --index;
    while (index >= 0 && item < arr[index]) {
        arr[index + 1] = arr[index];
        --index;
    }
    arr[index + 1] = item;
    return arr;
}

int *isort(int arr[], size_t nitems) {
    for (int i = 1; i < nitems; i++) {
        insert(arr, i, arr[i]);
    }
    return arr;
}
于 2012-08-14T23:15:52.997 に答える