2015-04-07 51 views
0

我正在嘗試使用C++創建一個簡單的shell程序。我有一個帶實例變量的CommandLine類,用於參數個數和這些參數的數組。如何動態地爲字符串數組實例變量分配空間?

private: 
int argc; 
char *argv[]; 

這裏是我的CommandLine類的構造函數我的定義代碼:

CommandLine::CommandLine(istream& in) {  
    string cmd; 
    getline(in, cmd); 
    vector<string> args; 
    string arg; 
    istringstream iss(cmd); 
    while(iss >> arg) args.push_back(arg); 
    argc = args.size(); 
    argv = (char*) malloc(argc*sizeof(argv)); 
    } 

當我嘗試編譯,我得到這個錯誤信息:

CommandLine.cpp:在構造函數'CommandLine :: CommandLine(std :: istream &)': CommandLine.cpp:29:41:錯誤:賦予'char *'到'char * [0]'的不兼容類型

+0

另外,線29是在構造中的最後一行,即「的argv =(字符*)malloc的(的argc *的sizeof(argv的) );」 – reubonwry

+0

'char * argv [];'這是非標準的C++。數組必須使用編譯時表達式聲明,而不是留空。你可以簡單地使用'std :: vector '代替,那麼當我們處於這個狀態時,給你這個問題的代碼就是'argv.resize(argc);'而不是'malloc' – PaulMcKenzie

+1

:'std :: vector '... –

回答

0

從改變你的成員定義:

char *argv[];

char** argv;

對於你的任務,他們將功能兼容。然後,分配空間是這樣的:

argc = args.size(); 
argv = (char**)malloc(argc * sizeof(char*)); 

if(!args.empty()) 
{ 
    for(int n = 0; n < argc; ++n) 
    { 
    const string& src = args[n]; 
    char*& current = argv[n]; 

    current = (char*)malloc((src.length() + 1) * sizeof(char)); 
    memcpy(current, src.c_str(), (src.length() + 1) * sizeof(char)); 
    } 
} 

不過,我不明白你爲什麼不能使用std::vector<string>類型的成員,因爲你已經用它來臨時存儲命令行參數。這將是更好的解決方案(並且不太容易出錯)。

+0

當我做你的建議的更改,並使用從上面的代碼中,我得到這些錯誤消息: CommandLine.cpp:在構造 '的CommandLine ::的CommandLine(的std :: istream的&)': CommandLine.cpp :23:44:錯誤:在'char **'賦值爲'char ** [0]'時不兼容類型' CommandLine.cpp:30:26:錯誤:類型'char *&'的引用無效初始化'char **'類型的表達式 – reubonwry

+0

這些錯誤表示您沒有正確更新您的代碼。如果'argv [n]'被檢測爲'char **'類型,'argv'成員必須被聲明爲'char ** argv []'。它需要是'char ** argv'(沒有括號)。 –

+0

謝謝,這樣做!忘了這個簡單的修復 – reubonwry

0

你應該使用:char **argv;

和分配如下:

argv = new char*[argc]; //needed to be deleted at destructor 
for (int i=0; i< argc; i++){ 
    argv[i]= strdup(args[i].c_str()); //needed to be freed at destructor 
} 

更好的解決方案是使用vector<string> args;作爲成員,而不是argv

0

使用mallocnew創建argv*數組的想法是一種混亂的方法,可能會導致內存泄漏。

一種方法,將使用mallocnew將是這是自由的內存泄漏或存儲器直接分配:

首先,同時存儲一個字符數組的矢量,和指針的向量到char:

class CommandLine 
{ 
    typedef std::vector<char> CharArray; 
    typedef std::vector<CharArray> ArgumentVector; 
    ArgumentVector argvVec; 
    std::vector<char *> argv; 
    public: 
     CommandLine(std::stream& in); 
}; 

這是argv矢量,它最終將保存命令行參數所需的char *。其他ArgumentVector成員的原因是爲了確保這些字符串不會超出範圍(只要CommandLine對象處於活動狀態)。

一旦你有了這個,那麼函數放置在argv向量參數變得更安全:

#include <vector> 
#include <algorithm> 
#include <fstream> 
#include <iostream> 
#include <string> 
#include <sstream> 
//... 
using namespace std; 

void my_command_line(int numArgs, char** args); 

CommandLine::CommandLine(std::istream& in) 
{ 
    string cmd; 
    getline(in, cmd); 
    string arg; 
    istringstream iss(cmd); 
    while (iss >> arg) 
    { 
     // create an entry in our string vector. This basically 
     // replaces the call to allocate for each new string 
     argvVec.push_back(CharArray(arg.begin(), arg.end())); 

     // make sure we null-terminate the last string we added. 
     argvVec.back().push_back(0); 

     // add the pointer to this string to the argv vector 
     argv.push_back(argvVec.back().data()); 
    } 

    // call the alternate command-line function 
    my_command_line(argv.size(), argv.data()); 
} 

void my_command_line(int numArgs, char** args); 
{ 
    for (int i = 0; i < numArgs; ++i) 
     std::cout << "argument " << i << ": " << args[i] << std::endl; 
} 

int main() 
{ 
    ifstream ifs("Test.txt"); 
    CommandLine test(ifs); 
}  

注意這裏是malloc沒有來電,來new沒有電話,沒有內存泄漏等。唯一的缺點是你需要兩個矢量,一個用於字符串數據,另一個用於保存指向每個字符串項的指針,後者用於類似「main-like」函數所需的char**類型(在上例中,「main」函數只是輸出它給出的參數列表)。

現在,當CommandLine對象超出範圍時,所有元素都會被清除,因爲字符串和指針都存儲在向量中。沒有內存泄漏,沒有指針採取不適當等

直播示例:http://ideone.com/0tCfYa

相關問題