别误用IsDigit与IsNumber函数(转)

1、起因


最近发现程序中有一段控制TextBox数字输入的代码,相信大家都不会太陌生,如下:


void int_KeyPress(object sender, KeyPressEventArgs e)
{
const char Delete = (char)8;
if (!Char.IsDigit(e.KeyChar) && e.KeyChar != Delete)
{
e.Handled = true;
}
}

乍一看,好像没有啥问题,但是却出现了一个bug,能够输入全角的数字,如:0、1、2、3等。错误的根源就是上面代码中用到的IsDigit函数,于是就有了下面的一番探究,让我们来看看IsDigit函数的真面目。

2、IsDigit函数

查阅MSDN,Char.IsDigit 方法是指示某个 Unicode
字符是否属于十进制数字类别。通过ILSpy查看其源代码:


[__DynamicallyInvokable]
public static bool IsDigit(char c)
{
if (char.IsLatin1(c))
{
return c >= ‘0‘ && c <= ‘9‘;
}
return CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.DecimalDigitNumber;
}

第一行的IsLatin1函数是判断字符是0~255的函数,而全角的0、1、2、3等的Unicode编码不在这个范围,于是就执行了下面这句代码:

CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.DecimalDigitNumber;

而对于Unicode的分类中,半角的1,2,3和全角的0、1、2、3等都被归为了DecimalDigitNumber,所以对于全角的数字,这个函数返回了true。
还有一个函数IsNumber和IsDigit功能相似,我们是否可以用它来代替呢?看下面的分析

3、IsNumber函数又是何物?

MSDN的解释:Char.IsNumber 方法指示某个 Unicode
字符是否属于数字类别。

这个函数的定义:


[__DynamicallyInvokable]
public static bool IsNumber(char c)
{
if (!char.IsLatin1(c))
{
return char.CheckNumber(CharUnicodeInfo.GetUnicodeCategory(c));
}
if (char.IsAscii(c))
{
return c >= ‘0‘ && c <= ‘9‘;
}
return char.CheckNumber(char.GetLatin1UnicodeCategory(c));
}


internal static bool CheckNumber(UnicodeCategory uc)
{
switch (uc)
{
case UnicodeCategory.DecimalDigitNumber:
case UnicodeCategory.LetterNumber:
case UnicodeCategory.OtherNumber:
return true;
default:
return false;
}
}

和IsDigit函数相比有3点区别:
1)多了一个UnicodeCategory.LetterNumber类型

2)多了一个UnicodeCategory.OtherNumber类型

3)多了一个IsAscii的判断(0~127)

很显然IsNumber的范围更广了。下面列举几种IsNumber认为是数字的字符

UnicodeCategory.LetterNumber:Ⅰ、Ⅱ、Ⅲ

UnicodeCategory.OtherNumber:①、②、③

128~255中有哪些字符会被IsNumber认为是数字,有兴趣的可以自己去测试。

测试的方法可以利用这个函数:System.Globalization.CharUnicodeInfo.GetUnicodeCategory(char c)
,返回的是一个UnicodeCategory类型,你可以看看是不是IsNumber的几个类型就知道了。

4、结论

搞清楚了上面这两个函数的内部实现,那么在判断是否是ASCII数字(0~9)的时候,我们就需要注意以下几点了。

1)不能用IsDigit和IsNumber函数判断是否是ASCII数字,这两个函数都有可能把ASCII以外的某些字符当做是数字。

2)尽量用这种方式判断: c >= ‘0‘ && c <= ‘9‘(当然也可以用正则表达式)。

3)数字判断的严格性,从严到松依次是:

c >= ‘0‘ && c <= ‘9‘ ?IsDigit ?IsNumber

4)修改上面的bug函数作为结束


void int_KeyPress(object sender, KeyPressEventArgs e)
{
const char Delete = (char)8;
if (!(e.KeyChar >= ‘0‘ && e.KeyChar <= ‘9‘) && e.KeyChar != Delete)
{
e.Handled = true;
}
}


  欢迎加群:.NET反编译|破解 群号:183569712(请输入验证信息:博客园). 


引用:

  别误用IsDigit与IsNumber函数

别误用IsDigit与IsNumber函数(转),布布扣,bubuko.com

时间: 2024-08-04 05:13:54

别误用IsDigit与IsNumber函数(转)的相关文章

信号处理函数误用不可重入函数导致的进程死锁情况

