二維字符串數組的初始化-動態內存分配

二維字符串數組的初始化-動態內存分配

     昨天在用FBS200 指紋採集芯片採集到一個二維數組數據後,利用串口傳輸上來的數據是以十六進制的數據格式表示的二維矩陣,比如“FF” 、“BD” 、“5C ”等等這樣的形式,而對於一幅灰度圖像,一般都是在0255 之間的數據來表示其亮度值,因此想通過二維字符串數組來對採集過來的數據進行轉化顯示。 但在動態分配一個 char **str str new char*[128] ;之後對其進行初始化時,總是出現錯誤,不知道如何才能很好的對其賦值,還得深入學習一下。

其實對一個字符的轉化很容易,但對一個字符串形式的字符來轉化,而且是對一個多維數組來轉化就有點喫力了。首先建立一個多維字符串數組,這裏是二維的字符串數組,程序如下所示:

#i nclude "stdio.h"

void main()

{

     char *str1[2][2] ={"FF","F9","FA","F9"};// 初始化一個二維字符串數組

     char *str;// 定義一個一維字符串變量

     int a,b;

     int i,j;

     int result1;

     for (i=0;i<2;i++)

     {

         for (j=0;j<2;j++)

         {

              str=str1[i][j];// 對一維字符串賦值

              printf("%s/n",str);

              if(str[0]>='A' && str[1]>='A')

              {

                   a=int(str[0]-'A');

                   b=int(str[1]-'A');

                   result1=(a+10)*16+(b+10)*1; // AA” ~“FF ”之間的轉化結果

              }

              else if (str[0]>='A' && str[1]<'A')

              {

                   a=int(str[0]-'A');

                   b='A'-str[1]+1;

                   result1=(a+10)*16+b; // A0” ~“F9” 之間的轉化結果

              }

              else if (str[0]<'A' && str[1]>='A')

              {

                   a='A'-str[0]+1;

                   b=int(str[1]-'A');

                   result1=a*16+(b+10)*1; // 0A ~“9F 之間的轉化結果

              }

              else

              {

                   a='A'-str[0]+1;

                  b='A'-str[1]+1;

                   result1=a*16+b; // 00” ~“99 ”之間的轉化結果     

              }

              printf("a=%d/n",a);

              printf("b=%d/n",b);

              printf("%d/n",result1);    

         }

     }

}

這裏只是用2 ×2 的字符串數組做了一個實驗,一幅圖像都是比較大的,這樣在對數組初始化時會佔用很多的內存,這樣有時會造成編譯無法通過,昨天就很有幾次死機,當時只是用到64 ×64 的數組。後來把數組的初始化放到main 的外面,作爲全局變量,在棧中靜態的分配一塊內存空間,雖然可行,但也很佔內存,於是想到了在函數中動態分配內存,對動態分配內存又重新學習了一遍,不瞭解的可以和我一起學習一下。

動態內存分配

1. 堆內存分配

C/C++ 定義了4 個內存區間:代碼區,全局變量與靜態變量區,局部變量區即棧區,動態存儲區,即堆(heap )區或自由存儲區(free store )。

堆的概念:

通常定義變量(或對象),編譯器在編譯時都可以根據該變量(或對象)的類型知道所需內存空間的大小,從而系統在適當的時候爲他們分配確定的存儲空間。這種內存分配稱爲靜態存儲分配;

    有些操作對象只在程序運行時才能確定,這樣編譯時就無法爲他們預定存儲空間,只能在程序運行時,系統根據運行時的要求進行內存分配,這種方法稱爲動態存儲分配。所有動態存儲分配都在堆區中進行。

當程序運行到需要一個動態分配的變量或對象時,必須向系統申請取得堆中的一塊所需大小的存貯空間,用於存貯該變量或對象。當不再使用該變量或對象時,也就是它的生命結束時,要顯式釋放它所佔用的存貯空間,這樣系統就能對該堆空間進行再次分配,做到重複使用有限的資源。

 

2. 堆內存的分配與釋放

堆空間申請、釋放的方法:

C++ 中,申請和釋放堆中分配的存貯空間,分別使用newdelete 的兩個運算符來完成:    指針變量名=new 類型名( 初始化式)

         delete 指針名;

例如:1 int *pi=new int(0);

      它與下列代碼序列大體等價:

      2 int ival=0, *pi=&ival;

區別:pi 所指向的變量是由庫操作符new() 分配的,位於程序的堆區中,並且該對象未命名。  

堆空間申請、釋放說明:

.new 運算符返回的是一個指向所分配類型變量(對象)的指針。對所創建的變量或對象,都是通過該指針來間接操作的,而且動態創建的對象本身沒有名字。

. 一般定義變量和對象時要用標識符命名,稱命名對象,而動態的稱無名對象( 請注意與棧區中的臨時對象的區別,兩者完全不同:生命期不同,操作方法不同,臨時變量對程序員是透明的)

. 堆區是不會在分配時做自動初始化的(包括清零),所以必須用初始化式(initializer) 來顯式初始化。new 表達式的操作序列如下:從堆區分配對象,然後用括號中的值初始化該對象。

 

3. 堆空間申請、釋放演示:

. 用初始化式(initializer) 來顯式初始化

