相关疑难解决方法(0)

从字符串中有效地读取括号中两个以逗号分隔的浮点数,而不受全局语言环境的影响

我是一个库的开发人员,我们的旧代码使用sscanf()和sprintf()从/到字符串读/写各种内部类型.我们遇到过使用我们库的用户的问题,并且其语言环境与我们基于XML文件的语言环境不同("C"语言环境).在我们的例子中,这导致从这些XML文件解析的值不正确,以及在运行时以字符串形式提交的值.区域设置可以由用户直接更改,但也可以在用户不知情的情况下进行更改.如果区域设置更改发生在另一个库中,例如GTK,这是​​一个错误报告中的"犯罪者",就会发生这种情况.因此,我们显然希望从语言环境中删除任何依赖关系,以永久地摆脱这些问题.

我已经在float/double/int /的上下文中阅读了其他问题和答案,特别是如果它们被一个字符分隔或位于括号内,但到目前为止,我发现的建议解决方案并不令我们满意.我们的要求是:

  1. 除了标准库之外,不依赖于库.因此,使用boost中的任何内容都不是一种选择.

  2. 必须是线程安全的.这具体涉及可以全局更改的区域设置.这对我们来说真的很糟糕,因为我们库的一个线程可能会受到用户程序中另一个线程的影响,该线程也可能正在运行一个完全不同的库的代码.setlocale()因此,任何直接受影响的东西都不是一种选择.此外,由于线程中的竞争条件,在开始读/写之前设置区域设置并将其设置回原始值不是解决方案.

  3. 虽然效率不是最重要的优先级(#1和#2),但它仍然是我们关注的问题,因为字符串可能会在运行时频繁地读取和写入,具体取决于用户的程序.越快越好.

编辑:作为补充说明:boost::lexical_cast不保证不受语言环境的影响(来源:boost :: lexical_cast <>的语言环境不变保证).即使没有要求#1,这也不是解决方案.

到目前为止,我收集了以下信息:

  • 首先,我看到的建议很多是使用boost的lexical_cast,但不幸的是,这对我们来说根本不是一个选项,因为我们不能要求所有用户也链接到boost(并且由于缺乏locale-safety) , 往上看).我查看了代码,看看我们是否可以从中提取任何内容,但我发现它很难理解,而且篇幅太长,而且很可能是性能提升者仍在使用依赖于语言环境的函数.
  • 在C++ 11引入了许多功能,如std::to_string,std::stod,std::stof,等取决于全球区域只是sscanf的方式和sprintf做的,这是非常不幸的,我不理解的,考虑到的std ::螺纹已被添加.
  • std::stringstream似乎是一般的解决方案,因为它在语言环境的上下文中是线程安全的,但一般来说如果保护正确的话.但是,如果它每次都是新建的,那么它很慢(良好的比较:http://www.boost.org/doc/libs/1_55_0/doc/html/boost_lexical_cast/performance.html).我假设这可以通过配置和使用每个线程一个这样的流来解决,每次使用后清除它.但是,问题在于它不能像以下那样容易地解决格式sscanf(),例如:" { %g , %g } ".

sscanf() 例如,我们需要能够阅读的模式是:

  • " { %g , %g }"
  • " { { %g , %g } , { %g , %g } }"
  • " { top: { %g , %g } …

c++ parsing std

9
推荐指数
1
解决办法
329
查看次数

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

是否有计划添加在当前语言环境下不变的 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 = '.';
}
Run Code Online (Sandbox Code Playgroud)

这些函数预处理它的输入,以便它可以独立于当前语言环境使用,在假设下

  1. 分隔符是一个字节
  2. setlocale在这些修复函数和对任何受影响函数的调用之间没有调用
  3. 字符串可以在转换前修改

(1) 意味着预处理方法在异国语言环境中中断(参见https://en.wikipedia.org/wiki/Decimal_mark#Hindu.E2.80.93Arabic_numeral_system示例)。(2) …

c locale standard-library

5
推荐指数
1
解决办法
1364
查看次数

标签 统计

c ×1

c++ ×1

locale ×1

parsing ×1

standard-library ×1

std ×1