【问题标题】:Convert std::string to char* when string has nulls in middle当字符串中间有空值时,将 std::string 转换为 char*
【发布时间】:2021-11-14 17:56:53
【问题描述】:
char* convert()
{    
    std::string data = "stack\0over\0flow";
    return data.c_str();
}

这将返回指针,并在调用者上从它构建字符串时,它将具有 stack 而不是完整的字符串。在 c++ 11 中是否有不改变输入和返回类型的解决方法? 我想从 char* 重建调用方的整个字符串。

【问题讨论】:

  • 小心:data 超出范围将被销毁。因此,如果返回类型是指针,您的代码将返回一个悬空指针。
  • 哦等等 - 你是对的。 eerorika 下面的回答是最好的指导。
  • @vmario 有点正确,它返回完整的数据字符串——只是如果你想在中间包含 NUL,你必须以不同的方式构造 std::string。
  • 当你得到一个 char* 时你想做什么,你丢失了原始字符串长度的所有信息并且你不能循环直到终止零。这不会有用。

标签: c++ string std


【解决方案1】:

当字符串中间有空值时,将 std::string 转换为 char*

为了将中间有空值的 std::string 转换为 char*,首先必须有一个中间有空值的 std::string。你没有这样的字符串。

因为您使用了构造函数 std::string(const char*),所以您创建的字符串将传递的指针视为指向空终止字符串的第一个元素的指针,因此 std::string 仅包含 "堆栈”。

你可以使用:

const auto& str = "stack\0over\0flow";
std::string data(str, std::size(str) - 1);

这将返回堆栈而不是完整的字符串

如果字符串实际上包含“stack\0over\0flow”,则 c_str 将返回指向完整字符串“stack\0over\0flow”的第一个元素的指针。

如果您将指针视为指向 null 终止 字符串的指针,则第一个 null 终止符将终止以 null 终止的字符串。如果将指针视为指向空终止字符串的指针,则无法避免这种情况。因此,如果您希望避免字符串被第一个空终止符终止,那么不要将其视为指向空终止字符串的指针(例如,当您使用字符串文字作为指向空终止字符串的指针时)示例)。

但是,这主要是一个没有实际意义的问题,因为指向的字符串将被释放,并且在函数返回时返回的指针将悬空。尝试通过悬空指针进行访问将导致未定义的行为。

此外,c_str 始终返回 const char* 而从不返回 char*

【讨论】:

    【解决方案2】:

    为了能够使用带有 \0 的 安全 的完整字符串。您必须将数据放在缓冲区中。 例如。像这样:

    #include <iostream>
    #include <array>
    #include <vector>
    
    template<std::size_t N>
    auto make_buffer(const char(&chars)[N])
    {
        // note returing an object uses RVO and nothing is left dangling.
        std::array<char, N> buffer{};
        for (std::size_t n = 0; n < N; ++n) buffer[n] = chars[n];
        return buffer;
    }
    
    int main()
    {
        auto buffer = make_buffer("stack\0over\0flow");
    
        // this is the closest you can get to having a char*
        // pointing to ALL the data.
        char* data_ptr = buffer.data();
    
        // but you still must rely on the buffer size
        // for correct looping over the valid values!
        for (std::size_t n = 0; n < buffer.size(); ++n)
        {
            std::cout << data_ptr[n];
        }
        std::cout << std::endl;
    
        // But with a buffer like this a range based for loop is recommended
        for (const auto c : buffer)
        {
            std::cout << c;
        }
        std::cout << std::endl;
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2011-05-26
      • 1970-01-01
      • 2010-11-14
      • 2020-04-23
      • 2014-06-24
      • 2018-09-23
      • 2021-07-18
      • 1970-01-01
      • 2013-07-18
      相关资源
      最近更新 更多