私のアプリケーションでは、構造体の配列を使用しており、配列を反復処理する必要があります。それを行う適切な方法は何ですか?アレイの最後に達したかどうかを確認するにはどうすればよいですか?
// structure
struct MyData {
int count;
char name[20];
float average;
}
私はこのように繰り返してみましたが、アプリケーションがクラッシュします:
struct MyData data[2] = { {3, "name1", 1.0}, {5, "name2", 2.5} };
struct MyData* ptr = data;
while (*ptr != NULL) {
// print the contents, works ok for 2 elements
ptr++; // increment the pointer
}
あなたの場合、_MyData[2]
_配列はメモリ内では次のようになります。
_| count | name | average | count | name | average |
^ -- your ptr points here
_
これは、サイズが3 * sizeof (struct MyData)
の単一の連続スペースです。
_ptr++
_操作を実行すると、ポインタは配列の次の構造に移動します。つまり、単一の_struct MyData
_のサイズが考慮されます。
_| count | name | average | count | name | average |
^ -- after ptr++ your ptr points here
_
別の_ptr++
_の後、ポインタはメモリを指します直後配列。
_| count | name | average | count | name | average |
^ -- another ptr++ and your ptr points here
_
ptr
ポインターを逆参照すると、まだ使用されていない、または割り当てられていないメモリにアクセスします。これは未定義の動作であり、アプリケーションがクラッシュするためです。
それを行うにはいくつかの方法があります。すべての方法がすべての場合に適用できるわけではないことに注意してください。
シンプル
多くの場合、私たちは単純に配列のサイズを知っています。その後、通常のfor
ループを使用して、コンテンツを反復処理できます。
_int len = 2;
struct MyData data[len] = { {3, "name1", 1.0}, {5, "name2", 2.5} };
struct MyData* ptr = data;
for (int i=0; i<2; i++, ptr++ ) {
// do your thing with the ptr
// and note that ptr gets increased inside for
}
_
sizeofを使用して配列の長さを決定する
_struct MyData data[2] = { {3, "name1", 1.0}, {5, "name2", 2.5} };
struct MyData* ptr = data;
struct MyData* endPtr = data + sizeof(data)/sizeof(data[0]);
while ( ptr < endPtr ){
// do your thing with the ptr
ptr++;
}
_
sizeof(data)/sizeof(data[0])
は、要素の量を計算します。配列の合計サイズを取得し、それを単一の要素のサイズで割ります。
この方法には欠点があります。配列がポインタとして宣言されている場合は使用できません!たとえば、配列をパラメータとして関数に渡すと、通常はポインタに変換されます。その後、配列のサイズを特定できません。
配列のサイズを制御できず、それを要求することさえできない場合は、MyData
の配列ではなくpointersからMyData
へ。その場合、NULL
値を持つガードを格納するには、配列を1スロット長くする必要があります。
イテレーションは、例として書いたイテレーションのようになります。
// N is the number of MyData instances you have
MyData* vData[N+1];
// vData[i] is filled, and vData[N] = NULL
// ...
MyData* vPtr = vData[0];
while(vPtr) {
// ...
}
ただし、これには配列のタイプをMyData[]
からMyData*[]
に変更することが含まれます。できない場合は、Dariuszの回答に従ってください。