В разделе, покрывающем setlocale, ANSI C стандарт указывает в сноске, что единственный ctype.h функционирует, чье поведение не затронуто текущей локалью, isdigit и isxdigit.
Реализация Microsoft isdigit является зависимым локали, потому что, например, в локалях с помощью кодовой страницы 1250 isdigit только возвращается ненулевой для символов в диапазоне 0x30 ('0') - 0x39 ('9'), тогда как в локалях с помощью кодовой страницы 1252 isdigit также возвращается ненулевой для цифр верхнего индекса 0xB2 (' ² '), 0xB3 (' ³ ') и 0xB9 (' ¹ ').
Нарушает Microsoft стандарт C путем создания isdigit зависимого локали?
В этом вопросе я, прежде всего, интересуюсь C90, которому Microsoft утверждает, что приспособила, а не C99.
Дополнительный фон:
Собственная документация Microsoft setlocale неправильно указывает, что isdigit незатронут частью LC_CTYPE локали.
Раздел стандарта C, который касается функций ctype.h, содержит некоторую формулировку, которую я считаю неоднозначными:
Поведение этих функций затронуто текущей локалью. Те функции, которые имеют определенные для локали аспекты только если не в "C" локали, отмечены ниже.
Я считаю это неоднозначным, потому что неясно, что это пытается сказать о функциях, таких как isdigit, для которого нет никаких примечаний об определенных для локали аспектах. Это могло бы пытаться сказать, что такие функции, как должно предполагаться, являются зависимым локали, в этом случае реализация Microsoft isdigit была бы в порядке. (За исключением того, что сноска, которую я упомянул ранее, кажется, противоречит этой интерпретации.)
Microsoft всегда имеет собственную интерпретацию спецификации. И обычно фраза «но Microsoft ошибается» не имеет никакого отношения к вашему генеральному директору, поэтому вы должны кодировать ошибки / интерпретации MS.
Количество кода, поддерживающего некорректное поведение IE и Outlook, ошеломляет.
Во многих случаях единственное решение - использовать собственную версию функции, которая выполняет правильные действия, и делать что-то вроде этого:
int my_isdigit( int c )
{
#ifdef WIN32
your implementation goes here
#else
return isdigit( c );
#endif
}
Требуемый набор символов определен в разделе 2.2.1. Далее в разделе 2.2.1.2 описывается поведение символов расширения: