C++ Primer 4.34練習要求將存在vector<string>中的string取出,存入另外的字元數組中,並用一個字元指標數組存放每個字元數組的首地址。
動態分配一個字元數組不難,用
char *ptr = new char[N];
就可以了,但是如果想分配一個字元指標數組(一個數組,裡面的每個元素存放著指向其他字元數組的指標),就稍稍需要改變一下。
先把這道習題我做的代碼貼一下,再對動態分配字元指標數組的方法做分析:
/******************************************************* * C++ Primer 4.34 4.35習題 * *編寫程式讀入一組 string 類型的資料,並將它們儲存在 * *vector 中。接著,把該 vector 對象複製給一個字元指標數* *組。為 vector 中的每個元素建立一個新的字元數組,並把 * *該 vector 元素的資料複製到相應的字元數組中,最後把指 * *向該數組的指標插入字元指標數組。 * *******************************************************/#include "stdafx.h"#include <iostream>#include <string>#include <vector>using namespace std;int _tmain(int argc, _TCHAR* argv[]){vector<string> ivec;ivec.push_back("Hello world");ivec.push_back("Hello everybody!");ivec.push_back("Hello my family!");vector<string>::size_type size = ivec.size();vector<string>::iterator itr = ivec.begin();vector<string>::iterator end = ivec.end();vector<string>::size_type vSize = ivec.size(); // vector的大小char **chars = new char* [vSize]; // 動態分配字元指標數組 // 賦值操作左邊有兩個星號可理解為chars本身的元素是一個char*型, // new操作符又返回了一個指標指向字元數組,所以是char **chars // 注意賦值的右側不能是new (char*)[vSize],沒有在new後面加()的文法。 int i = 0;while(itr != end) {string str = *itr; // 從vector中得到下一個stringconst char* strContent = str.c_str(); // 將string轉換為c風格字串size_t strLength = strlen(strContent); // 求字串長度,不包含null字元char *strArray = new char[strLength + 1]; // 為當前字串動態分配一個數組 chars[i] = strArray; // 記錄這個字元數組的首地址 // chars[i]相當與*(chars + i)for(int k = 0; k != strLength + 1; k++) { // 將字串的內容拷貝到新的數組中strArray[k] = strContent[k];}++itr;++i;}for(int j = 0; j != 3; j++) { // 顯示各字串cout << chars[j] << endl;delete [] chars[j]; // 釋放字元數組} delete [] chars; // 釋放字元指標數組return 0;}
這段代碼根據vector<string>中元素的個數動態分配指標數組,採用的文法為:
char **chars = new char* [vSize]; // 動態分配字元指標數組
我最初奇怪指派陳述式的左側為什麼是兩個*操作符,命名返回的是一個指向數組的指標嘛。但是後來一想,char **chars可以這樣理解:char* (*ptr),即new返回的是一個指向數組的指標(*ptr),其中的每個元素是char*型的,這樣就好理解了。在這之後,我想要更清楚的展示new的是一個字元指標數組,所以畫蛇添足的寫了下面這句
char **chars = new (char*) [vSize];
這時編譯器報錯了,我查了一些資料,比較好的一個解釋是new後面不能跟(),c++標準中沒有這樣的文法。因此即便是寫成
int *p = new (int)[N];
都是錯誤的。
在為chars的元素賦值時,用的是
chars[i] = strArray;
將字元數組的首地址賦給了chars的第i個元素,它等價於
*(chars + i) = strArray
在輸出字串時,是cout << chars[j] 而不是 cout << *chars[j] 這是比較基礎的了,chars[j]給除了一個字元數組的首地址,輸出的是從這個地址到第一個'\0'中間的內容,而*chars[j]給出的是字元數組首地址這個元素,所以只輸出數組的第一個字元。
最後值得注意的是delete一個數組空間的時候,不要忘記是delete []。