設定 EYNY 為首頁  |  加入我的最愛
伊莉討論區
熱門搜尋: 海角七號  周杰倫  九降風  冏男孩  松島楓  波麗士大人  蒼井空  籃球火 


休閒聊天
學術文化
感情感性
興趣交流
家庭事務
旅遊交流
飲食交流
家族門派
貼圖分享
動漫交流
音樂世界
美容打扮
潮流資訊
影視娛樂
電玩遊戲
連線遊戲
網絡遊戲
交易廣場
下載分享
BT下載區
CB下載區
電腦資訊
數碼產品
手機交流
網站事務
體育運動
時事新聞
上班一族
博彩娛樂
成人話題


 
標題: [原創] 動態陣列配置
daviddr

Rank: 2Rank: 2
小學生(200/1000)
潛水  
UID 4114704
精華 0
積分 590
帖子 594
潛水 762 米
閱讀權限 20
註冊 2008-5-3
來自 Taiwan
發表於 2008-7-4 04:06 PM  資料 文集 短消息 
伊莉遊戲

動態陣列配置

[顯示] [隱藏]
好的 coder 總是有辦法以 1D array 來駕馭高維陣列操作,
但有時使用高維陣列,可讓 code 中的邏輯概念更加清晰。
早期的 C 或目前的 C++ 中,無動態陣列配置的語法,
(在 C99 中才有,例如 gcc 與 dev C++ 皆可編譯動態陣列)
因此需要自己實現,底下是我的簡單作法:

設計陣列配置時有 3 點需考量:

1. 配置效率: 最好只呼叫一次 malloc 或 new。
2. 存取效率: 存取速度必須逼近 primary array。
3. 語意: array 的記憶體必須連續分佈。
    (所以 vector< vector<T> > 不能算是真正的陣列,
     他只是 array container... )

N維動態陣列配置較複雜,先從二維的寫起 ^^;

(1) 使用 C 語言:


void** new_arr (int size, int x, int y)   //size = 元素大小
{   
    void** a=0; char* p;
    int sz = sizeof (void*);
    if (!(a= (void **) malloc (sz*x + size*x*y))) return 0;
    p = (char*)a + sz * x;
    while (x--) a[x] = p + size*x*y;         
    return a;
}

void del_arr (void** a)
{
    if (a) free (a);  
}

void set_arr (void** a, int size, int n, ...)
{
    va_list p;
    va_start (p, n);
    memcpy (a[0], p, size*n);
}

void main ()
{
    typedef struct {float f; char c;} CC;

    CC cc[4] = {0.2,'a', 0.4,'b', 0.6,'c', 0.8, 'd'};

    int   sz;
    int   **a;
    char* **b;
    CC    **c;
        
    a = (int**) new_arr (sz = sizeof(int), 2,4);
    set_arr ((void**)a, sz, 2*4,
        1,2,3,4,        //依序輸入資料
        7,8,9,0
    );   
    printf ("%d", a[1][2]);


    b = (char***) new_arr (sz = sizeof(char*), 2,2);
    set_arr ((void**)b, sz, 2*2,
        "陣列","2D",    //依序輸入資料
        "輸入","範例"
    );
    printf ("\n%s", b[0][1]);


    c = (CC**) new_arr (sz = sizeof(CC), 2,2);
    set_arr ((void**)c, sz, 2*2,
        cc[0], cc[1],    //依序輸入資料
        cc[2], cc[3]
    );
    printf ("\n%f %c", c[1][0].f, c[0][0].c);


    del_arr ((void**)a);
    del_arr ((void**)b);
    del_arr ((void**)c);
}


(2) 使用 C++:
[code]template <class T> struct Array
{
[ 瀏覽完整內容請先註冊或登入會員。]

頂部
badstyle319
(頹廢系好學生)

Rank: 2Rank: 2
小學生(200/1000)
潛水  
UID 1513027
精華 0
積分 222
帖子 193
潛水 3484 米
閱讀權限 20
註冊 2007-6-10
發表於 2008-7-5 06:58 AM  資料 文集 短消息 
伊莉部落格伊莉交友伊莉聊天伊莉相簿

值得參考的好文章要推一下...第一個難道是傳說中的...指標的指標...
感謝分享


不管男或女...
瀹落到網上推銷自己...
會是什麼好貨?
別傻了...zZZ

頂部
daviddr

Rank: 2Rank: 2
小學生(200/1000)
潛水  
UID 4114704
精華 0
積分 590
帖子 594
潛水 762 米
閱讀權限 20
註冊 2008-5-3
來自 Taiwan
發表於 2008-7-5 09:43 AM  資料 文集 短消息 
維克斯討論區

回復 #2 badstyle319 的帖子

> 第一個難道是傳說中的...指標的指標...
因為是二維的,故有兩顆星星 :-)

