日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言动态数组建立方法

發布時間:2023/12/2 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言动态数组建立方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

動態數組是指在聲明時沒有確定數組大小的數組,即忽略圓括號中的下標;當要用它時,可隨時用ReDim語句(C語言中用malloc語句)重新指出數組的大小。使用動態數組的優點是可以根據用戶需要,有效利用存儲空間。

動態數組,是相對于靜態數組而言。靜態數組的長度是預先定義好的,在整個程序中,一旦給定大小后就無法改變。而動態數組則不然,它可以隨程序需要而重新指定大小。動態數組的內存空間是從堆(heap)上分配(即動態分配)的。是通過執行代碼而為其分配存儲空間。當程序執行到這些語句時,才為其分配。程序員自己負責釋放內存。(欲詳細了解堆請見堆棧)

為什么要使用動態數組?

在實際的編程中,往往會發生這種情況,即所需的內存空間取決于實際輸入的數據,而無法預先確定。對于這種問題,用靜態數組的辦法很難解決。為了解決上述問題,C語言提供了一些內存管理函數,這些內存管理函數結合指針可以按需要動態地分配內存空間,來構建動態數組,也可把不再使用的空間回收待用,為有效地利用內存資源提供了手段。

動態數組與靜態數組的對比

  對于靜態數組,其創建非常方便,使用完也無需釋放,要引用也簡單,但是創建后無法改變其大小是其致命弱點!   對于動態數組,其創建麻煩,使用完必須由程序員自己釋放,否則嚴重會引起內存泄露。但其使用非常靈活,能根據程序需要動態分配大小。   如何構建動態數組

遵循原則

  申請的時候從外層往里層,逐層申請;   釋放的時候從里層往外層,逐層釋放。

構建所需指針

   對于構建一維動態數組,需要一維指針;   對于二維,則需要一維,二維指針;   三維需要一,二,三維指針;   依此類推。

構建所需函數

  
函數原型 返 回 功能說明
void *malloc(unsigned int size); 成功:返回所開辟
空間首地址 失敗:返回空指針
向系統申請
size字節的
堆空間
void *calloc(unsigned int num, unsigned int size); 成功:返回所開辟
空間首地址 失敗:返回空指針
按類型申請
num個size字
節的堆空間
void?free(void *p); 無返回值 釋放p指向
的堆空間
void *realloc(void *p,unsigned int size); 成功:返回新開辟
空間首地址 失敗:返回空指針
將p指向的
堆空間變為
size

說明:

  (1)規定為void *類型,這并不是說該函數調用后無返回值,而是返回一個結點的地址,該   地址的類型為void(無類型或類型不確定),即一段存儲區的首址,其具體類型無法確定,只有使   用時根據各個域值數據再確定。可以用強制轉換的方法將其轉換為別的類型。例如:double   *pd=NULL; pd=(double *)calloc(10,sizeof(double)); 表示將向系統申請10個連續的   double類型的存儲空間,并用指針pd指向這個連續的空間的首地址。并且用(double)對calloc( )   的返回類型進行轉換,以便把double類型數據的地址賦值給指針pd。   (2)使用sizeof的目的是用來計算一種類型的占有的字節數,以便適合不同的編譯器。   (3)由于動態分配不一定成功,為此要附加一段異常處理程序,不致程序運行停止,使用戶   不知所措。通常采用這樣的異常處理程序段:   if(p==NULL) { printf("動態申請內存失敗!\n"); exit(1); //異   常退出 }   (4)這四個函數頭文件均包含在<stdlib.h>中。   (5)分配的堆空間是沒有名字的 只能通過返回的指針找到它。   (6)絕不能對非動態分配存儲塊使用free。也不能對同一塊內存區同時用free釋放兩次。   如:free(p);free(p);   (7)調用 free() 時, 傳入指針指向的內存被釋放, 但調用函數的指針值可能保持不變, 因   為p是作為形參而傳遞給了函數。嚴格的講, 被釋放的指針值是無效的, 因為它已不再指向所申請   的內存區。這時對它的任何使用便可能會可帶來問題。   malloc與calloc的區別   對于用malloc分配的內存區間,如果原來沒有被使用過,則其中的每一位可能都是0;反之,   如果這部分內存空間曾經被分配、釋放和重新分配,則其中可能遺留各種各樣的數據。也就是說,   使用malloc()函數的程序開始時(內存空間還沒有被重新分配)能正常運行,但經過一段時間后(內   存空間已被重新分配)可能會出現問題,因此在使用它之前必須先進行初始化(可用memset函數   對其初始化為0),但調用calloc()函數分配到的空間在分配時就已經被初始化為0了。   當你在calloc()函數和malloc()函數之間作選擇時,你需考慮是否要初始化所分配的內存空   間,從而來選擇相應的函數。

具體構建方法

  以三維整型數組array[n1][n2][n3]為例。   先遵循從外層到里層,逐層申請的原則:   最外層指針是array,它是個三維指針,所指向的是array[],其為二維指針。所以給array   申請內存應:   array=(int***)calloc(n1,sizeof(int**));   次層指針是array[],它是個二維指針,所指向的是array[][],其為一維指針。所以給array[]   申請內存應:   for(i=0;i<n1;i++)   {   array[i]=(int**)calloc(n2,sizeof(int*));   }   最內層指針是array[][],它是個一維指針,所指向的是array[][][],其是個整型常量。所   以給array[][]申請內存應:   for(i=0;i<n1;i++)   {   for(j=0;j<n2;j++)   {   array[i][j]=(int*)calloc(n3,sizeof(int));   }   }   當然,你可以把它們整合在一起為:   int i,j,k;   int n1,n2,n3;   int ***array;   scanf("%d%d%d",&n1,&n2,&n3);   array=(int***)calloc(n1,sizeof(int**));   for(i=0;i<n1;i++)   {   array[i]=(int**)calloc(n2,sizeof(int*));   for(j=0;j<n2;j++)   {   array[i][j]=(int*)calloc(n3,sizeof(int));   for(k=0;k<n3;k++)   {   array[i][j][k]=i+j+k+1;   }   }   }   最后不要忘了釋放這些內存,這要遵循釋放的時候從里層往外層,逐層釋放的原則。   分析過程可參考上面的解答,這里不再贅述。只給出代碼吧:   for(i=0;i<n1;i++)   {   for(j=0;j<n2;j++)   {   free(array[i][j]);//釋放第三維指針   }   }   for(i=0;i<n1;i++)   {   free(array[i]);//釋放第二維指針   }   free(array);//釋放第一維指針   其余維的如四維創建過程大同小異,這里不再贅述。

基礎概念

  C#集合、C#動態數組的概念之集合,什么是集合呢?集合就如同數組,用來存儲和管理一組特定類型的數據對象,除了基本的數據處理功能,集合直接提供了各種數據結構及算法的實現,如隊列、鏈表、排序等,可以讓你輕易地完成復雜的數據操作。在使用數組和集合時要先加入system.collections命名空間,它提供了支持各種類型集合的接口及類。集合本身上也是一種類型,基本上可以將其作為用來存儲一組數據對象的容器,由于c#面向對象的特性,管理數據對象的集合同樣被實現成為對象,而存儲在集合中的數據對象則被稱為集合元素。這里提到了接口這個概念,它也是面向對象編程進化的重要標準,我們在這里不做過多的講解,先注重學習集合中的對象及其使用就可以了,下面我們來學習第一種集合:   C#集合、C#動態數組的概念之C#動態數組ArrayList.ArrayList 類提供了繼承了IList接口。什么是繼承呢?這也是面向對象語言的重要特點之一,現在你們先把它理解為,如果一個對象繼承了類或接口,那么它也具有了這個類和接口中的方法、屬性,可以用這些繼承的方法和屬性來做相應的操作,比如:數組增加元素沒有Add()方法,但是動態數組ArrayList繼承了一個增加元素有Add()方法的接口,那么當它要增加元素的時候,不僅可以用索引,也可以用繼承下來的Add()方法了。隨著學習的深入,我會給大家再具體講解繼承的概念和使用繼承的好處。那么下面讓我們來看看動態數組所繼承的這個接口IList它有什么特性呢?   C#動態數組之 Ilist接口:定義了利用索引訪問集合對象的方法,還繼承了ICollection和IEnumerable接口,除實現了接口原有的方法成員外,其本身也定義多個專門的方法成員,例如新增、移除、在指定位置插入元素或是返回特定元素在集合中所在的位置索引,這些方法主要為集合對象提供類似數組的元素訪問功能。   C#動態數組之ILsit接口成員:add、insert、RemoveAt、Remove、contains、Clear、indexof方法,它最大的特色在于提供類似數組索引的訪問機制。   C#集合、C#動態數組的概念的基本情況就向你介紹到這里,希望對你了解和學習C#集合、C#動態數組的概念有所幫助。

構建實例

一維

  #include <stdio.h>   #include <stdlib.h>   int main()   {   int n1,i;   int *array;   puts("輸入一維長度:");   scanf("%d",&n1);   array=(int*)malloc(n1*sizeof(int));//第一維   for(i=0;i<n1;i++)   {   array[i]=i+1;   printf("%d\t",array[i]);   }   free(array);//釋放第一維指針   return 0;   }

二維

  #include <stdlib.h>   #include <stdio.h>   int main()   {   int n1,n2;   int **array,i,j;   puts("輸入一維長度:");   scanf("%d",&n1);   puts("輸入二維長度:");   scanf("%d",&n2);   array=(int**)malloc(n1*sizeof(int*)); //第一維   for(i=0;i<n1; i++)   {   array[i]=(int*)malloc(n2* sizeof(int));//第二維   for(j=0;j<n2;j++)   {   array[i][j]=i+j+1;   printf("%d\t",array[i][j]);   }   puts("");   }   for(i=0;i<n1;i++)   {   free(array[i]);//釋放第二維指針   }   free(array);//釋放第一維指針   return 0;   }

三維

  #include <stdlib.h>   #include <stdio.h>   int main()   {   int n1,n2,n3;   int ***array;   int i,j,k;   puts("輸入一維長度:");   scanf("%d",&n1);   puts("輸入二維長度:");   scanf("%d",&n2);   puts("輸入三維長度:");   scanf("%d",&n3);   array=(int***)malloc(n1*sizeof(int**));//第一維   for(i=0; i<n1; i++)   {   array[i]=(int**)malloc(n2*sizeof(int*)); //第二維   for(j=0;j<n2;j++)   {   array[i][j]=(int*)malloc(n3*sizeof(int)); //第三維   for(k=0;k<n3;k++)   {   array[i][j][k]=i+j+k+1;   printf("%d\t",array[i][j][k]);   }   puts("");   }   puts("");   }   for(i=0;i<n1;i++)   {   for(j=0;j<n2;j++)   {   free(array[i][j]);//釋放第三維指針   }   }   for(i=0;i<n1;i++)   {   free(array[i]);//釋放第二維指針   }   free(array);//釋放第一維指針   return 0;   }

四維

  #include <stdlib.h>   #include <stdio.h>   int main()   {   int n1,n2,n3,n4;   int ****array;   int i,j,k,m;   puts("輸入一維長度:");   scanf("%d",&n1);   puts("輸入二維長度:");   scanf("%d",&n2);   puts("輸入三維長度:");   scanf("%d",&n3);   puts("輸入四維長度:");   scanf("%d",&n4);   array=(int****)malloc(n1*sizeof(int***));//第一維   for(i=0; i<n1; i++)   {   array[i]=(int***)malloc(n2*sizeof(int**)); //第二維   for(j=0;j<n2;j++)   {   array[i][j]=(int**)malloc(n3*sizeof(int*)); //第三維   for(k=0;k<n3;k++)   {   array[i][j][k]=(int*)malloc(n4*sizeof(int));//第四維   for(m=0;m<n4;m++)   {   array[i][j][k][m]=i+j+k+m+1;   printf("%d\t",array[i][j][k][m]);   }   puts("");   }   puts("");   }   puts("");   }   for(i=0;i<n1;i++)   {   for(j=0;j<n2;j++)   {   for(k=0;k<n3;k++)   free(array[i][j][k]);//釋放第四維指針   }   }   for(i=0;i<n1;i++)   {   for(j=0;j<n2;j++)   {   free(array[i][j]);//釋放第三維指針   }   }   for(i=0;i<n1;i++)   {   free(array[i]);//釋放第二維指針   }   free(array);//釋放第一維指針   return 0;   }

數組案例

  #include <stdio.h>   #include <stdlib.h>   int main()   {   int*n,*p;   int i;   n=(int*)calloc(1,sizeof(int));   for(i=0;i<5000;i++)   {   n[i]=i+1;   printf("%d\t",n[i]);   p=(int*)realloc(n,(i+2)*sizeof(int));//動態擴充數組   if(p!=NULL)   n=p;   else   {   puts("error!");   return 0;   }   }   free(n);   return 0;   }

游戲應用

預備知識

  (1)getch()   函數原型: int getch(void);   函數功能: 從控制臺讀取一個字符,但不顯示在屏幕上。   函數返回: 讀取的字符。   (2)rand()   函數原型: int rand(void);   函數功能: 隨機函數, 產生0到32767間的隨機整數(0到0x7fff之間)。   函數返回: 隨機整數   所屬文件: <stdlib.h>   (3)srand()   函數原型: void srand(unsigned seed);   函數功能: 該函數和rand隨機函數配合使用,產生隨機數的起始發生數據。   參數說明: seed為無符號整數。   所屬文件: <stdlib.h>   (4)time()   函數原型: time_t time(time_t *timer)   函數功能: 得到機器的日歷時間或者設置日歷時間。   函數返回: 機器日歷時間。   參數說明: timer=NULL時得到機器日歷時間,timer=時間數值時,用于設置日歷時間,   time_t是一個long類型。   所屬文件: <time.h>   (5)'\b'實現退格,即當前光標后退一格。   (6)'\a'實現響鈴,即執行時計算機會嘟一聲。   (7)得到隨機數值范圍在a~b(包含b)的方法:rand()%(b-a+1)+a;

代碼

  #include <stdio.h>   #include <conio.h>//getch()函數所需頭文件   #include <stdlib.h>//隨機函數所需頭文件   #include <time.h>//time()函數所需頭文件   void clear(void)//此函數用以清除當前行   {   printf("\r \r");   }   void start(void)   {   puts("這是消單詞游戲的精簡版,還不會圖像編程的人可以看一看");   puts(" 由于沒有引人數據庫,所以此單詞是模擬的。");   puts("按任意鍵開始,按Esc鍵結束,按tab鍵重新開始:");   puts(" 一旦輸錯,將發出聲音警告,你必須重新輸入。");   puts(" 按任意鍵開始,按Esc鍵結束:");   if( '\x1b' == getch() ) //按Esc鍵結束   {   exit( 1 );   }   }   int main()   {   char*c_rand,*c_input;   int i,j,N,n,space,N_rand;   start();   printf("\r你想消最多由多少個字母組成的單詞?(輸入數字(1-9)");   n=getch();   N=n-'0';//將輸入的字符轉換為整型數字   clear();//清除當前行   if(!((N>=1&&N<=9)||n==27))//27是鍵Esc的ASII值   {   printf("\r范圍錯誤,請重新開始:");   getch();   exit(1);//異常退出   }   if(n==27)   return 0;   srand(time(NULL));//用來對隨機函數初始化   c_rand=(char*)malloc(N+1);   c_input=(char*)malloc(N+1);   while(1)   {   N_rand=rand()%N+1;//實現單詞長度隨機定義   for(i=0;i<N_rand;i++)   {   c_rand[i]=(rand() ==0)?(rand()&+'A'):(rand()&+'a');//隨機取個字母   }   c_rand[N_rand]='\0';   //下面四行代碼實現單詞位置隨機出現   space=rand()P;   putchar('\r');   for(i=0;i<space;i++)   putchar(' ');   printf("%s",c_rand);   for(i=0;i<N_rand;i++)   {   c_input[i]=getch();//用戶輸入   if(c_input[i]=='\x1b')//"\x1b"代表的是Esc鍵   break;   //下面五行代碼實現字母消失效果   putchar('\r');   for(j=0;j<space;j++)   putchar(' ');   for(j=0;j<=i;j++)   putchar(' ');   if(c_input[i]!=c_rand[i])   {   i=-1;   putchar('\a');   //下面四行代碼代碼字母重現效果   putchar('\r');   for(j=0;j<space;j++)   putchar(' ');   printf("%s",c_rand);   }   }   if(c_input[i]=='\x1b')//"\x1b"代表的是Esc鍵   break;   }   free(c_rand);   free(c_input);   return 0;

  }



轉:http://blog.sina.com.cn/s/blog_7414b2930100v20t.html

總結

以上是生活随笔為你收集整理的C语言动态数组建立方法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。