如何为字符串数组实例变量动态分配空间?

时间:2015-04-07 00:06:35

标签: c++ arrays

我正在尝试使用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&amp;)'中: CommandLine.cpp:29:41:错误:将'char *'赋值给'char * [0]'的不兼容类型

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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>类型的成员,因为你已经用它来临时存储命令行参数。这将是更好的解决方案(并且不易出错)。

答案 2 :(得分: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,没有内存泄漏等。唯一的缺点是你需要两个向量,一个用于字符串数据,另一个用于保存指向每个字符串项的指针,后者用于“类似主体”函数所需的char**类型(在上面的示例中,“main”函数只打印出给出的参数列表)。

现在,当CommandLine对象超出范围时,所有元素都被清除,因为字符串和指针存储在向量中。没有内存泄漏,没有指向错误管理等等。

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