發表文章

目前顯示的是 5月, 2020的文章

利用指標循序存取陣列元素(n像是會移動的)

練習嘗試運用指標處理陣列。 陣列範圍為 v[5] (相當於有0~4一共5個int),在C語言的陣列位址規則中, V[5]空間是不存在的 (超出範圍不可存取), 但是陣列位址是有的 ,也就是超出範圍且不可存取的V[5]位置中會有記憶體位址 可以取得該址 。 在練習中的迴圈條件是當int *n是取址&v[5],迴圈停止。 感覺n就像是會移動的(利用++n),如下: V[0]  V[1]  V[2]  V[3]  V[4]    n       n1     n2      n3     n4        ++n 所以++n以後n就會感覺像是一直向右移動了。 #include<stdio.h> int main(){ int v[5]={2,5,3,1,4}; printf("原始值\n"); for(int i=0;i<5;++i){ printf("%3d ",v[i]); } printf("\n\n"); int* n; for(n=v;n!=&v[5];++n){ *(n)=*(n)+10; } printf("全部加10\n"); for(int i=0;i<5;++i){ printf("%3d ",v[i]); } printf("\n"); return 0; } 不同用途與指令搭配的寫法可以有很多變化。 #include<stdio.h> int main(){ int v[5]={2,5,3,1,4}; int* n=v; printf("%d\n",*n++); printf("%d\n",*n++); printf("%d\n",*n++); printf("%d\n",*n++); printf("%d\n",*n++); return 0; } 搭配while更讓人驚豔 #include<stdio.h> int m

利用指標來處理陣列資料基本觀念

可以利用指標取出陣列位址,以及利用陣列位址加減(位移)特性來處理與運作達成條件和目的。 int *n是一個int指標,用以儲存記憶體位址,當有5個int的陣列v【也就是V[5]】,需要每都做加減乘除之類的運算,可以透過n=v(等同n=&v[0])賦予指標(n)的v[0]記憶體位址,以及v[1]+1==v[2]的這種特性來進行處理,也就是n=&v[0],n+1=&v[1]....依此類推,故只要給予運算元*後,就可以改變陣列每一個位址的內容值了,例如:*(n+2)=52+16,其結果v[2]內容值就等於68,*(n+4)=*(n+2)+1,那v[4]內容值就是69。 可以運用此關係配合迴圈或者其他指令達到條件與需求。 #include<stdio.h> int main(){ int a[5]={6,7,8,9,10}; //&v[0]+1==&v[1]; //&v[2]-1==&v[1]; //&v[2]+&v[3]C語言不合法,但是&v[x]-&v[x]是合法的 //&v[2]+&v[3];;;;;C語言&v[x]+&v[x]不合法,編譯會失敗 //&v[2]-&v[1];;會等於這兩個陣列中間隔了多少的陣列元素 ////↑等於1,簡單說就是這兩個位址距離1個元素 //&v[5]-&V[0]==5兩者位址之間有5個元素 //&v[x]-&V[x]會得到一個整數 int *n;//一個int指標 int v[5];//5個int大小的陣列 n=v;//n=&v[0]自動隱性轉型 int size=sizeof(v)/4;//1個int等於4byte printf("V[0]指標位址:%p\n",n); *n=69; *(n+1)=52; for(int i=0;i<5;++i){ *(n+i)=*(n+i)+i; } for(int i=0;i<5;++i){ printf("v[%d]=%d\n",i,v[i]); } f

指標心得記錄

雖然指標在傳遞後可以很方便的修改其內容而不用回傳值,但其實也伴隨著風險,當不想修改到主程式之中變數的內容值時,使用指標傳遞位址給函式運作是有修改到的風險,所以: 1. 能傳遞數值就傳數值 ,可以避免使用傳遞指標位址就不使用。 2.傳遞一份複製的數值用起來相對安全 (且保持主、函式之間更乾淨) 。 3.可傳遞一般常數(方便使用),但指標位址不能使用常數 (沒有類似&3或&16) 。 但有幾種應該採取傳遞指標記憶體位址的狀況: 1.當複製成本過高時【結構過度龐大或複雜】。 2.需要改變到引數(主程式的變數內容)時【例如比大小,數字交換等等】。 3.不能複製到數值、過度麻煩或困難取得數值時【例如陣列、字串】。

