3

const charの配列の非常に単純な例と、それらを出力することになっている1つの関数があります(選択したものを繰り返し処理します)。私のすべての期待に反して、それは議論として渡されたものだけでなく、それらすべてを繰り返しています。

#include <iostream>

const char* oranges[] = {
    "ORANGE",
    "RED ORANGE"
};

const char* apples[] = {
    "APPLE"
};

const char* lemons[] = {
    "LEMON"
};

void printFruit(const char** fruit){
    int i =0;
    while (fruit[i] != '\0'){
        std::cout << "---------------------\n";
        std::cout << fruit[i] << "\n";
        i++;
    }
}

int main (int argc, const char * argv[])
{
   printFruit(oranges); 
   return 0;
}

私が期待する結果は、引数としてオレンジが指定された関数printFruitがORANGEとRED ORANGEを出力する一方で、次のように(他の配列から)定義されたすべてのフルーツを出力することです。

---------------------
ORANGE
---------------------
RED ORANGE
---------------------
APPLE
---------------------
LEMON

私の無知で申し訳ありませんが、なぜこれが起こっているのですか?

編集:私はこの質問に従いました:私のものと同様のcの文字列の配列を定義して反復します。

4

5 に答える 5

7

ここにUBがあります。あなたの状態

while (fruit[i] != '\0')

に等しい要素がないため、満たされることはありません\0

すべての配列は、メモリ内に次々と正確に配置されます。あなたiは永遠に増え続けます。あなたi = 1はの最初の文字列にいorangesます。i = 2あなたは2番目の要素にいます。

その後、i3になります。直後にoranges、あなたのマモリーにapples配列があるので、ポインターがそれを指し始め、アプリが印刷しAPPLEます。i = 4ポインタはlemons配列上にあり、アプリはを出力しますLEMONS。その後、あなたは事実上あなた自身の記憶から出て行き、それは私にとっては墜落をもたらします。

これを修正するには、各配列に空の要素を明示的に追加する必要があります。

const char* oranges[] = {
    "ORANGE",
    "RED ORANGE",
    0
};
于 2012-10-12T10:16:31.627 に答える
5

あなたはそれをチェックしていfruit[i] != '\0'ます。は文字ではなく、でfruit[i]あるため、これは間違っています。char *さらに、ベクトルは終了しません。fruit[i] != 0、、または。かどうかを確認したいと思うかもしれません*fruit[i] != '\0'。最初のケースでは、次のようにベクトルを終了する必要があります。

const char* oranges[] = {
    "ORANGE",
    "RED ORANGE",
    0  // or NULL
};

第二に:

const char* oranges[] = {
    "ORANGE",
    "RED ORANGE",
    ""
};
于 2012-10-12T10:15:29.737 に答える
2

私見、あなたはあなたが扱っている要素の数を正確に知っているほうがよいでしょう。悪いニュースは、文字ポインタの単純な配列では通知さstd::vectorれないため(ではない)、関数でそれを検出できないことprintFruitです。

ただし、良いニュースは、コンパイル時に利用できるため、それを見つけるためのオーバーヘッドについて心配する必要がないことです。以下は私が何を意味するかを示しています:

void printFruit(const char** fruit, int fruitSize){
    int i =0;
    while (i < fruitSize){
        std::cout << "---------------------\n";
        std::cout << fruit[i] << "\n";
        i++;
    }
}

int main (int argc, const char * argv[])
{
   // The second parameter can be worked out by the compiler.
   printFruit(oranges, sizeof(oranges)/sizeof(const char*) ); 
   return 0;
}

ただし、C ++を使用しvectorているので、境界チェックやメモリ割り当てなどの点ではるかに安全であるなど、標準のコレクションタイプの1つを使用することを強くお勧めします。

于 2012-10-12T10:32:04.793 に答える
1
const char* oranges[] = {
    "ORANGE",
    "RED ORANGE"
};

const char* apples[] = {
    "APPLE"
};

const char* lemons[] = {
    "LEMON"
};

メモリ内は次のようになります

"オレンジ""レッドオレンジ""アップル""レモン"

while (fruit[i] != '\0'){
    std::cout << "---------------------\n";
    std::cout << fruit[i] << "\n";
    i++;
}

「レモン」である「ビッグアレイ」の最後に到達すると終了します

コードを機能させるには、 "ORANGE" "RED ORANGE" 0 "APPLE" 0"LEMON"0のように見えるメモリが必要です。

   const char* oranges[] = {
        "ORANGE",
        "RED ORANGE",
    0
    };

    const char* apples[] = {
        "APPLE",
    0
    };

    const char* lemons[] = {
        "LEMON"
     ,0
    };
于 2012-10-12T10:18:15.007 に答える
0
const char* oranges[] = {
    "ORANGE",
    "RED ORANGE",
    "\0"
};

配列はメモリ内に次々に配置されているため、while条件がfalse

于 2012-10-12T10:14:29.743 に答える