1

我無法創建和訪問結構指針作爲數組。這是一個家庭作業問題,但這只是我對操作的誤解。在單獨的函數中創建指向數組的結構指針

我的頭文件(我不能改變,必須實現這樣)包含:

typedef struct gw_struct GW; 

extern GW *gw_build(int nrows, int ncols, int pop, int rnd); 

在實現文件我已經實現雙方的聲明

#include <stdio.h> 
#include "gw.h" 
#include <stdlib.h> 

struct gw_struct { 
    int Alive; 
    int row; 
    int column; 
    int id; 
}; 

GW *gw_build(int nrows, int ncols, int pop, int rnd){ 

    GW* list = NULL; 
    int rows = nrows; 
    int cols = ncols; 

    for(nrows = 0; nrows < rows; nrows++){ 
     for(ncols = 0; ncols < cols; ncols++){ 
      GW *nn = malloc(sizeof *nn); 

      if (nn == NULL){ 
       break; 
      } 

      list = nn; 
     } 

    } 

    return list; 
} 

最後我測試文件包含:

#include <stdio.h> 
#include "gw.h" 
#include <stdlib.h> 

int main(){ 

    GW* World = gw_build(50, 50, 34, 1); 

    World[0][0] -> Alive = 2;   //Can't get this to work 
} 

最後,我編譯我的程序

gcc -c gw.c 
gcc gw.o main.c 

結構指針似乎被創建,但我不能像數組訪問它。

我試圖用多種方法解決這個問題。我本來初始化變量世界

GW* World[50][50] = gw_build(50,50,34,1); 

,我試圖與在gw_build功能「名單」同樣的事情,但它返回初始化錯誤。

去無環路,做

GW* list[nrows][ncols]; 

是不允許的,以及因爲你不能有一個變量作爲大小字段。

我可以創建,maloc,並在主函數本身,一切工作正常訪問

GW* World[50][50]; 

,但一旦我嘗試從gw_build函數返回來設置它,它根本不起作用。因此,我試圖改變返回類型,但再一次,它導致了無效的返回錯誤。

任何指導表示讚賞,謝謝!

回答

2

你偶然發現,你必須從一個簡單的1d陣列模擬一個2d陣列的挑戰。如果你看看你給出的函數聲明,你有GW *gw_build(...),它告訴gw_build將返回arraystruct 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_structgw.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 * nrowsj,僅僅是來自該地址的附加偏移。

您還可以選擇使用->運算符來引用上面顯示的單元格,或者您可以編寫一個等效表單,該表單使用.運算符作爲結構成員引用。替代方案如下所示:

#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語句來修正nrowsncols的例子。編譯和運行代碼,你會看到輸出:

$ ./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 
+0

這樣做是正確的,很好的方式是艱難的方式... ;-) – alk

+0

阿門...,但這樣做的硬道路可能就是這個狡猾的教授計劃 - 只是爲了鞏固一些基礎知識。 –

+0

絕對奇妙的答案。非常感謝! – mrybak3

0
extern GW *gw_build(int nrows, int ncols, int pop, int rnd); 

這意味着gw_build返回指向一維數組的指針。

什麼,你正在努力實現一個2維數組的是:

World[0][0] -> Alive = 2 

無論如何,初始化一個二維數組的方式是:

gw *world[r]; 
for (i=0; i<r; i++) 
world[i] = (int *)malloc(rowsize * sizeof(gw)); 
現在

,調用gw_build列次數,因爲gw_build只能返回一行。

for(i=0;i<row;i++) 
    world[i] = gw_build(); 
+0

所以,我認爲我的解決辦法是 更改我的結構,使其包含的只有一件事: 一個結構**的結構(這將作爲我的2D結構數組)? – mrybak3

+0

你想用它作爲2d數組或1d數組? – basav

+0

我需要將它用作[rows] [columns]的二維數組 – mrybak3

1

在引擎蓋下,二維數組只是一維數組。通過在引用元素時做一些數學運算,您可以將一維數組視爲二維數組。

退房這個帖子一些好的細節

Performance of 2-dimensional array vs 1-dimensional array

+0

我擔心我必須這樣做。這隻會讓事情變得更難以獲得。但是,謝謝,我會盡力實現這一點! – mrybak3

0

正如在他/她的answer創建者函數的定義允許指針返回只有一維數組basav指出。

您可以但是通過使用討厭的鑄造錘返回一個二維數組:

#include <stdio.h> 
#include <stdlib.h> 

struct gw_struct 
{ 
    int Alive; 
    int row; 
    int column; 
    int id; 
}; 

typedef struct gw_struct GW; 

#define ROWS 50 
#define COLS 50 

GW * gw_build(int nrows, int ncols, int pop, int rnd) 
{ 
    GW * pgw = malloc(nrows * ncols * sizeof *pgw); 

    /* To access the array members do: */ 
    { 
    GW (*world)[ncols] = (GW (*)[ncols]) pgw; /* "Dirty" casting here. */ 
    world[0][0].row = 0; 
    world[0][0].column = 0; 
    ... 
    } 

    return pgw; 
} 

int main(void) 
{ 
    GW (*world)[COLS] = (GW (*)[COLS]) gw_build(ROWS, COLS, 34, 1); /* "Dirty" casting here. */ 

    world[0][0].Alive = 2; 
    world[0][1].Alive = 2;   

    world[1][0].Alive = 2;   
    world[1][1].Alive = 2;   

    world[2][0].Alive = 2;   
    world[2][1].Alive = 2;   

    ... 

    free(world); 

    return 0; 
} 

的差異basav的解決方案是,你最終有一個線性陣列,這是所有元素被放置在一個內存塊中。

注意:要擺脫「骯髒」的鑄件,你可以使用另一個技巧,那就是引入一個臨時的void-指針。

這樣做替換這個由

GW (*world)[COLS] = NULL; 

    { 
    void * p = gw_build(ROWS, COLS, 34, 1); 
    world = p; 
    } 

最後說明

GW (*world)[COLS] = (GW (*)[COLS]) gw_build(ROWS, COLS, 34, 1); 

我看到前面是不是很好的技巧。不要在綠色領域這樣做。我剛纔展示瞭如何繞過規格。

相關問題