解析末尾带有值修饰符('-'、'%')的字符串

2024-04-25

我尝试着去掌握解析。

我有一些数据来自de-de格式在字符串末尾带有附加信息。

我设法使 de-de 部分正确,但我很难得到- and %解析正确。我读了codecvt但我不明白这个话题。

这是我迄今为止所理解的反映以及我需要做的事情的示例。

#include <string>
#include <locale>
#include <iostream>
#include <sstream>

using namespace std;

#define EXPECT_EQ(actual, expected) { \
    if (actual != expected) \
    { \
        cout << "expected " << #actual << " to be " << expected << " but was " << actual << endl; \
    } \
}

double parse(wstring numstr)
{
    double value;
    wstringstream is(numstr);
    is.imbue(locale("de-de"));
    is >> value;
    return value;
}

int main()
{
    EXPECT_EQ(parse(L"123"), 123); //ok
    EXPECT_EQ(parse(L"123,45"), 123.45); //ok
    EXPECT_EQ(parse(L"1.000,45"), 1000.45); //ok
    EXPECT_EQ(parse(L"2,390%"), 0.0239); //% sign at the end
    EXPECT_EQ(parse(L"1.234,56-"), -1234.56); //- sign at the end
}

输出是:

expected parse(L"2,390%") to be 0.0239 but was 2.39
expected parse(L"1.234,56-") to be -1234.56 but was 1234.56

我怎样才能注入我的流,以便它读取- and %像我需要的那样签名?


我会正面解决这个问题:让我们在这里开始解析。

无论如何,你最终都会在某个地方写下它,所以我会忘记首先需要创建一个(昂贵的)字符串流。

选择的武器:提升精神

Note,

  • 我直接使用它的迭代器解析字符串。我的代码很漂亮 关于所使用的浮点数的类型的通用。

  • 您几乎可以搜索替换double例如boost::multiprecision::cpp_dec_float(或者将其作为模板 参数)并进行解析。因为我预测你需要解析decimal浮点数,不是binary浮点数字。您会失去转换的准确性。

UPDATE: 扩展样本住在科里鲁 http://coliru.stacked-crooked.com/a/61512abc5396630d

简单语法

从本质上讲,语法非常简单:

if (parse(numstr.begin(), numstr.end(), mynum >> matches['-'] >> matches['%'],
            value, sign, pct)) 
{
    if (sign) value = -value;
    if (pct)  value /= 100;

    return value;
}

你有它。当然,我们需要定义mynum所以它解析unsigned如预期的实数:

using namespace qi;
real_parser<double, de_numpolicy<double> > mynum;

魔术:real_policies<>

该文档详细解释了如何使用调整实数解析real_policies http://www.boost.org/doc/libs/1_59_0/libs/spirit/doc/html/spirit/qi/reference/numeric/real.html#spirit.qi.reference.numeric.real._code__phrase_role__identifier__realpolicies__phrase___code_。这是我想出的政策:

template <typename T>
    struct de_numpolicy : qi::ureal_policies<T>
{
    //  No exponent
    template <typename It>                static bool parse_exp(It&, It const&)          { return false; } 
    template <typename It, typename Attr> static bool parse_exp_n(It&, It const&, Attr&) { return false; } 

    //  Thousands separated numbers
    template <typename It, typename Attr>
    static bool parse_n(It& first, It const& last, Attr& attr)
    {
        qi::uint_parser<unsigned, 10, 1, 3> uint3;
        qi::uint_parser<unsigned, 10, 3, 3> uint3_3;

        if (parse(first, last, uint3, attr)) {
            for (T n; qi::parse(first, last, '.' >> uint3_3, n);)
                attr = attr * 1000 + n;

            return true;
        }

        return false;
    }

    template <typename It>
        static bool parse_dot(It& first, It const& last) {
            if (first == last || *first != ',')
                return false;
            ++first;
            return true;
        }
};

完整演示

Live On Coliru http://coliru.stacked-crooked.com/a/50416c7060695ab5

#include <boost/spirit/include/qi.hpp>
#include <iostream>


