如何將wchar_t
('9'
)轉換爲int
(9
)形式的數字?將wchar_t轉換爲int
我有下面的代碼,我檢查是否peek
是一個數字:
if (iswdigit(peek)) {
// store peek as numeric
}
可我只是減去'0'
或者是有一些Unicode的細節我應該擔心?
如何將wchar_t
('9'
)轉換爲int
(9
)形式的數字?將wchar_t轉換爲int
我有下面的代碼,我檢查是否peek
是一個數字:
if (iswdigit(peek)) {
// store peek as numeric
}
可我只是減去'0'
或者是有一些Unicode的細節我應該擔心?
如果問題只涉及'9'
(或其中一個羅馬 數字),只需減去'0'
是正確的解決方案。如果 您關心的任何事情iswdigit
返回 非零,但是,問題可能會更復雜。 標準說如果參數爲「十進制數字寬字符代碼[在當前的 本地]」,則它將返回一個非零值。這是模糊的,並將其留給區域設置爲 確切地定義了是什麼意思。在「C」語言環境或「Posix」語言環境中,「Posix」標準至少可以保證只有零到九位的羅馬數字才被認爲是十進制數字(如果我正確地理解了 )在「C」或「Posix」 區域設置中,只需減去'0'應該可以工作。
推測,在Unicode區域設置中,這可能是任何字符 ,它的一般類別爲Nd
。這些有一些 。最安全的解決辦法是簡單地創造一些 像(變量這裏靜態壽命):
wchar_t const* const digitTables[] =
{
L"",
L"\u0660\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669",
// ...
};
//! \return
//! wch as a numeric digit, or -1 if it is not a digit
int asNumeric(wchar_t wch)
{
int result = -1;
for (wchar_t const* const* p = std::begin(digitTables);
p != std::end(digitTables) && result == -1;
++ p) {
wchar_t const* q = std::find(*p, *p + 10, wch);
if (q != *p + 10) {
result = q - *p;
}
return result;
}
如果你走這條路:
UnicodeData.txt
文件Unicode聯盟 (「Uncode Character Database」—此頁面有一個鏈接到Unicode數據 文件和其中使用的編碼的解釋),和最後請注意,基於ostringstream
和 istringstream
解決方案(包括boost::lexical_cast
)不會 工作,因爲在流中使用的轉換定義爲僅 使用羅馬數字。 (在另一方面,它可能是 合理限制把你的代碼的羅馬數字。在 這種情況下,測試成爲if (wch >= L'0' && wch <= L'9')
, 和轉換是通過簡單地減去L'0'
— 總是假設的本地編碼完成寬字符 在你的編譯器中的常量是Unicode(這種情況,我很確定,它們都是VC++和g ++)或者只是確保語言環境爲 「C」(或者在Unix機器上的「Posix」)。
編輯:我忘了提及:如果你正在做任何嚴肅的Unicode編程,你應該看看ICU。 e 正確的是非常不平凡的,並且他們已經實現了許多功能已經 。
+1感謝您的全面回答:)我沒有進行任何嚴肅的Unicode編程。我只是想讓它具有Unicode意識,但我想這是一個非常困難的任務,要做好。 – 2011-05-20 08:59:03
這取決於你想如何識別Unicode。 C++和Java在Unicode中是正式的,但是它們仍然要求數字常量使用羅馬數字;它們是Unicode認識限於允許在符號和字符串和字符文字(和註釋)中的Unicode字符。我認爲對於很多程序來說,類似的東西就足夠了。 – 2011-05-20 09:12:12
窺視atoi
類的功能:http://msdn.microsoft.com/en-us/library/hc25t012(v=vs.71).aspx
特別_wtoi(const wchar_t *string);
似乎是你在找什麼。你必須確保你的wchar_t
正確空終止,雖然如此,嘗試這樣的事情:
if (iswdigit(peek)) {
// store peek as numeric
wchar_t s[2];
s[0] = peek;
s[1] = 0;
int numeric_peek = _wtoi(s);
}
我已經看到了這些,但將它轉換爲'string'似乎有點愚蠢,然後將它轉換爲int。但如果這是通常的做法,我想我會這樣做:) – 2011-05-20 07:39:15
是的,但是你真的想複製這種邏輯嗎?你必須確保你知道所有關於unicode的知識。或者至少可以確定你沒有搞砸。我個人不會冒險。 – 2011-05-20 07:41:23
我也不會。我只是覺得有一種方法可以做到這一點。我看到助推庫做到了。 +1 – 2011-05-20 07:43:08
在大多數情況下,你可以只減去碼「0」。
但是,維基百科關於Unicode numerials的文章提到,十三位數字表示在23個獨立的塊中(包括兩次阿拉伯語)。
如果您不擔心這一點,那麼只需減去'0'的代碼即可。
如果那些Unicode數字被'iswdigit'識別,那麼它可能會破壞我的代碼。所以我想我必須擔心:) – 2011-05-20 07:40:40
如果您當前的語言環境有一些不使用ASCII /英文標準數字的語言環境,Unicode數字將會破壞您的代碼。 – Raze 2011-05-20 08:16:55
你可以使用boost::lexical_cast
:
const wchar_t c = '9';
int n = boost::lexical_cast<int>(c);
+1正是我在找的東西 – 2011-05-20 07:43:55
這是過分的矯枉過正。在幕後,你正在創建一個'std :: ostreamstring'來將'wchar_t'轉換成'std :: string',然後'std :: istringstream'將'std :: string'轉換成int ,當需要的只是一個簡單的減法。 – 2011-05-20 07:53:44
我會簡單地使用if(peek> = L'0'&& peek <= L'9') – 2011-05-20 07:57:20
儘管MSDN documentation,一個簡單的測試表明,不僅遊俠L'0'L'9' 返回true。
for(wchar_t i = 0; i < 0xFFFF; ++i)
{
if (iswdigit(i))
{
wprintf(L"%d : %c\n", i, i);
}
}
這意味着L'0減法可能不會像您預期的那樣工作。
在哪些語言環境中? 'iswdigit'是語言環境特定的,所以你不能在沒有指定語言環境的情況下做任何關於它的聲明。 – 2011-05-20 08:30:43
英文或德文。不能肯定地說。我有一些德國設置的英文包裝盒。 – 2011-05-20 09:00:46
這不一定會影響代碼中的區域設置。所有程序都以「C」語言環境開始。 – 2011-05-20 09:07:58
你有一個字符'9',並且想將它轉換爲數字'9'嗎? – 2011-05-20 07:34:02
@達倫是的,這是主意。 – 2011-05-20 07:35:23
如果你只有ASCII碼,你也可以執行'peek&0xF' – Raze 2011-05-20 08:17:26