int *pi=new int(0);

.pi 生命週期結束時,必須釋放pi 所指向的目標:

         delete pi;

注意這時釋放了pi 所指的目標的內存空間,也就是撤銷了該目標,稱動態內存釋放(dynamic memory deallocation ),但指針pi 本身並沒有撤銷,它自己仍然存在,該指針所佔內存空間並未釋放。

下面是關於new 操作的說明

.new 運算符返回的是一個指向所分配類型變量(對象)的指針。對所創建的變量或對象,都是通過該指針來間接操作的,而動態創建的對象本身沒有名字。
  
. 一般定義變量和對象時要用標識符命名,稱命名對象,而動態的稱無名對象( 請注意與棧區中的臨時對象的區別,兩者完全不同:生命期不同,操作方法不同,臨時變量對程序員是透明的)

. 堆區是不會在分配時做自動初始化的(包括清零),所以必須用初始化式(initializer) 來顯式初始化。new 表達式的操作序列如下:從堆區分配對象,然後用括號中的值初始化該對象。

 
4.
在堆中建立動態一維數組

①申請數組空間:

指針變量名=new 類型名[ 下標表達式];

注意: 下標表達式 不是常量表達式,即它的值不必在編譯時確定,可以在運行時確定。

②釋放數組空間:

delete [ ] 指向該數組的指針變量名;

注意:方括號非常重要的,如果delete 語句中少了方括號,因編譯器認爲該指針是指向數組第一個元素的,會產生回收不徹底的問題(只回收了第一個元素所佔空間),加了方括號後就轉化爲指向數組的指針,回收整個數組。delete [ ] 的方括號中不需要填數組元素數,系統自知。即使寫了,編譯器也忽略。

#i nclude <iostream.h>

#i nclude <string.h>

void main(){

     int n;

     char *pc;

     cout<<" 請輸入動態數組的元素個數"<<endl;

     cin>>n; //n 在運行時確定,可輸入17

     pc=new char[n]; // 申請17 個字符(可裝8 個漢字和一個結束符)的內存空間

     strcpy(pc,“ 堆內存的動態分配”);//

     cout<<pc<<endl;

     delete []pc;// 釋放pc 所指向的n 個字符的內存空間

     return ;  }

 

5. 動態一維數組的說明

① 變量n 在編譯時沒有確定的值,而是在運行中輸入,按運行時所需分配堆空間,這一點是動態分配的優點,可克服數組 大開小用 的弊端,在表、排序與查找中的算法,若用動態數組,通用性更佳。一定注意:delete []pc 是將n 個字符的空間釋放,而用delete pc 則只釋放了一個字符的空間;

② 如果有一個char *pc1 ,令pc1=p ,同樣可用delete [] pc1 來釋放該空間。儘管C++ 不對數組作邊界檢查,但在堆空間分配時,對數組分配空間大小是紀錄在案的。

③ 沒有初始化式(initializer ),不可對數組初始化。


6.
指針數組和數組指針

指針類型:

(1)int*ptr;// 指針所指向的類型是int
(2)char*ptr;//
指針所指向的的類型是char
(3)int**ptr;//
指針所指向的的類型是int* (也就是一個int * 型指針)
(4)int(*ptr)[3];//
指針所指向的的類型是int()[3] // 二維指針的聲明

指針數組:

一個數組裏存放的都是同一個類型的指針,通常我們把他叫做指針數組。

比如 int * a[2]; 它裏邊放了2int * 型變量 .

int * a[2]
a[0]= new int[3];
a[1]=new int[3];
delete a[0];
delete a[1];

注意這裏 是一個數組,不能delete [] ;

 

數組指針:

  一個指向一維或者多維數組的指針.

int * b=new int[10];  指向一維數組的指針b ;
注意,這個時候釋放空間一定要delete [] , 否則會造成內存泄露, b 就成爲了空懸指針

int (*b2)[10]=new int[10][10]; 注意,這裏的b2 指向了一個二維int 型數組的首地址.
注意:在這裏,b2 等效於二維數組名,但沒有指出其邊界,即最高維的元素數量,但是它的最低維數的元素數量必須要指定!就像指向字符的指針,即等效一個字符串, 不要把指向字符的指針說成指向字符串的指針。

int(*b3) [30] [20];  // 三級指針――> 指向三維數組的指針;
int (*b2) [20];     //
二級指針;――> 指向二維數組的指針;
b3=new int [1] [20] [30];
b2=new int [30] [20];
刪除這兩個動態數組可用下式:
delete [] b3;  //
刪除(釋放)三維數組;
delete [] b2;  //
刪除(釋放)二維數組;

在堆中建立動態多維數組

new 類型名[ 下標表達式1] [ 下標表達式2]……;

例如:建立一個動態三維數組

float (*cp)[30][20] ;  // 指向一個3020 列數組

                             // 的指針,指向二維數組的指針

cp=new float [15] [30] [20];

      // 建立由1530*20 數組組成的數組;

注意:cp等效於三維數組名,但沒有指出其邊界,即最高維的元素數量,就像指向字符的指針即等效一個字符串,不要把指向字符的指針,說成指向字符串的指針。這與數組的嵌套定義相一致。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章