C语言中的isdigit函数是否合法地依赖于locale?

21
在涉及setlocale的部分,ANSI C标准在一个脚注中指出,当前语言环境不会影响的ctype.h函数只有isdigit和isxdigit。
由于在使用代码页面1250的语言环境中,isdigit仅对范围在0x30('0')- 0x39('9')之间的字符返回非零值,而在使用代码页1252的语言环境中,isdigit还会对上标数字0xB2('²'),0xB3('³')和0xB9('¹')返回非零值,因此Microsoft实现的isdigit是与语言环境相关的。
通过使isdigit与语言环境相关,Microsoft是否违反了C标准?
在这个问题中,我主要关心的是C90,因为Microsoft声称符合它,而不是C99。
附加背景:
Microsoft自己的setlocale文档错误地声明isdigit不受语言环境的LC_CTYPE部分的影响。
涵盖ctype.h函数的C标准部分包含一些我认为模棱两可的措辞:
这些函数的行为受当前语言环境的影响。那些仅在非“C”语言环境下具有特定地区性方面的功能如下所示。
我认为这是模棱两可的,因为不清楚它试图说isdigit这样的函数的情况,对于这些函数没有区域特定方面的注释。它可能试图说这样的函数必须假定是与语言环境相关的,在这种情况下,Microsoft的isdigit实现将是可以接受的。(除了我之前提到的脚注似乎与此解释相矛盾。)

我通常会避免使用<ctype.h>中的东西,因为它要求你对发送给它的所有内容进行清理。相应地,我会使用ICU的u_isalpha()u_isUAlphabetic() - Dúthomhas
3个回答

13
  1. Microsoft总是正确的。
  2. 如果Microsoft不正确,请查看项目1。

微软通常对规范有自己的解释。而且通常情况下,“但是微软错了”这句话对你的CEO没有什么说服力,所以你需要编写代码来解决MS的bug/解释。

为支持IE和Outlook的不正确行为所编写的代码量是惊人的。

在许多情况下,唯一的解决方案是编写自己的函数版本来执行正确的操作,然后像这样进行操作:

int my_isdigit( int c )
{
#ifdef WIN32
  your implementation goes here
#else
  return isdigit( c );
#endif
}

5

所需的字符集在第2.2.1节中定义。然后,第2.2.1.2节描述了扩展字符的行为:

  • 必须存在$2.2.1中定义的单字节字符。
  • 任何其他成员的存在、含义和表示都是与语言环境相关的。

1
答案对于所有版本的C标准都是相同的,但在这里我将使用C23的N3054草案。
7.4.1.5中isdigit的描述非常简单:
isdigit函数测试任何十进制数字字符(如5.2.1中定义的字符)。”
因此,我们需要查看5.2.1以了解什么是十进制数字字符。确切的短语“十进制数字字符”在那里不出现,但我们得到了一个要求基本字符集中必须包含的字符的描述,其中包括“10个十进制数字”,后面跟着从0到9的数字的明确列表。这无疑是我们寻找的定义,因为没有其他可用的候选者。
这明确表明isdigit函数仅测试这10个字符,没有其他字符。特别地,它不能是与区域设置相关的。
顺便说一句,通过类似的推理,isxdigit函数也不是与区域设置相关的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接