gpt4 book ai didi

c++ - 有效地从字符串中读取括号中的两个逗号分隔的 float ,而不受全局语言环境的影响

转载 作者:可可西里 更新时间:2023-11-01 16:38:43 26 4
gpt4 key购买 nike

我是一个图书馆的开发人员,我们的旧代码使用sscanf()sprintf()从字符串读取/写入各种内部类型。与使用我们的库且其语言环境与我们基于XML文件的语言环境(“C”语言环境)不同的用户遇到了问题。在我们的例子中,这导致从这些XML文件解析出的值不正确,并且在运行时以字符串形式提交了这些值。用户可以直接更改语言环境,但也可以在用户不知情的情况下更改语言环境。如果语言环境更改发生在另一个库(例如GTK)中,而该库是一个错误报告中的“肇事者”,则可能会发生这种情况。因此,我们显然希望从语言环境中删除任何依赖关系,以使自己永久摆脱这些问题。

我已经阅读了关于float/double/int/...的其他问题和答案,特别是如果它们之间用字符分隔或放在方括号内,但是到目前为止,我发现的建议解决方案对我们来说并不令人满意。我们的要求是:

  • 除标准库外,不依赖其他库。因此,例如,不能使用boost中的任何东西。
  • 必须是线程安全的。这是特定于语言环境的意思,可以全局更改。这对我们来说真的很糟糕,因为我们的库中的一个线程可能会受到用户程序中另一个线程的影响,该线程也可能正在运行完全不同的库中的代码。因此,不受setlocale()直接影响的任何事情都是不可行的。同样,由于线程中的竞争条件,在开始读取/写入之前设置语言环境,然后再将其设置回原始值也不是解决方案。
  • 尽管效率不是最高优先级(#1和#2是最高优先级),但它仍然绝对是我们关注的问题,因为根据用户的程序,在运行时可能会频繁地读写字符串。越快越好。

  • 编辑:作为附加说明:不能保证 boost::lexical_cast不受语言环境的影响(来源: Locale invariant guarantee of boost::lexical_cast<>)。因此,即使没有要求#1,这也不是解决方案。

    到目前为止,我收集了以下信息:
  • 首先,我发现很多建议都在使用boost的lexical_cast,但不幸的是,这根本不是我们的选择,因为我们不能要求所有用户也都链接到boost(并且由于缺少语言环境,安全,请参见上文)。我查看了一下代码,看是否可以从中提取任何内容,但是我发现它很难理解,而且长度太大,而且最有可能获得性能提升的人还是在使用依赖于语言环境的函数。
  • C++ 11中引入的许多功能,例如std::to_stringstd::stodstd::stof等,都依赖于全局语言环境,就像sscanf和sprintf一样,这是非常不幸的,并且考虑到std::thread具有对我来说是无法理解的已添加。
  • 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 } , left: { %g , %g } , bottom: { %g , %g } , right: { %g , %g }"

  • 用stringstreams编写这些似乎没什么大不了,但是阅读它们似乎有问题,尤其是考虑到空格。

    在这种情况下,我们应该使用 std::regex还是过度杀伤力?字符串流是此任务的理想解决方案,还是在提到的要求下还有更好的方法吗?另外,在线程安全性和语言环境的上下文中是否还有其他我没有考虑的问题,特别是在使用std::stringstream时?

    最佳答案

    在您的情况下,stringstream似乎是最好的方法,因为您可以独立于所设置的全局语言环境来控制其语言环境。但是,的确,格式化的阅读并不像sscanf()那样简单。

    从性能的角度来看,使用正则表达式输入流对于这种简单的逗号分隔读取来说是一个过大的杀伤力:在一个非正式的基准上,它比scanf()慢十倍以上。

    您可以轻松地编写一些辅助类来促进阅读格式(如您所列举的那样)。在这里,关于another SO answer的一般想法可以很容易地使用:

    sst >> mandatory_input(" { ")>> x >> mandatory_input(" , ")>>y>> mandatory_input(" } ");

    如果您有兴趣,我前段时间已经写过。这里是 full article with examples and explanation as well as source code。该类有70行代码,但其中大多数可提供错误处理功能,以备需要时使用。它具有可接受的性能,但仍比scanf()慢。

    关于c++ - 有效地从字符串中读取括号中的两个逗号分隔的 float ,而不受全局语言环境的影响,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31977457/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com