兩數數值排序(函式+指標)練習(&*抵銷)

這邊我用拆解的方式,把每個步驟都用函式分開(主程式、條件判斷函式、比大小函式),主要目的是練習指標傳遞運用。 有個要稍微注意的地方,當&*一起且連續出現時,兩者可以互相抵消 例如: 函式ABC(int *a,int *b){ 呼叫         big (&*a,&*b) ;         } 傳遞位址部分應該變成 big(a,b) 即可。 練習撰寫: #include<stdio.h> void sort(int*x,int*y){ if(*x<*y){ compare(x,y) ; //swap(&*x,&*y) &*可抵消 } } void compare(int *xx,int *yy){ int cg=*xx; *xx=*yy; *yy=cg; } int main(){ int a,b; scanf("%d%d",&a,&b); sort(&a,&b); printf("大:%d 小:%d",a,b); return 0; }

指標傳遞、陣列傳遞自我練習

#include<stdio.h> int swap(int[],int); void swap2(int*,int*); int main(){ int i,j,n,cg; int d[5]; n=sizeof(d)/4; for(i=1;i<=n;++i){ scanf("%d",&d[i-1]); } swap(d,n); for(i=1;i<=n;++i){ printf("%d ",d[i-1]);   } int k,l; printf("\n"); scanf("%d%d",&k,&l); swap2(&k,&l); printf("%d %d",k,l); return 0; } int swap(int x[],int n){ int i,j,cg; for(i=0;i<n;++i){ for(j=0;j<n-i;++j){ if(x[j]<x[j+1]){ cg=x[j]; x[j]=x[j+1]; x[j+1]=cg; } } } } void swap2(int *y,int *u){ if(*y<*u){ int ww=*y; *y=*u; *u=ww; } }

主程式、函式指標運用(取址、運算、資料型態)基本練習-2

運算元、運算子、型態等等搞清楚後,運用起來比較順手了。 #include<stdio.h> int swap(int *c,int *d){ int e=*c; *c=*d; *d=e; } int main(){ int a,b; int*x,*y; printf("A:"); scanf("%d",&a); printf("B:"); scanf("%d",&b); x=&a; y=&b; swap(x,y); int c=*x+*y; printf("\nAB交換後變成\nA:%d\nB:%d\n",*x,*y    /*a,b*/    ); printf("指標X存A位址為:%p\n",&a    /* x */    ); printf("指標Y存B位址為:%p\n",&b    /* y */    ); printf("C:%d\n",c); return 0; }

主程式、函式指標運用(取址、運算、資料型態)基本練習

簡單的練習指標,輸入數值給a,指標b取得a位址(&a),呼叫函式並給予指標b儲存的a位址,然後函式也要宣告一個指標型態的變數儲存指標b傳遞過來的a記憶體位址(int* n),最後函式中對n給予運算子*進行a記憶體位址的內容加以計算【函式中(*n=*n+10;)就等於主程式中a=a+10;】。 函式不須回傳,因為是直接修改記憶體位址之中的內容。 #include<stdio.h> void sum(int*n){ *n=*n+10; } int main(){ int a; int *b; printf("給予A初始值:"); scanf("%d",&a); b=&a; sum(b); printf("函式處理後的A=%d\nA ddr position is:%p\n",a,b); return 0; }

指標基本概念與基本運作

