-2

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?

DEKKER
  • 877
  • 6
  • 19

2 Answers2

1

You can use this regex to validate and extract the digit from first grouping pattern that will capture your number,

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

Explanation:

  • ^ - Start of string
  • \s* - Allows optional space before the number
  • (\d+) - Captures the number and places it in first grouping pattern
  • \b - Ensures the number does not match partially in a larger text because of the negative look ahead present ahead
  • (?!\.) - Rejects the match if there is a decimal following the number

Demo1

In case only last one is invalid, you can use this regex to capture number from first three entries,

^\s*(\d+)

Demo2

Pushpesh Kumar Rajwanshi
  • 18,127
  • 2
  • 19
  • 36
1

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

Richard Hodges
  • 68,278
  • 7
  • 90
  • 142