使用 strtod strtof atof printf 进行区域设置不变的字符串处理?

2024-01-08

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

目前有很多脆弱的解决方法,例如来自 jansson/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 https://en.wikipedia.org/wiki/Decimal_mark#Hindu.E2.80.93Arabic_numeral_system举些例子)。 (2) 意味着如果没有锁,预处理方法就不能是线程安全的,并且必须将锁添加到 C 库中。 (3) 只是愚蠢。

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

问题:

  1. WG14 或 WG21 是否有任何报告解决此缺陷?
  2. 如果是这样,为什么没有将它们合并到标准中?它只不过是一组以语言环境作为参数的新函数。
  3. 规范的解决方法是什么?

Update:

在网上搜索后,我发现了 *_l 函数,在 FreeBSD、GNU/Linux 和 MacOSX 上都可用。 Windows 上也存在类似的功能。这些解决了我的问题,但是它们不在 POSIX 中,POSIX 是 C 的超集(不是真的,POSIX 在指针上放宽)。因此问题 1 和 2 仍然悬而未决。


BSD 和 macOS Sierra(以及之前的 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, ...);

and:

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)就可以被采用。但是,与区域设置相结合,它可以使时间例程更容易通过单个可执行文件在不同的环境中使用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 strtod strtof atof printf 进行区域设置不变的字符串处理? 的相关文章

随机推荐