2009-02-03 105 views
2

我的產品是針對葡萄牙觀衆的,逗號是小數點符號。我通常使用CString :: Format將數字輸入到字符串中,並將計算機的區域設置考慮在內。雖然總的來說,這是一個好辦法,我有在格式化SQL查詢的問題,例如:如何將float轉換爲字符串而不管區域設置如何?

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。

回答

1

這就是我所做的。

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 <locale.h>才能正常工作。

我有點固執,所以我沒有使用預處理語句/參數化查詢。如果你有類似的問題,我建議你這樣做。同時,如果你的問題不是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; 
} 
10

壞主意,你真的應該使用準備好的語句。用數字進行SQL注入並不是很簡單,但CString :: Format並不是執行參數綁定的正確方法。 (MFC和SQL已經有一段時間了 - 事實證明這是非常隱蔽的,我已經開始看到我們如何結束SQL注入漏洞,謝謝微軟。 SQLPrepare。Pass?爲要填寫的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來執行操作。)

+0

那麼哪種方法正確? – djeidot 2009-02-03 15:32:20

+0

基於你正在使用的數據庫引擎的參數綁定... – user7116 2009-02-03 16:10:04

+0

有沒有辦法用ADO做到這一點? – djeidot 2009-02-03 17:28:11

6

參數化查詢應完全避免此問題。你應該看看那些。也就是說,您應該可以使用setlocale或更改小數點分隔符。

9

約Pukku與ostringstream建議註釋:對於這是語言環境無關,應該明確地灌輸()與所需的語言流:

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

否則,將使用當前的全球語言環境。

1

使用

_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); 

這是線程安全的。區域設置可以存儲在一個靜態變量中,以避免每次需要格式化值時創建它。

相關問題