【问题标题】:Validating integer part of an string验证字符串的整数部分
【发布时间】:2019-02-18 11:51:19
【问题描述】:

我有一个文本文件,我需要将每一行转换为整数。

行可以以“#”开头表示注释。此外,在数据之后,它也可能是内联注释...再次用“#”表示

所以我有下面的例子:

QString time = "5000 #this is 5 seconds";  // OK      
QString time = "  5000 # this is 5 seconds"; // OK..free spaceis allowed at start        
QString time = "5000.00 #this is 5 seconds"; // invalid...no decimal 
QString time = "s5000 # this is 5 seconds"; // invalid...does not start with numerical character

我该如何处理这些情况?我的意思是在上面的所有 4 个示例中,除了最后两个我需要提取“5000”。如何查出最后一个无效?

所以我的意思是处理这项任务的最佳防故障代码是什么?

【问题讨论】:

  • 您在代码中的评论说最后两个无效,而在帖子中您说只有最后一个无效?正确的说法是什么?
  • 1:正则表达式,2:boost.spirit解析器,3:其他解析器。
  • 您要使用的正则表达式是[0-9]\+。如果匹配,请使用QString::toInt
  • @PushpeshKumarRajwanshi 现已更正
  • 您也许可以使用QTime 而不是QString,然后您会让编译器为您验证它。

标签: c++ regex qt qregexp


【解决方案1】:

另一个使用std::regex的例子。将QString 转换为string_view 留给读者作为练习。

#include <regex>
#include <string_view>
#include <iostream>
#include <string>
#include <optional>

std::optional<std::string> extract_number(std::string_view input)
{
    static constexpr char expression[] = R"xx(^\s*(\d+)\s*(#.*)?$)xx";
    static const auto re = std::regex(expression);

    auto result = std::optional<std::string>();
    auto match = std::cmatch();
    const auto matched = std::regex_match(input.begin(), input.end(), match, re);
    if (matched)
    {
        result.emplace(match[1].first, match[1].second);
    }

    return result;
}

void emit(std::string_view candidate, std::optional<std::string> result)
{
    std::cout << "offered: " << candidate << " - result : " << result.value_or("no match") << '\n';
}

int main()
{
    const std::string_view candidates[] = 
    {
"5000 #this is 5 seconds",
"  5000 # this is 5 seconds",
"5000.00 #this is 5 seconds",
"s5000 # this is 5 seconds"
    };

    for(auto candidate : candidates)
    {
        emit(candidate, extract_number(candidate));
    }
}

预期输出:

offered: 5000 #this is 5 seconds - result : 5000
offered:   5000 # this is 5 seconds - result : 5000
offered: 5000.00 #this is 5 seconds - result : no match
offered: s5000 # this is 5 seconds - result : no match

https://coliru.stacked-crooked.com/a/2b0e088e6ed0576b

【讨论】:

    【解决方案2】:

    您可以使用此正则表达式来验证并从第一个分组模式中提取数字,该分组模式将捕获您的号码,

    ^\s*(\d+)\b(?!\.)
    

    说明:

    • ^ - 字符串开始
    • \s* - 允许数字前的可选空格
    • (\d+) - 捕获数字并将其置于第一个分组模式中
    • \b - 确保数字不会在较大的文本中部分匹配,因为前面存在负面预测
    • (?!\.) - 如果数字后面有小数则拒绝匹配

    Demo1

    如果只有最后一个无效,您可以使用此正则表达式从前三个条目中捕获数字,

    ^\s*(\d+)
    

    Demo2

    【讨论】:

      猜你喜欢
      • 2021-11-13
      • 1970-01-01
      • 1970-01-01
      • 2018-11-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-26
      • 1970-01-01
      • 2016-02-22
      相关资源
      最近更新 更多