頂部
badstyle319
(頹廢系好學生)

Rank: 2Rank: 2
小學生(200/1000)
潛水  
UID 1513027
精華 0
積分 222
帖子 193
潛水 3484 米
閱讀權限 20
註冊 2007-6-10
發表於 2008-7-5 04:34 PM  資料 文集 短消息 
伊莉部落格伊莉交友伊莉聊天伊莉相簿

回復 #3 daviddr 的帖子

仔細研究一下大大的程式...不是很好懂耶...
居然還有***...這又是啥...
再請問del_arr function裡...
這樣做就能完全釋放出記憶體嗎...不會有memory leak的問題嗎
再再請問set_arr function裡...
第四個參數是什麼東西
最後能煩請大大放享2個程式的源碼嗎...因為我不知要include什麼東西XD


不管男或女...
瀹落到網上推銷自己...
會是什麼好貨?
別傻了...zZZ

頂部
daviddr

Rank: 2Rank: 2
小學生(200/1000)
潛水  
UID 4114704
精華 0
積分 590
帖子 594
潛水 762 米
閱讀權限 20
註冊 2008-5-3
來自 Taiwan
發表於 2008-7-5 04:54 PM  資料 文集 短消息 
伊莉部落格伊莉交友伊莉聊天伊莉相簿

依照相同概念,繼續擴展到 N 維:

C 語言寫法: (此 code 由曾侃的程式修改而來.)

[code]//---------------------------------------------------------
//  size = 元素大小, nDim = 維數, n,... = 各個維度
//  若配置失敗則傳回 0
//---------------------------------------------------------

void* new_arr (int size, int nDim, int n,...)  
{
    static int d[32];                               //限制最多到 32 維
    int i,j, nPtr, nElem, sz = sizeof (void*);      //指位器與元素數目
    void *a, **b, **c, **t; char *p;                //a = 動態陣列起始位址

    va_list v;
    va_start (v, nDim);
    for (i=nDim-1; i>=0; i--) d = va_arg(v,int); //讀取各個維數
    if (0 == nDim) return 0;                        //禁止配置 0 維陣列

    nPtr  = d[1];                                   //計算指位器表大小
    nElem = d[0]*d[1];                                 //與元素所佔之總空間   
    for (i=2; i<nDim; i++)++nPtr*=d, nElem*=d;
    a = malloc (nPtr*sz + nElem*size);              //配置動態陣列空間
    if (!a) return 0;                               //若配置失敗則傳回 0
        
    p = (char*)a + nPtr*sz;                         //p 指向實際儲存點的開頭位址
    b = (void**)p - (nElem /= d[0]);                //b 指向第 1D 指位器表的開頭
   
    c = b; i = nElem;                               //令 c 遍歷指位器表
    while (i--) { *c++ = p; p += d[0]*size; }       //設定 1D 指位器表的索引位址
    for (i=1; i<nDim-1; i++) {                      //設定 2~N 維指位器表的索引   
        t = b;                                      //t 指向欲被索引的指位器元素
        c = (b -= (nElem /= d));                 //令 c 遍歷 2~N 維指位器表
        for (j=0; j<nElem; j++) *c++ = t, t += d;               
    }   
    return a;
}

void del_arr (void* a)
{
    if (a) free (a);  
}

void main ()
{
    typedef int**** I4D;
    int i;
    I4D a = (I4D) new_arr (sizeof(I4D), 4, 2,3,4,5);
   
    for (i=0; i<2*3*4*5; i+ [ 瀏覽完整內容請先註冊或登入會員。]

頂部
 




當前時區 GMT+8, 現在時間是 2008-10-8 05:43 PM

    本论坛支付平台由支付宝提供
携手打造安全诚信的交易社区 Powered by Discuz! 5.0.0  © 2001-2006 Comsenz Inc.
Processed in 0.106420 second(s), 6 queries , Gzip enabled

清除 Cookies - 聯繫我們 - 廣告查詢 [威旭代理] - 伊莉討論區 - Archiver
重要聲明:本討論區是以即時上載留言的方式運作,伊莉討論區對所有留言的真實性、完整性及立場等,不負任何法律責任。而一切留言之言論只代表留言者個人意見,並非本網站之立場,用戶不應信賴內容,並應自行判斷內容之真實性。於有關情形下,用戶應尋求專業意見(如涉及醫療、法律或投資等問題)。 由於本討論區受到「即時上載留言」運作方式所規限,故不能完全監察所有留言,若讀者發現有留言出現問題,請聯絡我們。伊莉討論區有權刪除任何留言及拒絕任何人士上載留言,同時亦有不刪除留言的權利。切勿撰寫粗言穢語、誹謗、渲染色情暴力或人身攻擊的言論,敬請自律。本網站保留一切法律權利。