【问题标题】:How to convert a float to a string regardless of regional settings?无论区域设置如何,如何将浮点数转换为字符串?
【发布时间】:2009-02-03 15:10:04
【问题描述】:

我的产品面向葡萄牙语受众,其中逗号是十进制符号。我通常使用 CString::Format 将数字输入字符串,它考虑了计算机的区域设置。虽然总的来说这是一个很好的方法,但我在格式化 SQL 查询时遇到了问题,例如:

CString szInsert;
szInsert.Format("INSERT INTO Vertices (X, Y) VALUES (%f, %f)", pt.X, pt.Y);

当值被传递时,我得到这个字符串是一个不正确的查询:

INSERT INTO Vertices (X, Y) VALUES (3,56, 4,67)

如何在这些字符串中强制将点作为十进制符号,而不更改区域设置并且不必为每个浮点值创建专门的字符串?

注意:这是一个一般性问题,而不是 SQL 问题。

【问题讨论】:

    标签: c++ mfc formatting locale


    【解决方案1】:

    坏主意,你真的应该使用准备好的语句。仅使用数字进行 SQL 注入并非易事,但 CString::Format 并不是进行参数绑定的正确方法。

    (MFC 和 SQL 已经有一段时间了 - 事实证明这是隐藏得非常好。我开始看到我们如何以 SQL 注入错误告终,感谢 Microsoft。使用原始 ODBC,您可以使用 SQLPrepare 创建一个语句(一次) .为你要填写的2个参数传递?。随后,对于每个INSERT调用SQLBindParameter(stmt, 1, &X); SQLBindParameter(stmt, 2, &Y) /*extra parameters omitted, see http://msdn.microsoft.com/en-us/library/ms710963(VS.85).aspx */。最后,调用SQLExecute来执行操作。)

    【讨论】:

    • 有没有办法用 ADO 做到这一点?
    • ADO 会很简单——在 Command 对象上设置 Prepared 属性,并在 ecacht INSERT 上更改 Parameters 集合
    【解决方案2】:

    关于 Pukku 对 ostringstream 的建议的评论:为了使其与语言环境无关,应该明确地为流注入所需的语言环境:

    std::ostringstream s;
    s.imbue(std::locale::classic());
    s << "INSERT INTO Vertices (X, Y) VALUES (" << pt.X << ", " << pt.Y << ")";
    

    否则,使用当前的全局语言环境。

    【讨论】:

      【解决方案3】:

      参数化查询应该完全避免这个问题。你应该调查那些。也就是说,您应该可以使用setlocale 或类似的方法来更改小数点分隔符。

      【讨论】:

        【解决方案4】:

        使用

        _create_locale( LC_NUMERIC, "C" )
        

        创建一个“英语”(C 默认)语言环境,然后将其传递给 _sprintf_l 函数组之一。

        例如

        _locale_t locale = _create_locale( LC_NUMERIC, "C" );
        _sprintf_l( pszValue, "%f", locale, 3.141 );
        _free_locale(locale);
        

        这是线程安全的。语言环境可以存储在静态变量中,以避免每次需要格式化值时都创建它。

        【讨论】:

          【解决方案5】:

          这就是我所做的。

          CString FormatQuery(LPCTSTR pszFormat, ...)
          {
              CString szLocale = setlocale(LC_NUMERIC, NULL);
              setlocale(LC_NUMERIC, "English");
          
              va_list args;
              va_start(args, pszFormat);
              CString szFormatted;
              int nSize = (_vscprintf(pszFormat, args) + 1) * sizeof(char);
              _vsnprintf_s(szFormatted.GetBuffer(nSize), nSize, nSize, pszFormat, args);
              szFormatted.ReleaseBuffer();
              va_end(args);
          
              setlocale(LC_NUMERIC, szLocale);
              return szFormatted;
          }
          

          您应该像sprintf 一样使用它。您必须 #include &lt;locale.h&gt; 才能使其正常工作。

          我有点固执,所以我没有使用准备好的语句/参数化查询。如果你有类似的问题,我建议你这样做。同时,如果您的问题与 SQL 无关,我的回答应该会有所帮助。

          编辑:这是一个线程安全的版本:

          CString FormatQuery(LPCTSTR pszFormat, ...)
          {
              _locale_t locale = _create_locale(LC_NUMERIC, "English");
          
              va_list args;
              va_start(args, pszFormat);
              CString szFormatted;
              int nSize = (_vscprintf_l(pszFormat, locale, args) + 1) * sizeof(char);
              _vsnprintf_s_l(szFormatted.GetBuffer(nSize), nSize, nSize, pszFormat, locale, args);
              szFormatted.ReleaseBuffer();
              va_end(args);
          
              return szFormatted;
          }
          

          【讨论】:

            猜你喜欢
            • 2018-02-15
            • 2011-12-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-06-16
            相关资源
            最近更新 更多