2017-01-22 80 views
4

是否有计划添加在当前语言环境下不变的C标准库字符串处理函数的版本?使用strtod strtof atof printf进行语言环境不变的字符串处理?

目前有许多易碎的解决方法,例如,从詹森/ strconv.c:

static void to_locale(strbuffer_t *strbuffer) 
{ 
    const char *point; 
    char *pos; 

    point = localeconv()->decimal_point; 
    if(*point == '.') { 
     /* No conversion needed */ 
     return; 
    } 

    pos = strchr(strbuffer->value, '.'); 
    if(pos) 
     *pos = *point; 
} 

static void from_locale(char *buffer) 
{ 
    const char *point; 
    char *pos; 

    point = localeconv()->decimal_point; 
    if(*point == '.') { 
     /* No conversion needed */ 
     return; 
    } 

    pos = strchr(buffer, *point); 
    if(pos) 
     *pos = '.'; 
} 

这些功能其进行预处理,以便输入它可以被用来独立于当前的区域设置的,假设下

  1. 与分隔符是一个字节
  2. setlocale没有呼叫这些修复功能和来电之间发生任何受影响的功能
  3. 该字符串可以转换之前被修改

(1)意味着在奇风异俗预处理方法断裂(参见https://en.wikipedia.org/wiki/Decimal_mark#Hindu.E2.80.93Arabic_numeral_system的例子)。 (2)意味着预处理方法不能在没有锁的情况下进行线程安全,并且该锁必须被添加到C库中。 (3)愚蠢。

如果只能将作为参数的字符串处理函数的单个调用的区域设置指定为不影响任何其他线程,则不会应用这些限制。

问题:

  1. 是否有解决这一缺陷WG14的任何报告或WG21?
  2. 如果是这样,为什么这些不被合并到标准中?这只不过是一组以功能为基础的新功能。
  3. 规范的解决方法是什么?

更新:

通过互联网搜索后,我发现* _l功能,在FreeBSD,GNU/Linux和MacOSX上可用。 Windows上也有类似的功能。这些解决了我的问题,但是这些不在POSIX中,这是C的超集(不是真的,POSIX放松指针)。所以问题1和2仍然是开放的。

+0

为什么不直接在非本地化模式下运行'printf'和 - 朋友? (也就是'locale =“C”') –

+0

@ BenVoigt。线程安全。如果我没有保持全局锁定而设置它,另一个线程进入之间。它可以将语言环境设置为其他内容,也可以使用我不想要的语言环境。 – user877329

+0

然后你的问题是http://stackoverflow.com/q/6561723/103167的副本? –

回答

2

BSD和MacOS塞拉利昂(以及Mac OS X之前)支持_l功能,允许您指定区域,而不是依赖于当前语言环境。例如:

int 
fprintf_l(FILE * restrict stream, locale_t loc, const char * restrict format, ...); 

int 
printf_l(locale_t loc, const char * restrict format, ...); 

int 
snprintf_l(char * restrict str, size_t size, locale_t loc, const char * restrict format, ...); 

int 
sprintf_l(char * restrict str, locale_t loc, const char * restrict format, ...); 

和:

int 
fscanf_l(FILE * restrict stream, locale_t loc, const char * restrict format, ...); 

int 
scanf_l(locale_t loc, const char * restrict format, ...); 

int 
sscanf_l(const char * restrict str, locale_t loc, const char * restrict format, ...); 

作为一般的设计,这似乎是明智的。 locale_t类型不是标准C的一部分,但是是POSIX的一部分(并在此处定义为<locale.h>),并在其他地方使用<ctype.h>。 BSD手册页说使用的标题是<xlocale.h>而不是<locale.h>;这可能会被标准所固定。除非BSD功能的设计中存在重大缺陷,否则这些应该是任何标准化工作的非常好的基础,无论是在POSIX还是标准C下。

BSD设计的一个问题可能是locale_t结构是通过值传递的,而不是通过(常量限制)指针,这有点令人惊讶。然而,它与POSIX功能,如一致的:

int isalpha_l(int, locale_t); 

一个类似的计划可能会被设计用来处理时区设置,太。由于还没有时区类型,所以在设置时需要做更多的工作(而locale_t已经是POSIX的一部分了 - 而且很可能不会改变为标准C)。但是,结合语言环境设置,它可以使时间例程更易于在单个可执行文件的不同环境中使用。

+0

从'/ usr/include/locale.h'(GNU/Linux):每个类别一个静态语言环境的概念并不是很清楚。许多应用程序需要使用来自多个不同语言环境的信息来处理其数据。 (...)为了支持这个使用语言环境数据的另一组函数,它们有一个额外的参数。注意:所有这些功能都不是以任何形式标准化的。这是一个概念验证实现。 __Side note__:在这个实现中'local_t' *是一个指针(指向'__locale_struct')。 – user877329

+0

关于时区的有趣思考。这里是一个用于处理时区的现有C++库:https://howardhinnant.github.io/date/tz.html目前正在收集现场经验。以下是所涉及类型的图形摘要:https://howardhinnant.github.io/date/tz_types.jpeg(确实包含'time_zone'类型)。 –

+0

'locale_t'也是macOS Sierra上指针的typedef。 – Wevah

相关问题