10

如何将 ( ) 转换为( wchar_t)'9'形式的数字?int9

我有以下代码检查是否peek是数字:

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

我可以减去'0'还是有一些我应该担心的 Unicode 细节?

4

5 回答 5

6

如果问题仅涉及'9'(或罗马数字之一),则仅减法'0'是正确的解决方案。但是,如果您关心iswdigit返回非零的任何内容,则问题可能要复杂得多。该标准规定,iswdigit如果其参数是“十进制数字宽字符代码 [在当前本地]”,则返回非零值。这是模糊的,并留给语言环境来准确定义含义。在“C”语言环境或“Posix”语言环境中,“Posix”标准至少保证只有罗马数字零到九被认为是十进制数字(如果我理解正确的话),所以如果你在“C”或“Posix”语言环境,只需减去“0”就可以了。

据推测,在 Unicode 语言环境中,这将是具有一般类别的任何字符Nd。其中有很多。最安全的解决方案是简单地创建类似(这里的变量具有静态生命周期):

wchar_t const* const digitTables[] =
{
    L"0123456789",
    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 时)——该文件是为简单的程序解析而设计的。

最后,请注意基于ostringstreamand istringstream(包括boost::lexical_cast)的解决方案将不起作用,因为流中使用的转换被定义为仅使用罗马数字。(另一方面,将代码限制为罗马数字可能是合理的。在这种情况下,测试变为if ( wch >= L'0' && wch <= L'9' ),并且通过简单的减法来完成转换L'0'- 始终假设编译器中宽字符常量的本机编码是 Unicode(我很确定,VC++ 和 g++ 都是这种情况)。或者只是确保语言环境是“C”(或“Posix”,在 Unix 机器上)。

编辑:我忘了提:如果你正在做任何严肃的 Unicode 编程,你应该看看ICU。正确处理 Unicode 非常重要,而且它们已经实现了很多功能。

于 2011-05-20T08:29:07.297 回答
6

查看atoi函数类:http: //msdn.microsoft.com/en-us/library/hc25t012 (v=vs.71).aspx

特别是_wtoi(const wchar_t *string);似乎是您正在寻找的东西。但是,您必须确保您wchar_t的正确以 null 终止,因此请尝试以下操作:

if (iswdigit(peek)) {
    // store peek as numeric
    wchar_t s[2];
    s[0] = peek;
    s[1] = 0;
    int numeric_peek = _wtoi(s);
}
于 2011-05-20T07:36:47.310 回答
1

你可以使用boost::lexical_cast

const wchar_t c = '9';
int n = boost::lexical_cast<int>( c );
于 2011-05-20T07:40:30.367 回答
1

尽管有MSDN 文档,但一个简单的测试表明,不仅 ranger 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' 减法可能不会像您预期的那样工作。

于 2011-05-20T07:55:33.603 回答
0

大多数情况下,您只需减去“0”的代码即可。

但是,关于Unicode数字的 Wikipedia 文章提到十进制数字以 23 个单独的块表示(包括阿拉伯语中的两次)。

如果您对此不担心,那么只需减去“0”的代码即可。

于 2011-05-20T07:36:50.157 回答