std::向量转换为 char* 数组

发布于 2024-11-29 15:35:59 字数 543 浏览 0 评论 0原文

我有一个 std::vector,我需要将其用于读取 char* fooC 函数参数。我见过如何std::string 转换为 char*。作为 C++ 的新手,我正在尝试拼凑如何对向量的每个元素执行此转换并生成 char* 数组。

我见过几个密切相关的 SO 问题,但大多数似乎都说明了走向另一个方向并创建 std::vector 的方法。

I have a std::vector<std::string> that I need to use for a C function's argument that reads char* foo. I have seen how to convert a std::string to char*. As a newcomer to C++, I'm trying to piece together how to perform this conversion on each element of the vector and produce the char* array.

I've seen several closely related SO questions, but most appear to illustrate ways to go the other direction and create std::vector<std::string>.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

め七分饶幸 2024-12-06 15:35:59

您可以使用 std::transform 作为:

std::transform(vs.begin(), vs.end(), std::back_inserter(vc), convert);  

这需要您将 convert() 实现为:

char *convert(const std::string & s)
{
   char *pc = new char[s.size()+1];
   std::strcpy(pc, s.c_str());
   return pc; 
}

测试代码:

int main() {
       std::vector<std::string>  vs;
       vs.push_back("std::string");
       vs.push_back("std::vector<std::string>");
       vs.push_back("char*");
       vs.push_back("std::vector<char*>");
       std::vector<char*>  vc;

       std::transform(vs.begin(), vs.end(), std::back_inserter(vc), convert);   

       for ( size_t i = 0 ; i < vc.size() ; i++ )
            std::cout << vc[i] << std::endl;

       for ( size_t i = 0 ; i < vc.size() ; i++ )
            delete [] vc[i];
}

输出:

std::string
std::vector<std::string>
char*
std::vector<char*>

在线演示: http://ideone.com/U6QZ5

您可以在任何需要 char** 的地方使用 &vc[0]