#define EXPECT_EQ(actual, expected) { \
    double v = (actual); \
    if (v != expected) \
    { \
        std::cout << "expected " << #actual << " to be " << expected << " but was " << v << std::endl; \
    } \
}

namespace mylib {
    namespace qi = boost::spirit::qi;

    template <typename T>
        struct de_numpolicy : qi::ureal_policies<T>
    {
        //  No exponent
        template <typename It>                static bool parse_exp(It&, It const&)          { return false; } 
        template <typename It, typename Attr> static bool parse_exp_n(It&, It const&, Attr&) { return false; } 

        //  Thousands separated numbers
        template <typename It, typename Attr>
        static bool parse_n(It& first, It const& last, Attr& attr)
        {
            qi::uint_parser<unsigned, 10, 1, 3> uint3;
            qi::uint_parser<unsigned, 10, 3, 3> uint3_3;

            if (parse(first, last, uint3, attr)) {
                for (T n; qi::parse(first, last, '.' >> uint3_3, n);)
                    attr = attr * 1000 + n;

                return true;
            }

            return false;
        }

        template <typename It>
            static bool parse_dot(It& first, It const& last) {
                if (first == last || *first != ',')
                    return false;
                ++first;
                return true;
            }
    };

    template<typename Char, typename CharT, typename Alloc>
    double parse(std::basic_string<Char, CharT, Alloc> const& numstr)
    {
        using namespace qi;
        real_parser<double, de_numpolicy<double> > mynum;

        double value;
        bool sign, pct;

        if (parse(numstr.begin(), numstr.end(), mynum >> matches['-'] >> matches['%'],
                    value, sign, pct)) 
        {
            // std::cout << "DEBUG: " << std::boolalpha << " '" << numstr << "' -> (" << value << ", " << sign << ", " << pct << ")\n";
            if (sign) value = -value;
            if (pct)  value /= 100;

            return value;
        }

        assert(false); // TODO handle errors
    }

} // namespace mylib

int main()
{
    EXPECT_EQ(mylib::parse(std::string("123")),       123);      // ok
    EXPECT_EQ(mylib::parse(std::string("123,45")),    123.45);   // ok
    EXPECT_EQ(mylib::parse(std::string("1.000,45")),  1000.45);  // ok
    EXPECT_EQ(mylib::parse(std::string("2,390%")),    0.0239);   // %  sign at the end
    EXPECT_EQ(mylib::parse(std::string("1.234,56-")), -1234.56); // -  sign at the end
}

如果取消注释“DEBUG”行,它将打印:

DEBUG:  '123' -> (123, false, false)
DEBUG:  '123,45' -> (123.45, false, false)
DEBUG:  '1.000,45' -> (1000.45, false, false)
DEBUG:  '2,390%' -> (2.39, false, true)
DEBUG:  '1.234,56-' -> (1234.56, true, false)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

