如何将字符串向量传递给foo(char const *const *const)函数?

8

编辑: 在实施James Hopkin的建议后,我仍然收到“无效名称'null'”的警告,这比那些奇怪的字符要好得多。然后,我回头再次阅读了库文档,结果发现对于该特定函数,它的参数应该比aNames的大小多一个非NULL字符串元素。这个额外的字符串有一些其他的目的。添加了一个字符串后,代码运行良好。这全是我的错,我非常抱歉。

原帖:

您好,

这是我第一次发帖,请多关照。我在论坛中搜索并谷歌过,但仍然找不到答案。这个问题已经困扰我一天以上了,请给我一些帮助。谢谢。

我需要将一个字符串向量传递给一个库函数foo(char const *const *const)。我不能传递&Vec[0],因为它是一个指向字符串的指针。因此,我有一个数组,并将c_str()传递给该数组。以下是我的代码(aNames是字符串向量):

const char* aR[aNames.size()];

std::transform(aNames.begin(), aNames.end(), aR, 
                boost::bind(&std::string::c_str, _1));
foo(aR);

然而,它似乎会导致一些未定义的行为:
如果我运行以上代码,则函数foo会抛出一些警告,指出aR中存在非法字符('èI'等等)。
如果我在函数foo之前像这样打印aR:
std::copy(aR, aR+rowNames.size(), 
          std::ostream_iterator<const char*>(std::cout, "\n"));
foo(aR);

然后,一切都好了。

  1. 转换是否会导致未定义行为?如果是,为什么?

  2. 将字符串向量传递给foo(char const *const *const)的正确方法是什么?

3个回答

5

由于foo只接受指针,我的猜测是它需要一个以NULL结尾的数组。为aR分配一个额外的元素,并将其赋值为NULL。

我的建议是:

std::vector<const char*> c_strings;
c_strings.reserve(aNames.size() + 1);

std::transform(
    aNames.begin(), aNames.end(),
    std::back_inserter(c_strings), 
    boost::bind(&std::string::c_str, _1)
    );

c_strings.push_back(0);
foo(&c_strings[0]);

+1 好猜测。事实上,找到“foo”函数的数组大小的唯一可能性就是找到空指针。 - Kirill V. Lyadvinsky
是的,猜得不错!除非foo函数签名不是真实的。@user347208:那是确切的函数签名吗? - neuro
非常感谢您的帮助!@neuro:确切的函数签名是int foo(const char * filename, char const *const *const rowNames, char const *const *const columnNames)。然而,正如我在我的编辑中所说的那样,很抱歉我没有仔细阅读文档,浪费了您的时间。无论如何,非常感谢大家的帮助! - EXP0

1

试试这个:

std::vector<char*> arr(aNames.size()+1); 
for(size_t i = 0; i < aNames.size(); ++i) 
    arr[i] = aNames[i].c_str();
arr[arr.size()-1] = NULL; // just in case
foo(&arr[0]);

1
无法编译 - c_str 返回一个 const char* - James Hopkin
好的。将向量更改为保存“const char*”元素现在可以编译通过。 - Remy Lebeau

1

在我看来,这似乎是正确的。c_str创建了一个以null结尾的char数组,该数组在下一个非const字符串操作之前是常量。您将c_str指针存储在const char*数组中。

我不是boost专家,所以问题可能出在那里,但我猜测您在向量中的字符串使用的编码与函数foo中预期的编码不兼容。

从编码角度检查您的代码。

我的意见。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接