【问题标题】:Translating std::string to vector<char>将 std::string 转换为 vector<char>
【发布时间】:2013-05-30 07:55:16
【问题描述】:

由于必须将一些数据传递给相当过时的 API,我正在尝试将 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 位。

我哪里出错了?

【问题讨论】:

  • 如果你使用 C++11,传递 &amp;rawStr[0] 没问题,只要它只写到 null 之前。
  • 字符串不包含作为begin()end() 范围内的元素的空终止符。其次,向量的地址不是向量数据的第一个元素的地址。
  • @chris:[citation needed](标准中关于这个问题的措辞非常微妙和古怪,但据我所知,这不能保证是空终止的
  • @jalf,我相信这与 data() 与 C++11 中的 c_str() 相同。如果你有兴趣,已经有一个question关于这个主题。
  • @chris 当然,它们是相同的,但它们都不与&amp;rawStr[0] 相同(并且该问题的答案仅表明内部字符串将在您使用时以空值结尾已经调用了c_str()data()。不能保证它会总是为空终止。

标签: c++ string vector char


【解决方案1】:

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

从您的 gdb 输出来看,您还需要在向量的末尾添加一个零,然后再将其传递给您的旧版 API。

【讨论】:

    【解决方案2】:

    首先,std::string 不包含作为 [begin(), end()) 覆盖范围内的元素的空终止。其次,向量的地址不是向量数据的第一个元素的地址。为此,您需要&amp;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
    }
    

    【讨论】:

      【解决方案3】:

      你需要做的两件事:

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

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

      【讨论】:

        【解决方案4】:

        &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;});
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-05-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-03-02
          • 2014-11-19
          相关资源
          最近更新 更多