如何保证一组特定的字符作为 string_view 参数的输入?

Posted

技术标签:

【中文标题】如何保证一组特定的字符作为 string_view 参数的输入?【英文标题】:How to guarantee a specific set of characters as input to a string_view parameter? 【发布时间】:2020-08-19 17:56:18 【问题描述】:

我正在研究一种设计实现,我希望从一组特定字符中选择输入作为其字符串文字表示。

考虑以下一组类:

class enum BaseType 
    BINARY = 2,
    OCTAL = 8,
    DECIMAL = 10,
    HEXADECIMAL = 16
;

template<BaseType BASE = BaseType::DECIMAL> // Default Template
class Foo 
public:
    const uint16_t BaseBASE;
private: 
    std::string digits_;
    int64_t integral_value_;
    int64_t decimal_value_;
    size_t decimal_index_location_;
public:
    Foo() 
      : digits_"", 
        integral_value_0, 
        decimal_value_0
        decimal_index_location_0
    
    Foo(const std::string_view digit_sequence) 
      : digits_digit_sequence, 
        integral_value_0, 
        decimal_value_0
        decimal_index_location0
    
        // set values according to the respective digits 
        // from the decimal point if one exists
        // and set the decimal index location if one exists...
    
;

我可能不得不对其他尚未确定的非默认类型使用特化。无论如何,我想将每种情况限制为以下字符集,如下所示:

BINARY'0', '1', '.' OCTAL['0' - '7'], '.' DECIMAL['0' - '9'], '.' HEXADECIMAL['0' - '9'], ['a' - 'f'], ['A' - 'F'], '.'

这些对于每种类型都是可接受的输入:

BINARY"010"".010""01.0""01."等... OCTAL"012345670"".012345670""01.2345670""1." 等... DECIMAL"01234567890"".01234567890""01.234567890""1." 等... HEXADECIMAL"0123456789abcdef0"".0123456789abcdef0""01.23456789abcdef0""1." 等... "0123456789ABCDEF0"".0123456789ABCDEF0""01.23456789ABCDEF0""1." 等...

成为类构造函数的string_view 参数的唯一有效输入字符集。


有没有一种简单、优雅、高效的方法来做到这一点?如果是这样,怎么做?是否通过抛出异常、编译时或运行时断言来处理这并不重要……我只想限制每个模板版本的可能有效字符集……


编辑

对于每种情况,即使单个 '.' 也是有效输入。例如:

Foo a("."); 

将被解释为0,稍后当我合并exponent 部分时,指数将评估为1,因此结果将是0,而不是1,因为电源规则...

【问题讨论】:

使用正则表达式查看输入是否匹配正确的模式? @NathanOliver,我得调查一下,我从来没有真正和 regex 合作过这么多...... 【参考方案1】:

使用&lt;regex&gt;,您可以这样做:

static const std::regex binary_regex(R"([01]*\.?[01]*)");
static const std::regex octal_regex(R"([0-7]*\.?[0-7]*)");
static const std::regex decimal_regex(R"([0-9]*\.?[0-9]*)");
static const std::regex hex_regex(R"([0-9a-fA-F]*\.?[0-9a-fA-F]*)");

bool do_match(const std::string& s, const std::regex& regex)

    // if (s.empty())  return false; 
    std::smatch base_match;
    
    return std::regex_match(s, base_match, regex);   

Demo

您甚至可以通过分组获得点之前和之后的值

【讨论】:

我喜欢这个建议,只是为了清楚起见,只是一个简单的问题......上面是否只允许一个.?我不想要 243.4252.342 这样的字符串。 是的,只允许使用一个点,因此只允许使用“”、“00”、“00.”、“00.00”、“.00”等形式的数字。 这只有一个问题......到目前为止一切正常,但是当我传入一个字符串,如 "24526" 没有小数点时,regex 抛出一个未处理的异常。 .. link 添加,这里没有问题。 在正则表达式 Demo 中使用组的简化版本。请注意,尽管您计算十进制的方式可能不是您对非十进制的期望:二进制中的0.10.25,即使是十进制前导0 也会丢失0.9。

以上是关于如何保证一组特定的字符作为 string_view 参数的输入?的主要内容,如果未能解决你的问题,请参考以下文章

将 std::string_view 与 api 一起使用,期望以 null 终止的字符串

将 std::string_view 与 api 一起使用,期望以 null 终止的字符串

如何在编译时从 string_view 中删除子字符串?

由给定字符串支持的 string_view

如何键入 Typescript 数组以仅接受一组特定的值?

比较 std::string_view 和子字符串 string_view