1

関数に次のコードがあります

char MenuOptions[7][200];
strcpy(MenuOptions[0], "Create New / Modify Existing Customer");
strcpy(MenuOptions[1], "Create New / Modify Existing Product");
strcpy(MenuOptions[2], "List All customers");
strcpy(MenuOptions[3], "List All Products");
strcpy(MenuOptions[4], "Batch Update of New Stock");
strcpy(MenuOptions[5], "Create Customer Order");
strcpy(MenuOptions[6], "View Last Order for Customer");
switch (displayMenu("Main Menu", MenuOptions, 7, TRUE)) {
etc....

char displayMenu(char *name, char *options[], int menuLength,
    enBoolean QuitEnabled) {

    int i;
    printf("%s: \n", name);
    for (i = 0; i < menuLength; i++) {
        printf("\t %d %s.\n", (i + 1), options[i]);
    }
    if (QuitEnabled == TRUE)
        printf("\t Q. Quit\n");
etc

ただし、displayMenuメソッドに入ると、MenuOptions配列がメモリから失われたように見えます。Eclipseの式ウィンドウでoptions[i]が何であるかを確認してみましたが、値として「範囲外」であると表示されます。

4

4 に答える 4

1

inの型はoptionsであるdisplayMenu必要がありますchar (*options)[200]。ありませんchar *options[]

のオペランドである場合を除きsizeofます。_Alignof、または単項&演算子、または宣言で配列を初期化するために使用されている文字列リテラルである場合、「 " の N 要素配列" 型のTは、" へのポインター " 型の式に変換 ("減衰") されますT。この場合、MenuOptionsは の 200 要素配列の 7 要素配列ですchar。上記の規則により、「の 200 要素配列へのポインター」型の式に減衰しますchar

書かれているように、の型optionschar **; の'番目の200 要素配列ではなく、配列のベースの後の' 番目のポインタをoptions[i]提供します。 icharichar

于 2012-12-10T19:16:25.493 に答える
1

何よりもまず、コンパイラで警告オプションをオンにします。コンパイラは、型の不一致があることを警告しているはずです。

MenuOptionsは 200 の 7 つの配列の配列ですchar。がdisplayMenu呼び出さMenuOptionsれ、パラメーターとして渡されるとMenuOptions、配列から 200 文字の 7 つの配列の最初の配列へのポインターに自動的に変換されます。

ではdisplayMenuoptionsパラメータは で宣言されchar *options[]ます。これは、optionsが へのポインタの配列であることを意味しcharます。関数パラメーターでは、[]は特別です。このパラメーターに配列が渡されることを示唆していますが、実際には配列は最初の引数のアドレスによって渡されます。したがって、この宣言は、optionsが へのいくつかのポインタのうちの最初のものへのポインタであることを示していcharます。

したがって、200 char の 7 つの配列の最初のポインターを渡していますが、関数は へのいくつかのポインターの最初のポインターを受け取ることを想定していますchar

これを修正する 1 つの方法は、 の宣言を に変更するoptionsことchar (*options)[200]です。これはoptions、200 文字の (最初の) 配列へのポインタであることを示しています。

これを修正するより良い方法は、MenuOptions を変更することです。

static const char *MenuOptions[] =
{
    "Create New / Modify Existing Customer",
    "Create New / Modify Existing Product",
    "List All customers",
    "List All Products",
    "Batch Update of New Stock",
    "Create Customer Order",
    "View Last Order for Customer",
};

(コンパイラが文字列をカウントするため、括弧内の「7」は必要ありません。)

options次に、追加したことを除いて、の宣言を変更する必要はありませんconst

char displayMenu(char *name, const char *options[], int menuLength,
    enBoolean QuitEnabled) {…

今:

  • MenuOptions文字列 (char の配列) への 7 つのポインターの配列です。文字列へのポインタへのポインタとして渡され、文字列へoptionsのポインタへのポインタであるため、型が一致します。
  • MenuOptions必要以上のスペースを取りません。以前は、文字列ごとに 200 文字で定義されていました。これで、各文字列は必要なだけのスペースしか占有しません (さらに末尾の null 文字とMenuOptions配列内の文字列へのポインター)。
  • const誤って文字列を変更しないようにするために追加されます。
  • MenuOptionsが宣言されstaticているため、コンパイル時に初期化され、実行時に文字列をコピーする必要はありません。

displayMenu最後に、呼び出しの「7」をに置き換えることができますsizeof MenuOptions / sizeof *MenuOptions。これにより、配列のサイズが配列の要素のサイズで除算され、配列内の要素の数が得られます。これは、ハードコーディングされた定数を変更せずに誰かが配列のサイズを変更する可能性を排除するため、定数をハードコーディングするよりも優先されます。

于 2012-12-10T19:20:16.513 に答える
0

1 つのオプション:

char displayMenu(char *name, char options[][200], int menuLength, enBoolean QuitEnabled) 
于 2012-12-10T19:17:17.800 に答える
0

入力タイプを変更します。

char displayMenu(char *name, char *options[], ...

それが多次元配列であることを反映するには:

char displayMenu(char *name, char options[][200], ...

動作するその他のオプション:

char displayMenu(char *name, char options[7][200], ...

char displayMenu(char *name, char (*options)[200], ...

要点は、多次元配列を渡す場合、最初の次元を超えるすべての次元も渡す必要があるということです。

于 2012-12-10T19:18:36.953 に答える