C語言 數組 列優先 實現

C語言數組結構列優先順序存儲的實現 (GCC編譯)。數組

從行優先轉換爲列優先存儲方式, 與行優先相比, 不一樣之處在於改變了數組維界基址的前後順序, 從而改變了映像函數常量基址。函數

  1 /**
  2 * @brief C語言 數組 列優先 實現
  3 * @author wid
  4 * @date 2013-11-02
  5 *
  6 * @note 若代碼存在 bug 或程序缺陷, 請留言反饋, 謝謝!
  7 */
  8 
  9 #include <stdio.h>
 10 #include <stdlib.h>
 11 #include <stdarg.h>
 12 #include <assert.h>
 13 
 14 #define OK 1
 15 #define ERROR -1
 16 
 17 #define MAX_DIM 8       ///容許的最大數組維數
 18 
 19 typedef int ElemType;
 20 
 21 typedef struct
 22 {
 23     ElemType *base;         ///數組元素基址
 24     int dim;                ///數組維數
 25     int *bounds;            ///數組維界基址
 26     int *constants;         ///數組映像函數常量基址
 27 }Array;     ///數組結構
 28 
 29 ///數組方法聲明
 30 int InitArray( Array *pArr, int nDim, ... );        ///初始化數組 pArr
 31 void DestroyArray( Array *pArr );                   ///銷燬數組 pArr
 32 int Locate( Array *pArr, int nDim, va_list ap );                     ///定位下標指向的元素在數組中的位置
 33 int Assign( Array *pArr, ElemType *elm, ... );      ///數組賦值
 34 int Value( Array *pArr, ElemType *elm, ... );       ///數組取值
 35 
 36 ///數組方法實現
 37 
 38 /**
 39 * @brief 初始化數組
 40 *
 41 * @param pArr 指向待初始化的數組
 42 * @param nDim 數組的維數
 43 * @param ... 數組各維數的長度
 44 *
 45 * @return 初始化成功返回OK, 不然返回ERROR
 46 */
 47 int InitArray( Array *pArr, int nDim, ... )
 48 {
 49     if( nDim < 1 || nDim > MAX_DIM )
 50         return ERROR;
 51 
 52     ///初始化 pArr 數組維數屬性
 53     pArr->dim = nDim;
 54 
 55     ///構造數組維界基址
 56     pArr->bounds = (int *)malloc( nDim * sizeof(int) );
 57     if( !pArr->bounds )
 58         return ERROR;
 59 
 60     int i = 0, nElemCount = 1;
 61     va_list ap;
 62     va_start( ap, nDim );
 63 
 64     /// i = nDim - 1, 使列優先
 65     for( i = nDim - 1; i >= 0; --i )
 66     {
 67         pArr->bounds[i] = va_arg( ap, int );
 68         if( pArr->bounds[i] < 0 )
 69             return ERROR;
 70 
 71         nElemCount *= pArr->bounds[i];
 72     }
 73     va_end(ap);
 74 
 75     ///初始化元素基址
 76     pArr->base = (ElemType *)malloc( nElemCount * sizeof(ElemType) );
 77     if( !pArr->base )
 78         return ERROR;
 79 
 80     ///初始化函數映像常數基址
 81     pArr->constants = (int *)malloc( nDim * sizeof(int) );
 82 
 83     ///遞推求常量基址, 列優先
 84     pArr->constants[nDim-1] = 1;
 85     for( i = nDim -2 ; i >= 0; --i )
 86     {
 87         pArr->constants[i] = pArr->bounds[i+1] * pArr->constants[i+1];
 88     }
 89 
 90     return OK;
 91 }
 92 
 93 /**
 94 * @brief 銷燬數組 pArr
 95 *
 96 * @param pArr 指向待銷燬的數組
 97 */
 98 void DestroyArray( Array *pArr )
 99 {
100     if( pArr->base )
101         free( pArr->base );
102 
103     if( pArr->bounds )
104         free( pArr->bounds );
105 
106     if( pArr->constants )
107         free( pArr->constants );
108 }
109 
110 /**
111 * @brief 定位數組下標指向的元素在數組中的位置
112 *
113 * @param 指向的數組
114 * @param ... 數組的下標
115 *
116 * @return 若下標合法, 返回下標在數組中的位置, 不然返回 ERROR
117 */
118 int Locate( Array *pArr, int nDim, va_list ap )
119 {
120     int nPos = 0, ind = 0, i = 0;
121 
122     ///列優先求地址
123     for( i = pArr->dim - 1; i >= 0; --i )
124     {
125         ind = va_arg( ap, int );
126 
127         ///使用斷言, 確保下標合法
128         assert( ind >= 0 && ind < pArr->bounds[i] );
129 
130         nPos += pArr->constants[i] * ind;
131     }
132     va_end(ap);
133 
134     return nPos;
135 }
136 
137 /**
138 * @brief 數組賦值
139 *
140 * @param pArr 指向待賦值的數組
141 * @param elm 指向賦值元素
142 * @param nDim 數組維數
143 * @param ... 數組下標
144 *
145 * @param 賦值成功返回 OK, 不然返回 ERROR
146 */
147 int Assign( Array *pArr, ElemType *elm, ... )
148 {
149     int nPos = 0;
150     va_list ap;
151     va_start( ap, elm );
152     nPos = Locate( pArr, pArr->dim, ap );
153     *(pArr->base + nPos) = *elm;
154 
155     return OK;
156 }
157 
158 /**
159 * @brief 數組取值
160 
161 */
162 int Value( Array *pArr, ElemType *elm, ... )
163 {
164     int nPos = 0;
165     va_list ap;
166     va_start( ap, elm );
167     nPos = Locate( pArr, pArr->dim, ap );
168     *elm = *(pArr->base + nPos);
169     printf( "addr = 0x%X\n", pArr->base + nPos );
170 
171     return OK;
172 }
173 
174 int main()
175 {
176     Array arr;
177 
178     ///初始化一個三維數組, 大小爲 2x3x5
179     InitArray( &arr, 3, 2, 3, 5 );
180 
181     int a = 0;
182     ///賦值測試
183     int i = 0, m = 0, n = 0;
184     for( i = 0; i < 2; ++i )
185         for( m = 0; m < 3; ++m )
186             for( n = 0; n < 5; ++n )
187             {
188                 a = i + m + n;
189                 Assign( &arr, &a, i, m, n );
190             }
191 
192     int b = 0;
193     ///取值測試
194     for( i = 0; i < 2; ++i )
195         for( m = 0; m < 3; ++m )
196             for( n = 0; n < 5; ++n )
197             {
198                  Value( &arr, &b, i, m, n );
199                  printf( "[%d][%d][%d]=%d\n", i, m, n, b );
200             }
201 
202     ///銷燬數組
203     DestroyArray( &arr );
204 
205     return 0;
206 }

運行測試:測試

 

若代碼存在 bug 或程序缺陷, 請留言反饋, 謝謝。                                                                                                                                                                                                                                                                                                                                                            spa

相關文章
相關標籤/搜索