c++regexqtqregexp

Validating integer part of an string


I have a text file that I need to convert each line into integer.

The lines can begin with '#' to indicate a comment. Also, after the data it might be inline comment too...again indicated by '#'

So I have the example below:

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

How can I take care of these cases? I mean in all the 4 example above except the last two I need to extract "5000". How to find out the last one is invalid?

So I mean what is the best fail-proof code to handle this task?


Solution

  • Another example using std::regex. Converting QString to a string_view is left as an exercise for the reader.

    #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));
        }
    }
    

    expected output:

    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