0

これは私のコンウェイのライフゲームCコードです。

関数newgenは、セルがマトリックスの端にある場合でも、隣接するセル(8つすべて)をチェックします。バインドされていないデータへのアクセスや未定義の動作が発生しないように変更するにはどうすればよいですか?

また、私はこのエラーがあります:

1   IntelliSense: a value of type "void *" cannot be assigned to an entity of type "int *"  

コードは次のとおりです。

void copy() {
  int i, j;
  for (i = j = 0; i < HEIGHT; i++) {
    for (; j < WIDTH; j++) {
      gb2[i][j] = gb[i][j];
    }
  }
}

void init() {
  int i, j;
  for (i = 0; i < HEIGHT; i++) {
    gb [i] = malloc(sizeof(int)*WIDTH);
    gb2[i] = malloc(sizeof(int)*WIDTH);
  }
  for (i = 0 ; i < HEIGHT; i++) {
    for (j = 0 ; j < WIDTH; j++) {
      gb [i][j] = 0;
    }
  }
  gb[0][0] = 1;
  gb[0][1] = 1;
  gb[1][0] = 1;
  gb[1][1] = 1;
  copy();
}

... int main(){int i; 初期化(); newgen(); printg(); for(i = 0; i <HEIGHT; i ++){free(gb [i]); free(gb2 [i]); }}

4

3 に答える 3

1

行に対してはnewgen()1 から HEIGHT - 2 までループし、境界外アクセスを回避しますが、列に対しては 0 から WIDTH - 2 までループするため、j - 1 にアクセスするすべての行で境界外アクセスが可能になります。あなたは最初の列にいます。つまり、

for (j = 0; j < WIDTH-1; j++) {
   if (gb[i][j+1]) n++;
   if (gb[i+1][j]) n++;
   if (gb[i+1][j+1]) n++;
   if (gb[i-1][j-1]) n++; // <- Here,
   if (gb[i][j-1]) n++;   // <- here,
   if (gb[i-1][j]) n++;
   if (gb[i+1][j-1]) n++; // <- ...and here.
   if (gb[i-1][j+1]) n++; 

列のループを開始するときは、0 ではなく 1 に等しい j から始めます。

for (j = 1; j < WIDTH-1; j++) { 
于 2012-01-21T14:11:45.360 に答える
0

以下のコードはテストしていません(とにかく不完全です)が、配列内のすべての要素をループして、ネイバーカウントを更新する必要があります。隣接するすべてのセルを実行し、境界チェックを実行するループをいくつか使用できます。

また、各セルの処理を開始するときに、隣接セルの数をリセットする必要があります。

void newgen()
{
    for (int i = 0; i < HEIGHT; i++)
    {
        for (int j = 0; j < WIDTH; j++)
        {
            int n = 0;

            for (int test_y = i - 1; test_y <= (i + 1); ++test_y)
            {
                for (int test_x = j - 1; test_x <= (j + 1); ++test_x)
                {
                    if ((test_x != test_y) &&
                        (test_x >= 0) && (test_x < WIDTH) &&
                        (test_y >= 0) && (test_y < HEIGHT))
                    {
                        if (gb[test_y][test_x])
                        {
                            n++;
                        }
                    }
                }
            }

            /* Process the n value here */
        }
    }
}

おそらく、1つの次元に沿って割り当てる代わりに静的配列を使用するか、両方の次元に沿って割り当てることができます。現在、静的サイズと動的サイズが混在しているため、問題はなく、一貫性がないように見えます。

Intellisenseエラーは、IntellisenseがCコードではなく、C ++コードのみを処理するように聞こえますが、それは推測にすぎません。CまたはC++としてコンパイルするようにコンパイラー(ここではMSVCを想定しています)を構成できますが、Intellisenseにそのオプションがないか、個別に構成されている可能性があります。

于 2012-01-21T14:32:28.090 に答える
0

IntelliSenseの警告は、Visual C ++を使用しているためであり、警告はC++で適切です。(Cを使用している場合は、それほど「インテリジェント」ではありません。)Cでは戻り値をキャストすることはお勧めしませんが、の戻り値をキャストすることで警告回避できmallocます。(int *)malloc

範囲外アクセスの回避について:範囲外にアクセスしないでください。考えられる解決策は次のとおりです。

  • 単一セルのライブ/デッド値を返す関数を作成し、そこで境界を確認し、範囲外の場合は0を返します。(または、グリッドを反対側にラップすることもできます。これは、小さなグリッド上のグライダーなどをアニメートする場合に便利です。)

  • ループに最初または最後の行または列を含めないでください。代わりに、それらを特殊なケースとして扱い、境界を越えてアクセスしないでください。

  • 2つの追加の行と列を割り当て、それらをゼロに初期化してから、最後の行または列を反復処理しないでください(つまり、アクティブなグリッドを[1..w] [1..h]として扱い、w+2列を割り当てますおよびh+2行)。その場合、エッジに特別なケースは必要ありませんが、少量の追加メモリを使用します。

于 2012-01-21T14:33:12.623 に答える