C++ fmtlib:如何将双精度转换为现有的 wchar_t 缓冲区?

Posted

技术标签:

【中文标题】C++ fmtlib:如何将双精度转换为现有的 wchar_t 缓冲区?【英文标题】:C++ fmtlib : How to convert a double to existing wchar_t buffer? 【发布时间】:2020-03-31 09:18:00 【问题描述】:

我正在考虑从 snprintf 及其同类过渡到 fmtlib。 想象一下这个虚构的代码:

class CFoo

  size_t  m_szLen0;
  wchar_t m_pwcDst[123];
  ...

public:
  void Bar(double dValue, uint8 u8TotDecimals)
  
    m_szLen += swprintf_s(&m_pwcDst[m_szLen], _countof(m_pwcDst)-m_szLen, L"%.*f", u8TotDecimals, dValue);
  
;

如何在不复制 std::wstring 或 fmt_memory_buffer 的情况下将其转换为 fmtlib? 所以,我希望 fmt::format_to 使用我现有的缓冲区。

【问题讨论】:

你能在minimal reproducible example那里你想要避免的副本吗? 类似这样的东西:``` std::wstring wstrTmp = fmt::format(L":.f", dValue, u8TotDecimals); wcsncpy(m_pwcDst, _countof(m_pwcDst)-m_u32Len, wstrTmp.c_str(); m_u32Len += wstrTmp.length(); ```为什么'源代码'标记在这条评论中不起作用?!?应该是像源代码一样概述。 这不是minimal reproducible example。来自链接:“您的代码示例应该是......完整 - 提供其他人需要在问题本身中重现您的问题的所有部分 本站使用问答格式,请不要在问题框中填写答案。您可以在答案框中写下答案。 (我已经回滚了) 【参考方案1】:

fmt 等效于 swprintf_sformat_to_n,可以按如下方式使用:

auto result = fmt::format_to_n(buffer, buffer_size, ":.", value, precision);

在您的示例中,valuedValueprecisionu8TotDecimalsresult.out 将为您提供指向输出末尾的指针,result.size 将提供总输出大小(如果输出未截断)(类似于 snprintf)。

【讨论】:

【参考方案2】:

fmtlib 中与swprintf_s() 最接近的函数是fmt::format_to_n()。但是,它会返回 写入的字符数,因此您必须小心使用它。下面是它的外观:

void CFoo::Add(double dValue, uint8 u8TotDecimals)

    if(pwcSrc) 
        auto space_left = _countof(m_pwcDst) - m_u32Len;
        auto result = fmt::format_to_n(&m_pcwDst, space_left, ":.f", u8TotDecimals, dValue);
        m_u32Len += std::min(result.size, space_left);
    

但是,如果您想以正确的 C++ 方式执行操作,请尝试查看是否可以将目标缓冲区更改为 std::wstring,然后直接添加到该缓冲区,如下所示:

void CFoo::Add(double dValue, uint8 u8TotDecimals)

    if(pwcSrc)
        m_pwsDst += fmt::format(L":.f", u8TotDecimals, dValue);

【讨论】:

嗯...我有点困惑。您的 :.*f 示例因异常而崩溃。仅当我删除指示长度的星号时,我才不会收到异常错误。 啊我忘了修复示例代码,确实它必须是 而不是*【参考方案3】:

这并不像我希望的那样简单/清晰,所以很遗憾。但是,这可能会做我想要的:

class CFoo

  size_t  m_szLen0;
  wchar_t m_pwcDst[123];
  ...

public:
  void Bar(double dValue, uint8 u8TotDecimals)
  
    m_pwcDst[m_szLen += std::min(_countof(m_pwcDst)-m_szLen-1, fmt::format_to_n(&m_pwcDst[m_szLen], _countof(m_pwcDst)-m_szLen, FMT_STRING(L":.f"), dValue, u8TotDecimals).size)] = L'\0';
  
;

【讨论】:

对了,不应该是fmt::format_to_n(n_pwcDst + m_u32Len, ...)吗?并且.size 返回在没有截断的情况下打印的大小。您不能安全地使用它来添加终止符。 我把它改成了 &m_pwcDst[m_u32Len]。关于尺寸......哦哦哦不!我得调查一下。

以上是关于C++ fmtlib:如何将双精度转换为现有的 wchar_t 缓冲区?的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中使用 boost::lexical_cast 将双精度转换为字符串?

如何将双精度向量传递给构造函数,然后在子类中访问其数据(在 C++ 中)?

如何将双精度值从 json 转换为函数

如何将双精度数组转换为 JS 数组?

如何防止 PHP SoapClient 将双精度值转换为科学计数法?

如何使用带有 0x 的 javascript 将双精度转换为十六进制 [重复]