【问题标题】:Cleanest way to convert non null terminating c string to terminating c string将非空终止 c 字符串转换为终止 c 字符串的最简洁方法
【发布时间】:2016-03-28 17:43:57
【问题描述】:

我有一些返回非空终止字符串的旧函数。

struct legacy {
    char a[4];  //not null terminated
    char b[20]; //not null terminated 
};

我传递了很多这些 char 数组,我需要一种干净的方法将它们转换为以 null 结尾的。

到目前为止,这就是我正在做的事情:

legacy foo;
std::string a(foo.a, sizeof(foo.a));
std::string b(foo.b, sizeof(foo.b));
bar(foo.a.c_str(), foo.b.c_str());

有没有一种更简洁的方法可以使用类和模板来将此代码简化为...

legacy foo;
bar(make_null_terminated(foo.a), make_null_terminated(foo.b));

【问题讨论】:

  • bar() 只接受const char* 吗?它会保留它们还是 ntbs 的生命周期不必持续到对 bar() 的调用?
  • @Barry bar 只需要一个const char*
  • 你能把它改成其他东西还是你无法控制的?
  • @Barry,很遗憾这超出了我的控制范围。

标签: c++ templates c-strings c++03 null-terminated


【解决方案1】:

应该这样做:

struct make_null_terminated {
    template <size_t sz>
    make_null_terminated(char (&lit)[sz]) : str(lit, sz) {}
    operator const char* () const { return str.c_str(); }
private:
    std::string str;
}

这将允许您以您想要的方式使用它。

EDIT标签编辑后,我去掉了std::beginstd::endl

【讨论】:

    【解决方案2】:

    你可以简单地:

    std::string a(std::begin(foo.a), std::end(foo.a));
    

    【讨论】:

    • std::end 是否假设我们已经有一个空终止字符?
    • 我认为您错过了问题的重点-可以将其封装到函数(模板)中吗?
    • @andre:没有。
    • @andre,它们在 C++03 中也不可用
    • c++03 标签刚刚添加。抱歉我不知道
    【解决方案3】:

    我能想到的最简洁的方法是使用 std::string 的迭代器构造函数,指针是一种迭代器。

    bar(std::string(std::begin(foo.a), std::end(foo.a)).c_str(),
        std::string(std::begin(foo.b), std::end(foo.b)).c_str()); 
    

    这里发生了什么?

    1. 通过复制 foo.a 中的字节并添加尾随零来构造一个字符串(这被封装在 std::string 中)

    2. 同样适用于 foo.b

    3. 在临时字符串上调用方法 c_str() 以获取指向内部以 null 结尾的 c 字符串的指针。

    4. 通话栏

    5. 销毁临时字符串

    【讨论】:

    • 打字太多:)
    • @SergeyA 测量两次,剪切一次。然后,输入多少都没关系 - 你再也不需要触摸它了。
    • 对于需要来自legacy 的数据的函数的每次调用。我相信,OP 不止一个。
    • @SergeyA 你可能是对的。无论如何,您的第二个 +1 来自我。很好的答案。
    • 欣赏好话。 )
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-02
    • 1970-01-01
    • 1970-01-01
    • 2010-11-12
    • 1970-01-01
    • 2014-02-01
    • 1970-01-01
    相关资源
    最近更新 更多