std :: vector 到char *数组
我有一个std::vector
,我需要将它用于读取char* foo
的C
函数的参数。 我已经看到 如何将std::string
转换为char*
。 作为C++
的新手,我正在尝试拼凑如何在向量的每个元素上执行此转换并生成char*
数组。
我已经看到了几个密切相关的SO问题,但大多数似乎都说明了转向另一个方向并创建std::vector
。
您可以使用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 vs; vs.push_back("std::string"); vs.push_back("std::vector "); vs.push_back("char*"); vs.push_back("std::vector"); std::vector 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 char* std::vector
在线演示: http : //ideone.com/U6QZ5
你可以在任何需要char**
地方使用&vc[0]
。
请注意,由于我们使用new
为每个std::string
分配内存(在convert
函数中),我们最后要释放内存。 这使您可以灵活地更改矢量vs
; 你可以push_back
更多字符串,删除vs
的现有字符串和vc
(即vector
仍然有效!
但是如果你不想要这种灵活性,那么你可以使用这个convert
函数:
const char *convert(const std::string & s) { return s.c_str(); }
你必须将std::vector
更改为std::vector
。
现在转换后,如果通过插入新字符串来更改vs
,或者从中删除旧字符串,那么vc
所有char*
都可能变为无效。 这是一个重点。 另一个重要的一点是,您不再需要在代码中使用delete vc[i]
了。
你能做的最好的事情就是分配一个const char*
的std::vector
const char*
和你的vector相同的大小。 然后,遍历向量的每个元素,调用c_str()
以获取字符串数组并将其存储在数组的相应元素中。 然后,您可以将指针传递给此向量的第一个元素到相关函数。
代码如下所示:
std::vector 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::strings
获取const char*
和调用C函数的时间之间,不能允许调整字符串的原始向量。
这应该工作:
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函数不修改字符串,则可能没有必要复制字符串。 如果你能详细说明你的界面是什么样的,我相信我们可以为你提供更好的帮助。
一个C ++ 0x解决方案,其中std::string
元素保证连续存储:
std::vector 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 pointer; std::vector 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); });
const char *也与char *相同,只在const_ness中有所不同,你的接口方法接受const和非const字符串。
c_str()不返回const char吗? 如果我只需要一个char *,那会有问题吗?
是的,它返回一个const字符串,没有任何问题
const char*a="something"; ////whatever it is here const char* retfunc(const char*a) { char*temp=a; //process then return temp }
许多人都不接受返回本地对象,并且这个小例子是按原样提供的。
向量的元素是连续存储的 ,因此最好和最简单的方法是:
std::vector v; char* c = &v[0];