其實在之前已經使用過指標的功能,只是沒有明確的顯現出來。 當主程式要把陣列傳遞給函式時【主a[5];sum(a,5);函int sum(int b[ ],int n)】,其實主程式傳遞給函式的就是傳遞a陣列第一個儲存位置在記憶體的 "位址" ,先前有提到如果改變函式中接收的a陣列記憶體位址的b陣列,一旦b陣列內容改變,主程式的a陣列也會改變,其實這就是指標的基本概念之一。 (type *)指標:可儲存記憶體位置型別(int *b) (&)取址運算子:取得指定變數的記憶體位址(b=&a;) (*)間接運算子:取得該記憶體位址的內容值進行存取(*b=10,所以a變10) 基本指標運作: int a=69; int *b=&a; int r=*b; 表示式為a,型態為int,內容值為69; 表示視為&a,型態為int*,內容值為00061FE1XX(記憶體位址); 表示式為b,型態為int*,內容值為00061FE1XX(記憶體位址); 表示式為*b,型態為int,內容值為69; 至於指標上的基本運作,以下會直接用編碼來記錄。 int main(){ int a=69,c;               //a為int型態內容值69; int *b;//int* b皆可  //為int*型態用於紀錄記憶體位址; b =&a;                     // b為int*型態 ,用於儲存記憶體位址                                        //&a為int*型態, 內容為00061FE1XX(記憶體位址); c=*b;                      //c為int型態//*b為int型態 *b=96;                    //*b為int型態 printf("A:%d",a);  ////列印後: A:96 printf("B:%p",b);  ////列印後: B:00061FE1XX printf("C:%d",a);  ////列印後: C:69 return 0; } 要注意上面編碼紅色

如何解決STDIN內暫存的問題(目前會的方法)

如何解決stdin內暫存的問題,目前我有查到並練習使用過的有: 1.fflush(stdin)..........這種方式在網路資源上有人提,雖然有效果,但多數人不建議使用。 2.setbuf(stdin,NULL)....網路上有看到,將預設緩衝區變成無緩衝區,NULL解釋是給stdin一個空值,就像清空,但是如過後面又有要抓stdin內容的字元或數值,在每一次scanf我都會執行一次,有效果且似乎沒有人提到有後遺症,但使用上頗為不便利(每次都要先打再scanf),我是弄成簡易的函式每次要用就呼叫。 3.getchar.....使用getchar不斷獲取緩衝區內的內容,直到緩衝區內空為止,這種方法很有效,建議使用,C primer 上也介紹了這種方法,但是我還沒有融會貫通,只是會使用...有機會要徹底搞懂。 char str[5]; int i,n; n=sizeof(str); for(i=0;i<n;++i){ str[i]=getchar(); //網路資源是說會獲取直到緩衝區空的,測試過後似乎是少了什麼東西導致stdin還有字元或數值未消除。 }  setbuf(stdin,NULL); //為了消除stdin內容暫時用(找尋其他方式中) 上面範例似乎還是有問題,需要找時間徹底解決。 getchar似乎還需要跟EOF配合使用,目前嘗試中。 **EOF在C標準函式庫中表示檔案結束符(end of file)。在while迴圈中以EOF作為檔案結束標誌。

練習清除stdin且正確取得stdin中對應內容(%d,%c)

#include<stdio.h> #include<string.h> int value(){ int v; printf("key any value\n"); while(scanf("%d",&v)!=1){ printf("try again\n"); setbuf(stdin,NULL); } return v; } void word_string(){ char str[5]; int n=sizeof(str); setbuf(stdin,NULL); for(int i=0;i<n;++i){ scanf("%c",&str[i]); } printf("%s",str); } int main(){ char str[5]; printf("數值:%d\n",value()); word_string(); return 0; }

scanf的數值、字元讀取,清除stdin方法

練習一下 1.使用者需要輸入數值卻輸入字元,如何清除在stdin暫存的字元(錯誤輸入) 2.在緩衝區中會暫存到\n(也就是按下Enter鍵),當需要使用者輸入字串時,因為先前已先執行過輸入數值, 並按下Enter鍵 ,所以實際印出來的會少一個字元,找出解決方式。 適當運用setbuf(stdin,NULL);來清除多餘的輸入或錯誤的輸入也是一個方式(使stdin由預設緩衝區切換成無緩衝區),當scanf指令執行後,緩衝區內容就會消失。 #include <stdio.h> int main() { int value,i,n; char str[5] ; while(scanf("%d", &value)!=1){ printf("Error\nTry again\n"); setbuf(stdin,NULL); } setbuf(stdin,NULL); n=sizeof(str); for(i=0;i<n;++i){ scanf("%c", &str[i]); } printf("value:%d\n",value); for(i=0;i<n;++i){ printf("%c",str[i]); } printf("\n"); printf("hello C world\n"); return 0; }

解決scanf輸入數值問題(stdin==0 or stdin==1)【用fflush(stdin)非正確方式】

關於使用scanf("%d")、scanf("%f")、scanf("%lf")來接收數值時,如何限制僅接收數值,且避免出現錯誤。 當要使用scanf功能時,原理其實是把鍵盤所打的內容,先顯示在終端機上,當下並沒有任何存取的動作,當我們按下Enter按鍵時(也等於'\n'),就是把鍵盤所要輸入的內容先放到stdin的位置,然後scanf指令才會把暫存在stdin位置的內容讀取進來,至於所需要讀取的內容為何,就是看我們給予的讀取指令內容(%d、%f、%lf、%c、%s、%zu.....等等)。 其實當接收完成時候,stdin會回傳一個數值,接收成功傳1,失敗傳0,可以利用這個回傳值來控制程式執行反映,避免出現意外的方式。 因為當要讀取一個int數值時,鍵盤打ABC,按下Enter時,ABC會暫放在stdin中,直到等待適合的指令內容讀取(若符合成功讀取,stdin內容就會不見),若使用迴圈讀取int數值時(成功符合後跳脫迴圈繼續後面程式,失敗則繼續迴圈),因ABC不是int數值,所以迴圈會 一直執行,就會無限循環無法跳脫(scanf一直循環讀取到ABC),所以要再讓使用者重新輸入,就必須要先清除stdiin內容,目前我使用fflush去清除其內容【fflush(stdin)】,相信還有其他方式可以解決這個問題。 使用者輸入非整數時,需重新讓使用者輸入,直到讀取到int數值,接收到數值時將stdin丟到指定且取址的變數位置。 #include<stdio.h> int main(){ float a; while(scanf("%f",&a)!=1){ printf("please key integer\n"); fflush(stdin); } printf("%.3f\n",a); return 0; }

解決讀入字串的緩衝區溢位問題-1(不完美解決方法)

當宣告字元陣列時,賦予此陣列一個固定的大小(記得要留最後1個位置給\0),50個字元就給予大小51(50字元+最後的1個\0),嘗試用函式來處理字串時,先呼叫函式並將文字陣列位址傳遞以及陣列最大值(0~XX)【大小[51]就是50,[101]就是100】,函式名稱為keyin,傳遞陣列g,大小51(即為50),記得陣列式從[0]開始,所以g[0]~g[50]有51個,剛好與宣告的51個一樣。例如:keyin(g,50); 函式中設定for迴圈,基本上也是從0開始,停止條件要小於50,因為50是要給字串中的\0作判斷結束,不可<=50,會造成陣列資料儲存溢位問題。 練習程式如下: #include<stdio.h> #include<string.h> void keyin(char [],int); int main(){ char g[51];  //g陣列大小51個 keyin(g,50); //呼叫函式,傳遞g陣列位址,並賦予第0~50共51個 printf("%s\n",g); //將字元陣列g(已經經過函式處裡)%s印出。 return 0; } void keyin(char a[],int n){ //(主)陣列g記憶起始位址給(函式)陣列a,賦予大小0~50給予使用。 int i=0; //掃描stdin空間次數(等待儲存鍵盤輸入內容)。 for(i=0;i<n;++i){ //第0次(對應字元陣列[0])開始,直到第49次(0~49=50),但i還是會加到50,判斷50>50不成立,停止執行內容。 scanf("%c",&a[i]); //等待鍵盤輸入後存取至stdin,之後掃描stdin共i次(0~49),最多i=50停止 if(a[i]=='\n') //如果掃描未到第49次以前(輸入字元未滿最大空間)收到換行\n(也就是鍵盤輸入enter)字元,停止迴圈。 break; } a[i]='\0'; //最後陣列位置第50存取字串結束標記\0,或者停止迴圈時,當下i為多少,字元陣列[i]~最大位置[50]皆為\0。 }

關於C語言字串計算長度 ( 編譯器支援c99up :%zu )

補出一個要點,關於c語言中,在一般計算字元陣列,正確上是使用 %zu (編譯器支援c99或更新)來讀取sizeof所計算的數值,若編譯器沒有支援c99或使用c89,c90等以前的版本則使用%u和%lu。 另外,字串使用雙引號都會在最後加上\0,所以像是Hello world字串本身內容是11字元長,加上使用雙引號在最後加上得\0,所以會增加1字元,所以不管內容是多長,都要自動加上1,例如pass[ ]="pass"字串陣列長度為5個字元(本身4字元)。 #include<stdio.h> #include<string.h> int str_l(char []); int main(){ char str[]="hello world"; printf("字元內容: %s\n",str); printf("字元陣列長度: %zu \n",sizeof(str)); printf("本體長度: %d\n",str_l(str)); return 0; } int str_l(char str[]){ int i; while(str[i]!='\0'){ ++i; } return i; } 當然可以給字元陣列一個大於本體所需的字元長度,例如"hello world",本體11字元加上1個字元的\0,一共12個字元,在宣告char str[ 20 ]="hello world";雖然本身文字一共只用11字元,但範圍已指定空間20字元,所以其餘後面的位置皆會補上\0,當使用%zu去sizeof(字元陣列)求出來的依然會是20字元。

字串(字元陣列)使用練習

字元和字串是使用char 來做宣告,例如char b='b',而字串則是使用 字元陣列 來組成,例如char book[ ]={'b','o','o','k'};。 兩者在輸出時都是使用%c來讀取該位置的內容。 一般使用字串(字元陣列),可以在最後一個位置給予'/0',這是C語言特別為字串所設計的,當讀取到/0的時候,代表了字串結尾,所以列印字串(字元陣列)時候,可以利用/0來做判斷條件進而完成字串列印。{'b','o','o','k', '\0' }; 但當字串內容較為多時,一個一個打{'b','o','o','k'}是非常不便利的,所以在C語言處裡一般宣告時用char book[ ]= "book" ;這方式寫入字元陣列與{'b','o','o','k', '\0' }是一樣的;當要讀取輸出時用printf("%s",book); #include<stdio.h> #include<string.h> void test(char[]); int main(){ char ch ='H'; printf("%c\n",ch); char hello[]={'H','e','l','l','o'}; for(int i=0;i<5;++i){ printf("%c",hello[i]); } printf("\n"); char write[]={'W','r','i','t','e',' \0 '}; test(write); char str[]="Hel

主程式陣列傳遞函式【關於記憶體位址】

圖片
關於主程式陣列傳遞到函式,為什麼不是像我們傳遞變數那樣直接複製其內容給予函式呢?在程式語言中複製一整個陣列數值代價是較大的,所以當主程式傳遞陣列到函式時,它傳遞的是陣列的第一個記憶體位址,例如int a[10],相當於陣列a有10個int(每個int佔4位元)連續存在記憶體的一個區塊,先假設第一個int起始為16800,第十個int位置就相當於16836(記憶體位址非舉例內容,只是用於舉例)。 在範例中,主程式傳遞陣列的不是複製數值(代價大),是傳遞記憶體位址給函式,所以在函式中讀取到的是該陣列在記憶體起始位址,所以我們在函式裡面有修改到陣列的內容,沒有回傳就會修改到陣列的內容,不同於傳遞一個變數,既使函式修改到傳遞進來的一般變數數值,也不會更改到主程式該變數內容,既使種程式變數名稱和函式變數名稱相同也不會影響,這點要多注意。 #include<stdio.h> void test(int[],int); int max(int[],int); int main(){ int x[]={42,59,-5,69}; int a[]={11,5,9}; int b[]={52,69,30,86,98}; printf("a max= %d\n",max(a,3)); printf("b max= %d\n",max(b,5)); printf("\n\nA has %d value\nB use %d space\n\n",sizeof(a)/sizeof(int),sizeof(b)); test(x,4); for(int i=0;i<4;++i){ printf("%d\n",x[i]); } return 0; } void test(int h[],int n){ int i; for(i=0;i<n;++i){ h[i]=h[i]+10; } } int max(int q[],int n){ int bigger=q[0],i; for(i=1;i<n;++i){ if(q[i]>bigger){ bigger=q[i];

CRAPS骰子賭博遊戲自我練習-未優化前

#include<stdio.h> #include<stdlib.h> #include<time.h> int dice(void); void result(int); int main(){ srand(time(0)); int i,total,first=0,ft=0,play=0,throwdice; do{ int point[2]={0}; printf("擲骰子請按1\t退出遊戲按0\n(0 or 1) : "); scanf("%d",&play);//0結束 1擲骰子 first++; if(play==1){ total=0; for(i=1;i<=2;++i){//兩顆骰子 point[i-1]=point[i-1]+dice(); printf("第%d顆: %d 點\n",i,point[i-1]); total=total+point[i-1]; } }else if(play>1){ printf("請輸入 1 or 0\n"); } if(play!=0){ printf("骰出 %d 點\n\n",total); if(first==1){ ft+=total; if(ft==7||ft==11){ resule(0); }else if(ft==2||ft==3||ft==12){ resule(1); } }else if(first!=1&&total==ft){ resule(0); }else if(first!=1&&total==7){ resule(1); } } }while(play!=0); printf("Bye~Bye~\n"); return 0; } int dice(void){ int a,d=0; d=

陣列主程式傳遞函式技巧(保留值標記陣列長度)

這次嘗試使用保留值標記陣列最後的一個位置,至於保留值為什麼數值都可以, 只要確定此數值是 在我們運用此陣列公所 不會使用到 的數值即可,此次練習用-1來當保留值。 #include<stdio.h> int max(int[ ]); int main(){ int n[]={26,69,86,38,5,-1}; //運用最後一個-1值當作判斷陣列長度的保留值 int g[]={18,26,58,-1}; //運用最後一個-1值當作判斷陣列長度的保留值 printf("n of max = %d\n",max(n)); //直接傳遞陣列名稱 printf("g of max = %d\n",max(g)); //直接傳遞陣列名稱 return 0; } int max(int v[ ]){ //直接接收主程式呼叫後傳遞的陣列。 int i=1,maxv=v[0]; while(v[i]!=-1){  //條件配合在陣列中最後一個位置的數值(成立則停止) if(v[i]>maxv){ maxv=v[i]; } ++i; } return maxv; //return i; //可回傳一共有幾個int(不含保留值),但已回傳maxv,此函式只能擇一 //return i+1; // 可回傳一共有幾個int(含保留值),但已回傳maxv,此函式只能擇一 } 當函式回傳i時,在主程式列印時會出現陣列使用上一共多少(除去保留值),但如果要顯示或接收到完整的陣列長度,則須回傳i+1。 在最近幾次的練習與運用上再次強調,方法很多種,但能選擇出當下條件最合適的最好,當然也是要多學習以及思考才可以看的更多不同角度的處理方式。

傳遞不同大小的陣列(多個不同陣列)運用同一函式

主程式傳遞不同陣列到同一函式,這邊用比大小來作範例,將陣列的名稱與大小分開來看,在主程式裡面我們呼叫函式時,就是要傳遞陣列名稱與陣列大小【範例maxn(v,3)】,v是陣列名稱(另一個),3是其陣列大小。 依照此規則就可以讓同一個函式給不同陣列大小使用【maxn(g,5)】。 函式需接收陣列與其大小,範例為【maxn(int x[ ],int y)】,v、g傳給x,3、5傳給y,屆時函式的x[0]就是v[0],依此類推如下: 主程式main的陣列v傳遞 【maxn(v,3)】 ,maxn函式接收 【maxn(int x[ ],int y)】 v[0]=x[0] v[1]=x[1] v[2]=x[2] 主程式main的陣列g傳遞 【maxn(g,3)】 ,maxn函式接收 【maxn(int x[ ],int y)】 g[0]=x[0] g[1]=x[1] g[2]=x[2] g[3]=x[3] g[4]=x[4] 練習範例: #include<stdio.h> int maxn(int[ ],int y); int main(){ int i,n; int v[3]={5,7,1};          //v[3],g[5]兩個不同陣列大小 int g[5]={2,10,8,6,9}; printf("v: %d\n",maxn(v,3));//呼叫函式並傳遞陣列名稱與大小 printf("g: %d\n",maxn(g,5));//同上 return 0; } int maxn(int x[ ],int y){ int max=x[0],j; for(int j=0;j<y;++j){ if(x[j]>max){ max = x[j]; } } return max; }

主程式的陣列傳遞到函式(基本)

在C語言裡面比較特別的是一般 變數(區域變數) 在主程式、函式與其他不同的函式式互相部會影響的(除非 全域變數 ),例如主程式宣告的n=5,當其他函式運作時,也有一個叫做n的變數在其函式運作,主程式的n不不會受到影響且內容式不會被改變的,但是 陣列 較為特殊,主程式的陣列數值n[3]={1,2,3},當函式中有使用到n[3]時,在函式中陣列n[3]改變數值後,會直接改變主程式的n[3],因為在C裡面主程式所宣告的陣列與每個函式中的同樣名稱陣列都是同一個。 例如在main裡面宣告一個陣列叫k[5],賦予陣列k每個位置數值別1,9,2,8,0,呼叫函是帶k陣列值過去,函式若在陣列k的每個位置都加上2,則陣列n[5]為3,11,4,10,2, 不需要回傳即 會改變主程式的陣列n[5],因為他不是複製,他是同一個 。 以下是自我練習當範例: #include<stdio.h> #include<stdlib.h> #include<time.h> void arraytest(int v[3],int g[3]); int main(){ srand(time(0)); int i,j,n[3][3]={{1,2,3},{4,5,6},{7,8,9}}; int v[3]={1,2,3}; int g[3]={2,4,6}; arraytest(v,g); for(i=0;i<3;++i){ for(j=0;j<3;++j){ int r,m,b,k,t; r=rand()%(9-k)+k; m=r%3; b=r/3; t=n[i][j]; n[i][j]=n[m][b]; n[m][b]=t; k++; } } for(i=0;i<3;++i){ for(j=0;j<3;++j){ printf("%d ",n[i][j]); } printf("\n"); } for(i=1;i<=3;++i){ printf("v%d= %d\n",i-1,v[i-1]); } for(in

隨機生成九宮格-交換法

這次隨機九宮格之陣列中的陣列是用交換法來做的。 交換法的交換對象是由執行格(i,j當下的值)來配合亂數選擇其陣列後面的位置進行交換。 #include<stdio.h> #include<stdlib.h> #include<time.h> int main(){ srand(time(0)); int i,j,n[3][3]={{1,2,3},{4,5,6},{7,8,9}}; for(i=0;i<3;++i){ for(j=0;j<3;++j){ int r,m,b,k,t; r=rand()%(9-k)+k; //r值是用來選擇欲交換的對象,k是將以交換的在下一輪不會被選擇到。 m=r/3; //m值為列/%兩個皆可,但必須要和行錯開用。 b=r%3; //m值為行,若列用%,行則用/,必須錯開,相同則只有0.0,1.1,2.2。 t=n[i][j]; //交換法開始。 n[i][j]=n[m][b]; n[m][b]=t; k++; //每次交換完成需+1,屆時取r值才可以去除以交換完成的。 } } for(i=0;i<3;++i){  //列印模式。 for(j=0;j<3;++j){ printf("%d ",n[i][j]); } printf("\n"); } return 0; } 這方法的可讀性比較直觀,但與前一篇使用函式來處理是各有優缺點。

陣列中的陣列之亂數九宮格~~亂數函式

更新一下,我把亂數生成變成一個函式,似乎比我上一篇程式的可讀性提高了許多。 #include <stdio.h> #include <stdlib.h> #include <time.h> int m(void); int main(){ int i,j,n[3][3]; for(i=0;i<3;++i){ for(j=0;j<3;++j){ n[i][j]=m(); //呼叫亂數生成函式 } } for(i=0;i<3;++i){ for(j=0;j<3;++j){ printf("%d ",n[i][j]); } printf("\n"); } return 0; } int m(void){ //亂數生成函式 srand(time(0)); int c; int static counter[9]={0}; while(1){ c=rand()%9+1; if(counter[c-1]==0){ counter[c-1]++; break; } } return c; }