解析末尾带有值修饰符('-'、'%')的字符串 的相关文章

  • Microsoft Visual C++ 2008 和 R2007b 的 Mex 类型

    我想对 vs2008 和 matlab2007b 使用 mex 类型 我尝试了下面的代码 include
  • C# 中的 DateTime.Parse 抛出异常

    我不知道为什么抛出异常 这是工作代码 DateTime Parse 1 12 2012 12 00 00 AM 这是抛出异常的一个 DateTime Parse 1 13 2012 12 00 00 AM 抛出的异常是 格式异常 包括此消息
  • 仅使用 1 行 C++ 初始化 2d 向量

    我需要能够初始化一个 2D 向量 int同一条线我在其中创建它 更具体地说 我必须创建一个3x2大小 2D 向量并将其所有值设置为 0 仅使用1行代码 有没有一种方法可以在不使用 for 循环和几行代码的情况下完成此操作 尝试这个 std
  • 从 proc/pid/cmdline 解析命令行参数

    我正在尝试解析命令行参数另一个程序 这是一个模拟器 在我的程序中使用system 命令和模拟器的pid 不幸的是同时使用文件读取和cat 输出格式不正确 所以我无法真正获取数据 cat在命令行上显示删除了空格的文件内容 整个字符串粘在一起
  • 导入数据期间解析日期格式的最佳方法

    我创建了在数据导入 400 K 记录 期间解析视图不同日期格式的方法 我的方法捕获 ParseException 并尝试在不同时使用下一种格式解析日期 问题 在数据导入期间设置正确的日期格式是更好的方法 更快 吗 private stati
  • 通知另一个线程数据可用的最快方法是什么?有什么替代旋转的方法吗?

    我的一个线程将数据写入循环缓冲区 另一个线程需要尽快处理该数据 我本来想写这么简单的spin 伪代码 while true while a i do nothing just keep checking over and over proc
  • C 或 C++ 中是否有轻量级的多部分/表单数据解析器? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在考虑将多部分表单数据解析集成到 Web 服务器模块中 以便可以减轻后端 Web 应用程序 通常用动
  • 使用正在运行的进程的共享内存收集核心转储

    核心转储仅收集进程空间 而不收集为进程间通信创建的共享内存 如何使核心转储也包含正在运行的进程的共享内存 设置核心文件过滤器 proc PID coredump filter per http man7 org linux man page
  • 将迭代器取消引用到临时范围时出现非指针操作数错误

    Using auto empty line auto str return str size 0 我们做得到 auto line range with first non empty ranges view drop while range
  • 在 Visual Studio 中调试时向后拖动指令指针

    如需演示 请查看 基本上 我知道这在 Visual Studio Community Edition 2015 中是可能的 我想知道 a 这与 Intellitrace 和 历史调试 有关吗 b 这样做会有副作用吗 或者这只是将指令向后移动
  • 从网站保存嵌入的 pdf

    我正在编写一个小型 C 应用程序来管理供应商提供的 化学品 安全数据表 目前 我手动搜索该化学品并保存 pdf 并在我的程序中添加指向 pdf 的链接 问题是我还有很多化学品需要处理 所以最好将过程自动化 例如 化学品的部件号如下 2710
  • 使用 PrimarySearcher.FindAll() 时出现内存泄漏

    我也有一个使用插件和应用程序域长时间运行的服务 并且由于使用目录服务而出现内存泄漏 请注意 我正在使用 system directoryservices accountmanagement 但据我了解 它使用相同的底层 ADSI API 因
  • 在 Winforms 中,PreviewKeyDown() 从未针对任何键触发

    我最初试图让我的程序获取箭头键 上 下 左 右 的输入 但发现在 KeyDown 中这些键从未出现过 后来我发现我可以通过进入 PreviewKeyDown 函数并设置来启用箭头键 e IsInputKey true 及其周围的任何条件和逻
  • invoke_result获取模板成员函数的返回类型

    如何获取模板成员函数的结果类型 下面的最小示例说明了该问题 include
  • 从 WMI 运行 exe 时的网络身份验证

    我有一个 C exe 需要使用 WMI 运行并访问网络共享 但是 当我访问共享时 我收到 UnauthorizedAccessException 如果我直接运行 exe 则可以访问共享 我在这两种情况下都使用相同的用户帐户 我的应用程序有两
  • 为什么这些双精度数的返回值为-1.#IND?

    I have double score cvMatchContourTrees CT1 CT2 CV CONTOUR TREES MATCH I1 0 0 cout lt
  • 从原始 URL 获取重定向 URL

    我的数据库中有一个表 其中包含一些网站的 URL 我必须打开这些 URL 并验证这些页面上的一些链接 问题是某些 URL 被重定向到其他 URL 对于这样的 URL 我的逻辑是失败的 有什么方法可以传递原始 URL 字符串并获取重定向的 U
  • 使用 STL 迭代器而不初始化它

    我想做这样的事情 container iterator it NULL switch eSomeEnum case Container1 it vecContainer1 begin break case Container2 it vec
  • C++ 中的 Ofstream 数组

    我想要在我的项目中使用 41 个输出文件来在其上写入文本 首先创建一个字符串数组list为了命名这些输出文件 然后我尝试定义一个 ofstream 对象数组并使用list命名它们 但我收到此错误 outfile cannot be used
  • C# 泛型中的通配符等效项

    假设我有一个通用类 如下所示 public class GeneralPropertyMap

随机推荐