2011-05-20 141 views
7

如何將wchar_t'9')轉換爲int9)形式的數字?將wchar_t轉換爲int

我有下面的代碼,我檢查是否peek是一個數字:

if (iswdigit(peek)) { 
    // store peek as numeric 
} 

可我只是減去'0'或者是有一些Unicode的細節我應該擔心?

+1

你有一個字符'9',並且想將它轉換爲數字'9'嗎? – 2011-05-20 07:34:02

+0

@達倫是的,這是主意。 – 2011-05-20 07:35:23

+0

如果你只有ASCII碼,你也可以執行'peek&0xF' – Raze 2011-05-20 08:17:26

回答

4

如果問題只涉及'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; 
} 

如果你走這條路:

  1. 你一定會想下載從 UnicodeData.txt文件Unicode聯盟 (「Uncode Character Database」—此頁面有一個鏈接到Unicode數據 文件和其中使用的編碼的解釋),和
  2. 可能會編寫一個簡單的解析器來自動提取信息(例如,當有一個新版本的 Unicode)—該文件是爲簡單編程的 解析而設計的。

最後請注意,基於ostringstreamistringstream解決方案(包括boost::lexical_cast)不會 工作,因爲在流中使用的轉換定義爲僅 使用羅馬數字。 (在另一方面,它可能是 合理限制把你的代碼的羅馬數字。在 這種情況下,測試成爲if (wch >= L'0' && wch <= L'9'), 和轉換是通過簡單地減去L'0' — 總是假設的本地編碼完成寬字符 在你的編譯器中的常量是Unicode(這種情況,我很確定,它們都是VC++和g ++)或者只是確保語言環境爲 「C」(或者在Unix機器上的「Posix」)。

編輯:我忘了提及:如果你正在做任何嚴肅的Unicode編程,你應該看看ICU。 e 正確的是非常不平凡的,並且他們已經實現了許多功能已經 。

+0

+1感謝您的全面回答:)我沒有進行任何嚴肅的Unicode編程。我只是想讓它具有Unicode意識,但我想這是一個非常困難的任務,要做好。 – 2011-05-20 08:59:03

+1

這取決於你想如何識別Unicode。 C++和Java在Unicode中是正式的,但是它們仍然要求數字常量使用羅馬數字;它們是Unicode認識限於允許在符號和字符串和字符文字(和註釋)中的Unicode字符。我認爲對於很多程序來說,類似的東西就足夠了。 – 2011-05-20 09:12:12

5

窺視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); 
} 
+0

我已經看到了這些,但將它轉換爲'string'似乎有點愚蠢,然後將它轉換爲int。但如果這是通常的做法,我想我會這樣做:) – 2011-05-20 07:39:15

+0

是的,但是你真的想複製這種邏輯嗎?你必須確保你知道所有關於unicode的知識。或者至少可以確定你沒有搞砸。我個人不會冒險。 – 2011-05-20 07:41:23

+0

我也不會。我只是覺得有一種方法可以做到這一點。我看到助推庫做到了。 +1 – 2011-05-20 07:43:08

0

在大多數情況下,你可以只減去碼「0」。

但是,維基百科關於Unicode numerials的文章提到,十三位數字表示在23個獨立的塊中(包括兩次阿拉伯語)。

如果您不擔心這一點,那麼只需減去'0'的代碼即可。

+0

如果那些Unicode數字被'iswdigit'識別,那麼它可能會破壞我的代碼。所以我想我必須擔心:) – 2011-05-20 07:40:40

+0

如果您當前的語言環境有一些不使用ASCII /英文標準數字的語言環境,Unicode數字將會破壞您的代碼。 – Raze 2011-05-20 08:16:55

1

你可以使用boost::lexical_cast

const wchar_t c = '9'; 
int n = boost::lexical_cast<int>(c); 
+0

+1正是我在找的東西 – 2011-05-20 07:43:55

+2

這是過分的矯枉過正。在幕後,你正在創建一個'std :: ostreamstring'來將'wchar_t'轉換成'std :: string',然後'std :: istringstream'將'std :: string'轉換成int ,當需要的只是一個簡單的減法。 – 2011-05-20 07:53:44

+0

我會簡單地使用if(peek> = L'0'&& peek <= L'9') – 2011-05-20 07:57:20

1

儘管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減法可能不會像您預期的那樣工作。

+0

在哪些語言環境中? 'iswdigit'是語言環境特定的,所以你不能在沒有指定語言環境的情況下做任何關於它的聲明。 – 2011-05-20 08:30:43

+0

英文或德文。不能肯定地說。我有一些德國設置的英文包裝盒。 – 2011-05-20 09:00:46

+0

這不一定會影響代碼中的區域設置。所有程序都以「C」語言環境開始。 – 2011-05-20 09:07:58