从字符串向量初始化2d数组的最简单方法是什么?

What is the easiest way to initialize a 2d array from a vector of strings?

本文关键字:最简单 方法 是什么 数组 字符串 向量 初始化 2d      更新时间:2023-10-16

我有:

vector<string> myVector = {0};
myVector.push_back("first");
myVector.push_back("second");
char *list[] = ????

我希望它被初始化就像我在做这个

char *list[] = { "first", "second", NULL };

我知道我可以根据向量的大小和向量(list[v.size()+1][longest_string_in_vector])中最长字符串的大小开始分配内存,但我想看到我没有想到可能更容易/更快的东西。

如果遗留代码需要char **,那么要创建一个变量列表,您可以创建一个向量,就像您最初在问题中所做的那样。

之后,创建一个std::vector<char *>,其中指针是每个项目的向量内的指针。当然,您必须确保向量没有超出作用域或调整大小。在创建std::vector<char *>之前必须完全"设置"。

另外,既然你确定遗留函数不会试图改变发送给它的字符串,我们应该去掉字符串的"constness"。

#include <vector>
#include <string>
#include <iostream>
void legacy_function(char **myList) 
{
     for (int i = 0; myList[i]; ++i)
          std::cout << myList[i] << "n";
}
using namespace std;
int main()
{
    vector<string> myVector;
    myVector.push_back("first");
    myVector.push_back("second");
    //...
    // create the pointer vector
    vector<char *> myPtrVector;
    // add pointer to string to vector
    for (size_t i = 0; i < myVector.size(); ++i)
       myPtrVector.push_back(const_cast<char*>(myVector[i].c_str()));
    // stick the null at the end
    myPtrVector.push_back(NULL);
    // ...
    // call legacy function
    legacy_function(&myPtrVector[0]);
}  
基本上,我们在vector容器中创建了string对象,并创建了另一个vector容器来存储指向string对象的指针。

注意,函数legacy_function接受一个char **,我们所需要做的就是把指针向量中第一个元素的地址传递给它。

实例:http://ideone.com/77oNns

编辑:与其让代码散布在程序的不同区域,从代码组织的角度来看,更好的方法是封装数组的创建:
#include <vector>
#include <string>
class CharPtrPtr
{
   std::vector<std::string> m_args;
   std::vector<char *> m_argsptr;
   public:
       void add(const std::string& s) { m_args.push_back(s); }
       char ** create_argsPtr() 
       { 
          m_argsptr.clear();
          for (size_t i = 0; i < m_args.size(); ++i)
             m_argsptr.push_back(const_cast<char*>(m_args[i].c_str()));
          m_argsptr.push_back(NULL);
          return &m_argsptr[0]; 
       }
       char **get_argsPtr() { return m_argsptr.empty()?NULL:&m_argsptr[0]; }
       void clear_args() { m_args.clear(); m_argsptr.clear(); }
};

#include <iostream>
void legacy_function(char **myList) 
{
    for (int i = 0; myList[i]; ++i)
        std::cout << myList[i] << "n";
}
int main()
{
    CharPtrPtr args;
    args.add("first");
    args.add("second");
    legacy_function(args.create_argsPtr());
}     

实例:http://coliru.stacked-crooked.com/a/834afa665f054a1f

我试过这两种方法,

1。手动初始化

char *list[] = { (char*)&myVector[0][0], (char*)&myVector[1][0] };

2。在循环中初始化

char **list2 = new char*[ myVector.size() ];
for ( unsigned int i = 0; i < myVector.size(); ++i ) {
    list2[ i ] = (char*)&myVector[ i ][0];
}

然而,这些列表只有指向vector中的每个字符串的指针,实际上没有副本。如果您更改字符串,您将看到列表中的更改。但是如果你清空vector,那么列表将有一个悬空指针。

3。如果需要字符串的副本,则

char **list = new char*[ myVector.size() ];
for ( unsigned int i = 0; i < myVector.size(); ++i ) {
    list[ i ] = new char[myVector[i].size()+1];
    strcpy( list[ i ], &myVector[i][0] );
}

我不会写这段代码,但是,这就是…