1

由于必须将一些数据传递给相当过时的 API,我正在尝试将 a 转换std::string为(复制而不是强制转换)。char*

从表面上看,有很多方法可以做到这一点,但有人建议我将其作为一个似乎明智的矢量来做。但是,当我尝试这样做时,结果是乱码。代码如下:

const string rawStr("My dog has no nose.");
vector<char> str(rawStr.begin(), rawStr.end());
cout << "\"" << (char*)(&str) << "\"" << endl;

(请注意令人不快的 C 转换 - 使用 static_cast 不起作用,这可能告诉我一些事情)

当我运行它时,我得到:

"P/"

显然不对。我看了一下gdb中的向量

(gdb) print str
$1 = std::vector of length 19, capacity 19 = {77 'M', 121 'y', 32 ' ', 100 'd', 111 'o', 
  103 'g', 32 ' ', 104 'h', 97 'a', 115 's', 32 ' ', 110 'n', 111 'o', 32 ' ', 110 'n', 
  111 'o', 115 's', 101 'e', 46 '.'}

尽管最后没有空终止符,但这看起来是正确的,这是令人担忧的。向量 ( sizeof(str)) 的大小为 24,这表明字符被存储为 8 位。

我哪里错了?

4

4 回答 4

9

的实例std::vector本身并不是一个字符数组——它指向一个数组。而不是(char*)(&str)尝试&str[0]

从您的 gdb 输出来看,您还需要在将向量传递给旧版 API 之前将零推到向量的末尾。

于 2013-05-30T07:56:39.483 回答
7

首先,std::string不包含作为 [ begin(), end()) 覆盖范围内的元素的空终止符。其次,向量的地址不是向量数据的第一个元素的地址。为此,您需要&str[0]str.data()

#include <vector>
#include <string>
#include <iostream>

int main()
{
  const std::string rawStr("My dog has no nose.");
  std::vector<char> str(rawStr.begin(), rawStr.end());
  str.push_back('\0');
  std::cout << "\"" << &str[0] << "\"" << std::endl;
  std::cout << "\"" << str.data() << "\"" << std::endl; // C++11
}
于 2013-05-30T08:01:33.240 回答
2

你需要做两件事:

1) 使用 &str[0] 获取向量中第一个字符的地址;这绝对没问题(如果有点做作),因为标准保证向量内存是连续的。您不能简单地写 &str,因为那是向量的地址,不一定是第一个数据元素的地址。

2) 如果要使用标准的类 c 函数将字符显示为字符串,请在向量的末尾注入一个空终止符。我在第二点上可能是错的;rawStr.end() 是否指向与“我的狗没有鼻子”相关的隐式空终止符?

于 2013-05-30T07:58:39.060 回答
0

&str 为您提供指向向量对象的指针,而不是指向包含的字符串。

如果您希望将其打印为 C 字符串,则需要将 0 推到末尾,然后输出 &str[0] (它将获取包含数组开头的地址)。

不过,这非常丑陋。您最好创建自己的继承 std::vector 的字符串向量类,或者使用精心设计的函数来遍历向量,逐字打印每个元素。

编辑:

如果您熟悉 C++11,则可以在此处以干净的方式使用带有 lambda 的 for_each:

std::for_each(str.begin(), str.end(), [](char i) -> void {std::cout << i;});
于 2013-05-30T08:03:04.457 回答