如何解决使用循环填充char *数组
我有一个遗留函数,其输入参数类型为const char * array
myfunc(const char* names[]);
我有一组std::set<std::string> mynames;
。该集合已被填充。
我必须将mynames
传递给myfunc
使用基于范围的循环,我有
const char* names[];
int i = 0;
for (const auto &name : mynames)
{
//allocate memory to names here
names[i] = name.c_str();
++i;
}
//call myfunc
myfunc(names);
有更好的方法吗?
解决方法
您没有为names[]
数组分配任何内存。您需要执行以下操作:
const char** names = new const char*[mynames.size()]; // +1 if needed
size_t i = 0;
for (const auto &name : mynames)
{
names[i++] = name.c_str();
}
/* if needed:
names[i] = nullptr;
*/
/* alternatively
std::transform(mynames.begin(),mynames.end(),names,[](const std::string &name){ return name.c_str(); }
);
// if needed :
// names[mynames.size()] = nullptr;
*/
myfunc(names);
delete[] names;
然后可以使用std::vector
代替new[]
进一步简化,例如:
std::vector<const char*> names;
names.reserve(mynames.size()); // +1 if needed
for (const auto &name : mynames)
{
names.push_back(name.c_str());
}
/* if needed:
names.push_back(nullptr);
*/
/* alternatively:
std::vector<const char*> names(mynames.size()); // +1 if needed
std::transform(mynames.begin(),names.begin(),[](const std::string &name){ return name.c_str(); }
);
// if needed:
// names.back() = nullptr;
*/
myfunc(names.data());
,
如果可以重写此功能,请这样做。但是,有很多像这样的长期第三方库,并且您不想尝试将它们弄乱。
您将不得不分配一个临时数据结构,该结构以函数期望的格式提供数据。您将不得不弄清楚它必须存在多长时间。我将在此处显示一个示例,该示例假定您可以跳过分配单个字符串的过程,而只需为它们的指针分配一个数组即可(
)。您没有为指针分配空间,也没有在末尾添加nullptr。请注意,该函数采用原始数组,因此它不知道有多少个名称。几乎可以肯定,期望NULL表示姓氏。
#include <iostream>
#include <string>
#include <set>
// This demonstrates how a legacy function like this might work
int myfunc(const char* names[]) {
if (names) {
int index = 0;
const char* name = names[index];
// Notice that this function cannot know how many names there are.
// The function documentation will almost certainly tell you
// to add a NULL as the last entry.
while (name) {
std::cout << name << std::endl;
name = names[++index];
}
}
return 0;
}
int main()
{
const char * legacy [] = {
"one","two","three",nullptr,};
std::cout << "legacy" << std::endl;
myfunc(legacy);
std::set<std::string> modern { "one","three" };
// this temp structure is valid as long as it is
// allocated,and original set doesn't change
// although you probably should allocate and clean up
// a copy of each string within this temp array.
const char ** temp = new const char* [modern.size()+1];
int index = 0;
for (const auto &name : modern) {
temp[index++] = name.data();
}
temp[index] = nullptr;
// if myfunc just uses them and exits,you're okay
// if it remembers any of the pointers for later,that would be unfortunate
std::cout << "using temp" << std::endl;
myfunc(temp);
// delete what we allocated. The pointers inside are owned by the set,so we don't care about that
delete [] temp;
return 0;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。