记一次进程死锁的情况: 某天突然发现进程不再运行处理且有没有崩溃产生core文件: 使用gdb -p pid查看堆栈信息如下: 1 #0 0x000000376faf83ae in __lll_lock_wait_private () from /lib64/libc.so.6 2 #1 0x000000376fa7d35b in _L_lock_10288 () from /lib64/libc.so.6 3 #2 0x000000376fa7ab83 in malloc () from /l

c语言中的 isalpha,isdigit,islower,isupper等一系列函数

isalnum(测试字符是否为英文或数字) 相关函数 isalpha,isdigit,islower,isupper 表头文件 #include<ctype.h> 定义函数 int isalnum (int c) 函数说明 检查参数c是否为英文字母或阿拉伯数字,在标准c中相当于使用“isalpha(c) || isdigit(c)”做测试. 返回值 若参数c为字母或数字,则返回TRUE,否则返回NULL(0). 附加说明 此为宏定义,非真正函数. 范例 /* 找出str 字符串中为英文字母或数

Difference between Char.IsDigit() and Char.IsNumber() in C#

http://stackoverflow.com/questions/228532/difference-between-char-isdigit-and-char-isnumber-in-c-sharp Char.IsDigit() is a subset of Char.IsNumber(). Some of the characters that are 'numeric' but not digits include 0x00b2 and 0x00b3 which are supersc

【C#遗补】之Char.IsDigit和Char.IsNumber的区别

原文:[C#遗补]之Char.IsDigit和Char.IsNumber的区别 Char中IsDigit和IsNumber的两个方法都是用来判断字符是否是数字的,那他们有什么区别 IsDigit        判断的是十进制数字,就是 '0 '.. '9 '. IsNumber   判断的是数字类别,包括十进制数字 '0 '.. '9 ',还有用字母表示的数字,如表示罗马数字5的字母 'V ',还有表示其他数字的字符,如表示“1/2”的字符.

isalpha函数和isdigit函数

       函数:isalpha 原型:int isalpha(int ch) 用法:头文件加入#include <cctype>(旧版本的编译器使用<ctype.h>) 功能:判断字符ch是否为英文字母,当ch为英文字母a-z或A-Z时,在标准c中相当于使用“isupper(ch)||islower(ch)”做测试,返回非零值,否则返回零. PS:{ isupper 原型:extern int isupper(int c); 头文件:<cctype>(旧版本的编译器

Linux常用C函数---字符测试篇

函数讲解部分参考http://net.pku.edu.cn/~yhf/linux_c/ isalnum(测试字符是否为英文或数字) 相关函数 isalpha,isdigit,islower,isupper 表头文件 #include<ctype.h> 定义函数 int isalnum (int c) 函数说明 检查参数c是否为英文字母或阿拉伯数字,在标准c中相当于使用"isalpha(c) || isdigit(c)"做测试. 返回值 若参数c为字母或数字,则返回TRUE,

isdigit(测试字符是否为阿拉伯数字)

/*isdigit(测试字符是否为阿拉伯数字) 相关函数 isxdigit 表头文件 #include<ctype.h> 定义函数 int isdigit(int c) 函数说明 检查参数c是否为阿拉伯数字0到9. 返回值 若参数c为阿拉伯数字,则返回TRUE,否则返回NULL(0). 附加说明 此为宏定义,非真正函数. 范例*/ /* 找出str字符串中为阿拉伯数字的字符 */ #include<ctype.h> #include<stdio.h> main() {

字符测试篇isalnum isalpha isascii iscntrl isdigit isgraphis islower isprint isspace ispunct isupper isxdigit

isalnum(测试字符是否为英文或数字) 相关函数 isalpha,isdigit,islower,isupper 表头文件 #include<ctype.h> 定义函数 int isalnum (int c) 函数说明 检查参数c是否为英文字母或阿拉伯数字,在标准c中相当于使用“isalpha(c) || isdigit(c)”做测试. 返回值 若参数c为字母或数字,则返回TRUE,否则返回NULL(0). 附加说明 此为宏定义,非真正函数. 范例 /* 找出str 字符串中为英文字母或数

PB函数大全

Abs()功能计算绝对值.语法Abs ( n )参数n:要得到绝对值的数值型变量或表达式返回值返回值的数据类型与n的数据类型相同,函数执行成功时返回n的绝对值.如果参数n的值为NULL,Abs()函数返回NULL. Ceiling()功能返回大于n的最小整数.语法Ceiling ( n )参数n:数值型变量或表达式返回值返回值的数据类型与n的数据类型相同.函数执行成功时返回大于n的最小整数.如果参数n的值为NULL,Ceiling()函数返回NULL. Cos()功能计算余弦,其中参数以弧度为单