HOWTO · C
Regular Expressions in C
In this article, we'll talk about regular expressions in C.
On this page
POSIX regular-expression functions let a C program compile a pattern, test strings against it, and inspect whether each test matched. Regular expressions are not part of the C language itself; this article uses the POSIX <regex.h> interface.
Regular expressions in C with POSIX
A regular expression describes a pattern in text. POSIX provides two main pattern syntaxes: basic regular expressions and extended regular expressions. The examples below select the extended syntax with REG_EXTENDED.
Bracket expressions match one character from a set. For example, [abc] matches a, b, or c; [[:digit:]] matches a digit; [[:alnum:]_] matches an alphanumeric character or underscore; and [[:lower:]] matches a lowercase letter in the active locale. A POSIX character class must be written inside a bracket expression, so forms such as [:number:] and [:word:] are not the standard classes. Use [[:digit:]] for digits and [[:alnum:]_] when you want letters, digits, and underscore.
The matching behavior can depend on the current locale, particularly for character classes and case folding. Set the locale deliberately if an application needs locale-specific rules. POSIX implementations provide this API, but the C language alone does not guarantee it.
Compile a POSIX regular expression with regcomp()
Declare a regex_t object to hold the compiled expression, then pass its address, a NUL-terminated pattern, and compilation flags to regcomp(). With REG_EXTENDED, operators such as + use extended regular-expression syntax. Add REG_ICASE for case-insensitive matching or REG_NOSUB when submatch offsets are not needed.
regcomp() returns 0 when compilation succeeds. A nonzero return is an error code; it is not an errno value. Use regerror() with the same regex_t object to format a diagnostic. Only call regfree() after successful compilation.
Match strings with regexec() and release the compiled regex
Call regexec() with the compiled regex_t and a NUL-terminated string. A return value of 0 means a match, while REG_NOMATCH means the pattern did not match. Any other value indicates an execution error and can be formatted with regerror(). When submatch locations are needed, provide an array of regmatch_t entries and its capacity; the first entry describes the overall match. With REG_NOSUB, do not request submatch locations.
This complete example compiles one pattern, tests two strings, and releases the compiled object. It reports compile and execution diagnostics through regerror(). In the supplied successful run, it printed match followed by no match and exited with code 0.
Run this example:
#include <regex.h>
#include <stddef.h>
#include <stdio.h>
int main(void) {
regex_t re;
const char *pattern = "[[:alpha:]]+";
int status = regcomp(&re, pattern, REG_EXTENDED);
if (status != 0) {
char message[256];
regerror(status, &re, message, sizeof message);
printf("compile: %s\n", message);
return 1;
}
const char *samples[] = {"C language", "123"};
for (size_t i = 0; i < sizeof samples / sizeof samples[0]; ++i) {
status = regexec(&re, samples[i], 0, NULL, 0);
if (status == 0) {
puts("match");
} else if (status == REG_NOMATCH) {
puts("no match");
} else {
char message[256];
regerror(status, &re, message, sizeof message);
printf("execution: %s\n", message);
}
}
regfree(&re);
return 0;
}
match
no match
The sample checks each return value before using it and preserves the compiled expression until both strings have been tested. The supplied run exited with code 0. The example requires a POSIX <regex.h> implementation.