你偶然發現,你必須從一個簡單的1d
陣列模擬一個2d
陣列的挑戰。如果你看看你給出的函數聲明,你有GW *gw_build(...)
,它告訴gw_build
將返回array
的struct GW
。現在理想情況下,通過創建一個array of pointers to struct GW
可以使事情變得更簡單,但顯然,分配的一部分是讓您使用一個簡單的struct數組。
這簡化了分配,但使索引複雜化。意思是,你的gw_build
聲明可以簡單地是:
GW *gw_build(int nrows, int ncols, int pop, int rnd){
GW *list = calloc (nrows * ncols, sizeof *list);
if (!list) {
fprintf (stderr, "gw_build() error: virtual memory exhausted.\n");
return NULL;
}
return list;
}
但隨後的挑戰來自於填充和引用的每個,特別是如果你想有一個僞2D表示。這個任務實際上是理解指針和索引操作的練習。談論這件事的最好方法就是舉例。 (注:以下,我已經包括的gw_struct
在gw.h
申報,但如果你不能這樣做,只是把聲明中每一個源文件)
#ifndef _gw_header_
#define _gw_header_ 1
typedef struct gw_struct GW;
struct gw_struct {
int Alive;
int row;
int column;
int id;
};
extern GW *gw_build(int nrows, int ncols, int pop, int rnd);
#endif
的#ifdef _gw_header_
僅僅是一個例子控制頭文件包含。它確保gw.h
只包含一次。如果你不能添加到頭文件,你可以取消它。
源文件gw.c
只是需要分配nrows * ncols
結構,所以可以簡單:
#include <stdio.h>
#include <stdlib.h>
#include "gw.h"
GW *gw_build(int nrows, int ncols, int pop, int rnd){
GW *list = calloc (nrows * ncols, sizeof *list);
if (!list) {
fprintf (stderr, "gw_build() error: virtual memory exhausted.\n");
exit (EXIT_FAILURE);
}
return list;
}
兩個標準並沒有太多討論。真正的工作來自您的源文件,其中包含main()
,您將填寫並使用由gw_build
返回的數組。
#include <stdio.h>
#include "gw.h"
#define ROWS 10
#define COLS 10
int main (void) {
GW *world = gw_build (ROWS, COLS, 34, 1);
int i, j;
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++)
(world + i * ROWS + j)->Alive = (i*ROWS + j) % 3;
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++)
printf (" world[%2d][%2d] : %d\n", i, j, (world + i*ROWS + j)->Alive);
return 0;
}
(例如目的,我只是充滿Alive
具有取決於索引值0-2
之間的值)
當您收到分配的數組從gw_build
回你必須管理填充和offset
從使用數組的開始。您可以簡單地使用(0 < index < (nrows*ncols)
),但這會使用僞二維索引。技巧就是找到一種方法來使用二維數組語法來計算和引用每個偏移量。如果您在上面注意到,每個結構的偏移量可通過i * ROWS + j
訪問。這允許在場景i
後面的array[i][j]
的僞-2D參考代表i * nrows
和j
,僅僅是來自該地址的附加偏移。
您還可以選擇使用->
運算符來引用上面顯示的單元格,或者您可以編寫一個等效表單,該表單使用.
運算符作爲結構成員引用。替代方案如下所示:
#include <stdio.h>
#include "gw.h"
#define ROWS 10
#define COLS 10
int main (void) {
GW *world = gw_build (ROWS, COLS, 34, 1);
int i, j;
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++)
world[i * ROWS + j].Alive = (i * ROWS + j) % 3;
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++)
printf (" world[%2d][%2d] : %d\n", i, j, world[i * ROWS + j].Alive);
return 0;
}
查看兩者並讓我知道您是否有疑問。我已經使用了兩個#define
語句來修正nrows
和ncols
的例子。編譯和運行代碼,你會看到輸出:
$ ./bin/gwtest
world[ 0][ 0] : 0
world[ 0][ 1] : 1
world[ 0][ 2] : 2
world[ 0][ 3] : 0
world[ 0][ 4] : 1
world[ 0][ 5] : 2
world[ 0][ 6] : 0
world[ 0][ 7] : 1
world[ 0][ 8] : 2
world[ 0][ 9] : 0
world[ 1][ 0] : 1
world[ 1][ 1] : 2
world[ 1][ 2] : 0
world[ 1][ 3] : 1
world[ 1][ 4] : 2
world[ 1][ 5] : 0
world[ 1][ 6] : 1
world[ 1][ 7] : 2
world[ 1][ 8] : 0
world[ 1][ 9] : 1
world[ 2][ 0] : 2
...
world[ 8][ 8] : 1
world[ 8][ 9] : 2
world[ 9][ 0] : 0
world[ 9][ 1] : 1
world[ 9][ 2] : 2
world[ 9][ 3] : 0
world[ 9][ 4] : 1
world[ 9][ 5] : 2
world[ 9][ 6] : 0
world[ 9][ 7] : 1
world[ 9][ 8] : 2
world[ 9][ 9] : 0
這樣做是正確的,很好的方式是艱難的方式... ;-) – alk
阿門...,但這樣做的硬道路可能就是這個狡猾的教授計劃 - 只是爲了鞏固一些基礎知識。 –
絕對奇妙的答案。非常感謝! – mrybak3