Use negative look-ahead expression:
Negative lookahead is indispensable if you want to match something not followed by something else: q(?!u)
means q
not followed by u
In your case q
is %
, and u
is ([.]?[0-9]+)?[a-zA-Z]
(an optional prefix of an optional dot followed by one or more numbers, and a letter suffix).
Demo 1
Note: This expression uses +
in the look-ahead section, a feature that does not have universal support. If your regex engine does not take it, set an artificial limit of, say, 20 digits by replacing [0-9]+
with [0-9]{1,20}
.
Edit:
What about writing my own parser?
If you need the ultimate speed for this relatively simple regex, use a hand-written parser. Here is a quick example:
for (string str ; getline(cin, str) ; ) {
bool found = false;
size_t pos = 0;
while (!found && (pos = str.find('%', pos)) != string::npos) {
if (++pos == str.size()) {
found = true;
break;
}
if (str[pos] == '.') {
if (++pos == str.size()) {
found = true;
break;
}
if (!isdigit(str[pos])) {
found = true;
break;
}
}
while (isdigit(str[pos])) {
if (++pos == str.size()) {
found = true;
break;
}
}
found |= !isalpha(str[pos]);
}
cout << '"' << str << '"' << " : " << found << endl;
}
Demo 2