请注意,由于我们使用 new 为每个 std::string 分配内存(在 convert 函数中),因此我们必须取消分配记忆在最后。这使您可以灵活地更改向量 vs;您可以向其中 push_back 更多字符串,从 vsvc 中删除现有字符串(即 vector< /code> 仍然有效!

但是如果您不想要这种灵活性,那么您可以使用这个 convert 函数:

const char *convert(const std::string & s)
{
   return s.c_str();
}

并且您必须更改 std::vector;std::vector

现在,在转换之后,如果您通过插入新字符串或从中删除旧字符串来更改 vs,则所有内容vc 中的 char* 可能会变得无效,这是另一个重要的一点,您不需要使用 delete vc[i]。 在你的代码中了。

You can use std::transform as:

std::transform(vs.begin(), vs.end(), std::back_inserter(vc), convert);  

Which requires you to implement convert() as:

char *convert(const std::string & s)
{
   char *pc = new char[s.size()+1];
   std::strcpy(pc, s.c_str());
   return pc; 
}

Test code:

int main() {
       std::vector<std::string>  vs;
       vs.push_back("std::string");
       vs.push_back("std::vector<std::string>");
       vs.push_back("char*");
       vs.push_back("std::vector<char*>");
       std::vector<char*>  vc;

       std::transform(vs.begin(), vs.end(), std::back_inserter(vc), convert);   

       for ( size_t i = 0 ; i < vc.size() ; i++ )
            std::cout << vc[i] << std::endl;

       for ( size_t i = 0 ; i < vc.size() ; i++ )
            delete [] vc[i];
}

Output:

std::string
std::vector<std::string>
char*
std::vector<char*>

Online demo : http://ideone.com/U6QZ5

You can use &vc[0] wherever you need char**.

Note that since we're using new to allocate memory for each std::string (in convert function), we've to deallocate the memory at the end. This gives you flexibility to change the vector vs; you can push_back more strings to it, delete the existing one from vs, and vc (i.e vector<char*> will still be valid!

But if you don't want this flexibility, then you can use this convert function:

const char *convert(const std::string & s)
{
   return s.c_str();
}

And you've to change std::vector<char*> to std::vector<const char*>.

Now after the transformation, if you change vs by inserting new strings, or by deleting the old ones from it, then all the char* in vc might become invalid. That is one important point. Another important point is that, you don't need to use delete vc[i] in your code anymore.

暗藏城府 2024-12-06 15:35:59

您能做的最好的事情就是分配一个与您的向量大小相同的 const char*std::vector 。然后,遍历向量的每个元素,调用 c_str() 来获取字符串数组并将其存储为数组的相应元素。然后,您可以将该向量的第一个元素的指针传递给相关函数。

代码如下所示:

std::vector<const char *> cStrArray;
cStrArray.reserve(origVector.size());
for(int index = 0; index < origVector.size(); ++index)
{
  cStrArray.push_back(origVector[index].c_str());
}

//NO RESIZING OF origVector!!!!

SomeCFunction(&cStrArray[0], cStrArray.size());

请注意,您不能允许在从 std 获取 const char* 之间调整原始字符串向量的大小::strings,以及调用 C 函数的时间。

The best you can do is allocate an std::vector of const char* the same size as your vector. Then, walk each element of the vector, calling c_str() to get the string array and storing it the corresponding element of the array. Then you can pass the pointer to the first element of this vector to the function in question.

The code would look like this:

std::vector<const char *> cStrArray;
cStrArray.reserve(origVector.size());
for(int index = 0; index < origVector.size(); ++index)
{
  cStrArray.push_back(origVector[index].c_str());
}

//NO RESIZING OF origVector!!!!

SomeCFunction(&cStrArray[0], cStrArray.size());

Note that you cannot allow the original vector of strings to be resized between the time you fetch the const char*s from the std::strings, and the time you call the C-function.

醉酒的小男人 2024-12-06 15:35:59

这应该有效:

char ** arr = new char*[vec.size()];
for(size_t i = 0; i < vec.size(); i++){
    arr[i] = new char[vec[i].size() + 1];
    strcpy(arr[i], vec[i].c_str());
}

编辑:

假设 vec 仍然具有正确数量的元素,以下是释放这些数据结构的方法,如果您的 C 函数以某种方式修改了该数组,您可能需要以另一种方式获取大小。

for(size_t i = 0; i < vec.size(); i++){
    delete [] arr[i];
}
delete [] arr;

再次编辑:

如果您的 C 函数不修改字符串,则可能不需要复制字符串。如果您能详细说明您的界面是什么样子,我相信我们可以为您提供更好的帮助。

This should work:

char ** arr = new char*[vec.size()];
for(size_t i = 0; i < vec.size(); i++){
    arr[i] = new char[vec[i].size() + 1];
    strcpy(arr[i], vec[i].c_str());
}

EDIT:

Here's how you would free these data structures assuming vec still has the correct number of elements, if your C function modifies this array somehow you may need to get the size another way.

for(size_t i = 0; i < vec.size(); i++){
    delete [] arr[i];
}
delete [] arr;

EDIT Again:

It may not be necessary to copy the strings if your C function does not modify the strings. If you can elaborate on what your interface looks like I'm sure we could provide you with better help.

燃情 2024-12-06 15:35:59

C++0x 解决方案,其中 std::string 的元素保证连续存储:

std::vector<std::string> strings = /* from somewhere */;
int nterms = /* from somewhere */;

// using std::transform is a possibility depending on what you want
// to do with the result of the call
std::for_each(strings.begin(), string.end(), [nterms](std::string& s)
{ ModelInitialize(&s[0], nterms); }

如果函数 null 终止其参数,则在调用 (s.begin(), s.end()) 可能没有意义。您可以进行后处理来解决这个问题:

s = std::string(s.begin(), std::find(s.begin(), s.end(), '\0'));

一个更复杂的版本,将每个字符串单独复制到 char[] 中:

typedef std::unique_ptr<char[]> pointer;
std::vector<pointer> args;
std::transform(strings.begin(), strings.end()
               , std::back_inserter(args)
               , [](std::string const& s) -> pointer
{
    pointer p(new char[s.size()]);
    std::copy(s.begin(), s.end(), &p[0]);
    return p;
});

std::for_each(args.begin(), args.end(), [nterms](pointer& p)
{ ModelInitialize(p.get(), nterms); });

A C++0x solution, where elements of std::string are guaranteed to be stored contiguously:

std::vector<std::string> strings = /* from somewhere */;
int nterms = /* from somewhere */;

// using std::transform is a possibility depending on what you want
// to do with the result of the call
std::for_each(strings.begin(), string.end(), [nterms](std::string& s)
{ ModelInitialize(&s[0], nterms); }

If the function null terminates its argument, then after the call (s.begin(), s.end()) might not be meaningful. You can post-process to fix that:

s = std::string(s.begin(), std::find(s.begin(), s.end(), '\0'));

A more elaborate version that separately copies each string into a char[]:

typedef std::unique_ptr<char[]> pointer;
std::vector<pointer> args;
std::transform(strings.begin(), strings.end()
               , std::back_inserter(args)
               , [](std::string const& s) -> pointer
{
    pointer p(new char[s.size()]);
    std::copy(s.begin(), s.end(), &p[0]);
    return p;
});

std::for_each(args.begin(), args.end(), [nterms](pointer& p)
{ ModelInitialize(p.get(), nterms); });
所谓喜欢 2024-12-06 15:35:59

const char* 也与 char* 相同,只是 const_ness 不同,您的接口方法既接受 const 字符串,也接受非 const 字符串。

c_str() 不是返回 const char 吗?如果我只是
需要一个字符*?

是的,它返回一个 const 字符串,不,应该没有问题

const char*a="something";
////whatever it is here
const char* retfunc(const char*a)
{
   char*temp=a;
   //process then return temp
}

返回本地对象不被很多人接受,这个小例子是按原样提供的。

const char* is also the same as char*, only different in the const_ness, your interface method accepts both const and non-const string.

Doesn't c_str() return a const char? Will that be a problem if I just
need a char*?

Yes, it returns a const string and no there should no problem

const char*a="something";
////whatever it is here
const char* retfunc(const char*a)
{
   char*temp=a;
   //process then return temp
}

Returning a local object is n't accepted by many people andthis tiny example is provided as an as-is.

[旋木] 2024-12-06 15:35:59

向量的元素连续存储,所以最好、最简单的方法是:

std::vector<char> v;
char* c = &v[0];

The elements of a vector are stored contiguously, so the best and easy way is:

std::vector<char> v;
char* c = &v[0];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文