tags:

views:

262

answers:

2

Can anyone give me complete example program how to work with GNU regex functions in gcc C or C++ (http://docs.freebsd.org/info/regex/regex.info.GNU_Regex_Functions.html), with re_pattern_buffer, re_compile_fastmap?

For example, translate this small Python program:

import re
unlucky = re.compile('1\d*?3')

nums = ("13", "31", "777", "10003")

for n in nums:
    if unlucky.search(n) is None:
        print "lucky"
    else:
        print "unlucky"

Thanks!

A: 

Maybe this example collection will be of some help?

Vlad
I already looked at that article, but C++ examples there don't work and don't even compile: missing several semicolons. But even after I fixed semicolons I get "free(): invalid pointer" on `regfree()`. I think that author of that C++ program didn't really understand what he did. Also I'd like to see some comments.
Sergey Dymchenko
+2  A: 

Okay, before delving into the code, I should mention that you may want to use a higher-level library. You did say C++, so that opens you up to Boost.Regex and the like. Even if you want to stay with C, there are better options. I find the POSIX functions somewhat cleaner, not to mention more portable.

// Tell GNU to define the non-standard APIs
#define _GNU_SOURCE 
// This is actually the same header used for the POSIX API.
// Except then you obviously don't need _GNU_SOURCE
#include <regex.h> 
#include <stdio.h>
#include <string.h>

int main()
{
    struct re_pattern_buffer pat_buff; // Put a re_pattern_buffer on the stack
    // The next 4 fields must be set.  

    // If non-zero, applies a translation function to characters before 
    // attempting match (http://www.delorie.com/gnu/docs/regex/regex_51.html)
    pat_buff.translate = 0; 
    // If non-zero, optimization technique.  Don't know details.
    // See http://www.delorie.com/gnu/docs/regex/regex_45.html
    pat_buff.fastmap = 0;
    // Next two must be set to 0 to request library allocate memory
    pat_buff.buffer = 0;
    pat_buff.allocated = 0;
    char pat_str[] = "1[^3]*3";
    // This is a global (!) used to set the regex type (note POSIX APIs don't use global for this)
    re_syntax_options = RE_SYNTAX_EGREP; 
    // Compile the pattern into our buffer
    re_compile_pattern(pat_str, sizeof(pat_str) - 1, &pat_buff); 
    char* nums[] = {"13", "31", "777", "10003"}; // Array of char-strings
    for(int i = 0; i < sizeof(nums) / sizeof(char*); i++)
    {
        int match_ret;
        // Returns number of characters matches (may be 0, but if so there's still a match)
        if((match_ret = re_match(&pat_buff, nums[i], strlen(nums[i]), 0, NULL)) >= 0) 
        {
            printf("unlucky\n");
        }
        else if(match_ret == -1) // No match
        {
            printf("lucky\n");
        }
        // Anything else (though docs say -2) is internal library error
        else 
    {
            perror("re_match");
        }
    }
    regfree(&pat_buff);
}

EDIT: I added more explanation of the required fields, and the regfree. I had the lucky/unlucky backwards before, which explains part of the discrepancy. The other part is that I don't think any of the regex syntaxes available here support lazy operators (*?). In this case, there's a simple fix, using "1[^3]*3".

Matthew Flaschen
Thanks! But the output should be "unlucky lucky lucky unlucky", while I got "lucky unlucky unlucky unlucky".Also could you comment on `pat_buff.translate = 0; pat_buff.fastmap = 0; pat_buff.buffer = 0; pat_buff.allocated = 0;` part? And also what about `regfree()`? When we need to use it?
Sergey Dymchenko
As for Boost.Regex I can't use it because the program will work in specific environment where Boost isn't available. Also portability is not an issue - the program have to compile on specific version of gcc only.
Sergey Dymchenko
Thanks! It works now. Also I thinks that instead of `re_syntax_options` global we can use `re_set_syntax()` function.
Sergey Dymchenko
`re_set_syntax` just sets the global and returns the old value. :)
Matthew Flaschen