我正在尝试将std::string
转换为char*
(复制而不是转换),因为必须将一些数据传递给相当过时的API。
从表面上看,有很多方法可以做到这一点,但有人建议我这样做是一个看似合理的向量。但是,当我尝试这个时,结果是乱码。代码如下:
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位。
我哪里错了?
答案 0 :(得分:9)
std::vector
的实例本身不是一个字符数组 - 它指向到一个数组。而不是(char*)(&str)
尝试&str[0]
。
从您的gdb输出判断,您还需要将零推到矢量的末尾,然后再将其传递给您的旧API。
答案 1 :(得分: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
}
答案 2 :(得分:2)
您需要做的两件事:
1)使用&amp; str [0]获取向量中第一个字符的地址;这是绝对正常的(如果有点做作),因为标准保证了向量存储器是连续的。你不能简单地写&amp; str,因为那是矢量的地址,它不一定是第一个数据元素的地址。
2)如果要使用标准的c-like函数将字符显示为字符串,请在向量的末尾注入空终止符。在第二点我可能错了; rawStr.end()指向与“我的狗没有鼻子”相关联的隐式空终止符吗?
答案 3 :(得分:0)
&amp; str为您提供指向矢量对象的指针,而不是指向包含的字符串。
如果你想把它打印成C字符串,你需要将0推到最后,然后输出&amp; str [0](它会把你的地址抓到所包含的数组的开头)
但是,这非常难看。你要么创建自己的字符串向量类,继承std :: vector,要么使用一个函数来迭代遍历向量,逐字打印每个元素,你会好得多。修改强>
如果您对C ++ 11有所了解,可以在这里以干净的方式使用带有lambda的for_each:
std::for_each(str.begin(), str.end(), [](char i) -> void {std::cout << i;});