C陣列

文章推薦指數: 80 %
投票人數:10人

無論是幾維的陣列,C語言都以分配一塊連續的記憶體空間來處理。

int x[10];. 分配10*sizeof(int)個bytes int x[5][10];. 分配5* ... 說明:   陣列是一種結構性的資料儲存空間,其同一陣列裡的資料性質呈一致性,元素與元素之間的記憶位置是相鄰的,通常我們利用一個變數來代表整體的資料。

舉例而言,我們可以把陣列想成一群鳥窩,而陣列裡的變數個數代表鳥窩的數目,例如:麻雀[20],我們可以想成麻雀的窩總共有二十間,每一間住著一間麻雀,假如我們想要知道第三間麻雀的名字,只要把麻雀[2]的值取出,便可知道住在第三間麻雀的姓名。

C語言的陣列索引一定是從0的開始的。

格式: 根據陣列的結構而言,可以把陣列分為(1)一維陣列、(2)二維陣列、(3)多維陣列。

而其表示方法如下: 資料型態 陣列名稱[陣列大小]; 資料型態 陣列名稱[陣列大小][陣列大小]; 宣告陣列變數時,也可一併給與初始值: intx[5]={1,2,3,4,5}; inty[]={1,2,3}; intz[3][4]={{1,2,3,4},{5,6,7,8},{0,1,2,3}}; inta[]; 上面例子裡的y陣列大小,是由後面{}裡元素的個數決定。

inta[]並沒有分配儲存陣列內容的空間,因此可視為指標宣告。

引用方式: 陣列名稱[索引值] 陣列名稱[索引值][索引值] 圖示: 範例:(輸入3個實數,並求其平均值) #include voidmain(){ floatnum[3],sum=0; inti; for(i=0;i<3;i++){ printf("Inputanumbertonum[%d]:",i); scanf("%f",&num[i]); sum=sum+num[i]; } printf("Theaverageis%f\n",sum/i); } 陣列的空間分配方式 無論是幾維的陣列,C語言都以分配一塊連續的記憶體空間來處理。

intx[10]; 分配10*sizeof(int)個bytes intx[5][10]; 分配5*10*sizeof(int)個bytes intx[4][5][6]; 分配4*5*6*sizeof(int)個bytes voidfun(intx[]){ } 上面的x就沒有分配陣列的空間了,而是相當於int*x;這是因為C語言呼叫函數傳遞參數時,無法傳遞整個陣列(陣列可能大得不得了),而是傳遞陣列的開頭地址,也就是指標。

因此在參數宣告時,指標和沒有宣告大小的陣列是可以混用的。

既然無論是幾維的陣列,C語言都以分配一塊連續的記憶體空間來處理,那麼像是 intx[2][3]; x[0][2]=0; 中的x[0][2]被翻譯到哪一塊記憶體去了?C語言是使用rowmajor的方式來處理多維到一維的對應。

簡單的說,就是右邊的索引先變化: OOOOOO 這六個整數的順序為x[0][0],x[0][1],x[0][2],x[1][0],x[1][1],x[1][2]。

array和pointer的對應關係如下: intx[p][q]; inty[p][q][r]; intz[p]; int*po; po=x; x[i][j]=0; *(po+i*q+j)=0;//samewithx[i][j]; po=y; y[i][j][k]=0; *(po+i*q*r+j*r+k)=0;//samewithy[i][j][k] po=z; z[i]=0; *(po+i)=0;//samewithz[i] 陣列的參數傳遞 C語言只能傳遞指標,無法傳遞陣列的內容。

假設我們要傳遞一個二維陣列,則C會幫我們將該陣列的起頭位置傳入,但參數宣告部分則有如下不同的方式: voidfoo1(intx[][]){//編譯過,但Compiler不知如何翻譯,還是用int*x自己計算地址比較好 x[2][2]=0;//編譯錯誤!,Compiler不知如何翻譯 } voidfoo2(intx[][3]){//Compiler知道如何翻譯 x[1][1]=0;//Compiler知道要翻成*(x+1*3+1) } voidfoo3(intx[2][3]){//Compiler知道如何翻譯 x[1][1]=0;//Compiler知道要翻成*(x+1*3+1) } voidfoo4(intx[3][]){//編譯錯誤 } voidfoo5(int*x){//反正只能傳pointer *(x+1*3+1)=0; } intmain(){ intm[2][3]; int*p; intk[4][4]; foo2(m); foo2(p);//Compilerwarning,incompatiblepointertype foo3(k);//Compilerwarning,incompatiblepointertype foo5(m);//Compilerwarning,incompatiblepointertype foo5(p); foo5((int*)m);//強迫轉型,Compiler就不會抱怨了 } 動態空間分配 宣告陣列時,Ccompiler就已經分配好空間了。

例如 intmain(){ intx[10][20]; } compiler會在進入main時於堆疊上分配給x放置200個整數所需的空間,而在離開main時將空間回收。

對指標來說,則只有分配紀錄指標的空間,但對於透過該指標所能存取的記憶體,卻沒有分配。

有許多情況是設計者無法事先預知所需空間的大小,必須等到runtime才能知道。

C語言提供了一系列的函數可於執行期間分配或釋放記憶體空間。

void*malloc(size_tsize); void*calloc(size_tnelem,size_telsize); voidfree(void*ptr); 使用以上函數必須#include

malloc會自heap(堆積)取得size個byte,並傳回該區塊的起始位置。

calloc分配nelem個大小為elsize個byte的空間,並把該區塊所有的內容設為0。

free則是釋放由malloc或calloc所分配的記憶體空間。

要特別提醒讀者的是,malloc和free要小心使用,如果malloc所得的空間沒有用free釋放,則應用程式就會一直佔住該記憶體,此一現象稱為memoryleakage。

如果同一空間free了兩次,或已經free了卻繼續使用,也都可能出問題。

範例 SelectionSort #include #defineSIZE6 intmain(){ inti,j,min,at,tmp; intdata[]={5,7,1,4,3,2}; for(i=0;i #defineSIZE6 intmain(){ inti,j,tmp; intdata[SIZE]={5,7,1,4,3,2}; for(i=1;i=0&&data[j]>tmp;j--){ data[j+1]=data[j]; } data[j+1]=tmp; } } PascalTriangle 下圖為n=6的情況 1 11 121 1331 14641 15101051 1615201561 其規則是最外層是1,裡面每個數字都是上方兩個數字的和. PascalTriangle是(x+y)n每個項次的係數. 提示:如果把上圖左邊的空白拿掉則會變成下面的圖形,除了最左邊和最右邊的數字是1以外,裡面的每一個數字都是其正上方和左上方數字的和.你可以用陣列來計算和儲存這些數字,然後再以上圖的格式印出來. 1 11 121 1331 14641 15101051 1615201561 所以只要你能回答下面問題,程式就寫完了: 如果要用*號印出這種形狀的三角形,該怎麼寫?(迴圈範例裡已經練習過了) 最左邊和最右邊如何表達? 內部每一個數字都是正上方和左上方數字,請問正上方和左上方這兩個位置的陣列索引如何表達? 每一個row前面要加上幾個空白才能讓圖形看起來是正三角形? 以下是程式的範例: /** *ProgramName:pas2.c *Purpose:printpascaltriangleonscreen *Author:Shiuh-ShengYu,DepartmentofInformationManagement *NationalChiNanUniversity *Since:2004/12/10 */ #include intmain(){ intn,i,j; unsignedtri[51][51]; printf("PleaseinputsizeofPascaltriangle(0to50):"); scanf("%d",&n); if(n<0||n>50){ printf("IcanonlyprintPascaltrianglebetween0and50.\n"); return; } for(i=0;i<=n;i++){ for(j=0;j /*列出由at左邊所有的排列*/ voidpermutation(intdata[],intat,intarraySize){ inti,tmp; //如果已經排到最後了,印出結果 if(at==arraySize){ for(i=0;i /** *n:dataarray的長度 *m:希望選m個數字 *after:只能選after..n-1位置的數字 *got:目前已選的數字個數 */ voidcom(intdata[],intn,intm,intafter,intgot){ inti; if(m==got){//已選滿m個數字 for(i=0;i8){ showBoard(board); solutions++; return; } intdir[3]={9,10,11};//下方的三個方向 intcol,pos,i,j; //檢查nthrow上的每一個column(有8個要檢查) for(col=1;col<=8;col++){ //如果要放上去的地方不在任何一個皇后的勢力範圍內 if(board[pos=10*n+col]==0){ //放上新皇后 board[pos]='Q'; //建立新皇后下方的勢力範圍 for(i=0;i<3;i++) for(j=pos+dir[i];board[j]>=0;j+=dir[i]) board[j]++; putOneQueen(board,n+1); //移除此皇后 board[pos]=0; //移除此皇后的勢力範圍 for(i=0;i<3;i++) for(j=pos+dir[i];board[j]>0;j+=dir[i]) board[j]--; } } } intmain(){ putOneQueen(initBoard,1); printf("八皇后問題共有%d組解\n",solutions); } 如果在執行期間由使用者輸入棋盤的大小n,你如何寫一程式找出n皇后的所有解?



請為這篇文章評分?