Pagina 1 di 1

[C] Problemino con regex

Inviato: lun 7 gen 2008, 19:41
da Dani
Non riesco a recuperare piu' di un'occorrenza in un'espressione...
Esempio:

Codice: Seleziona tutto

#include <stdio.h>
#include <string.h>
#include <regex.h>
#include <assert.h>
#define MAX_MATCH 50
int main (void)
{
char str[] = "AAAAAAciao1ZZZZZZ\n"
             "AAAAAAciao5ZZZZZZ\n"
             "AAAAAAciao9ZZZZZZ\n",
buff[50];

regex_t preg;
regmatch_t matches[MAX_MATCH];
u_short i;

assert (!regcomp (&preg, "ciao[0-9]", REG_EXTENDED));
assert (!regexec (&preg, str, MAX_MATCH, matches, REG_EXTENDED));

for (i = 0; matches[i].rm_so >= 0 && i < MAX_MATCH; i++)
{
strncpy (buff, str + matches[i].rm_so, matches[i].rm_eo - matches[i].rm_so); 
printf ("Match %u: %s\n", i, buff);
}
regfree (&preg);
return 0;
}
Questo codice mi restituisce solo la prima delle tre stringhe.
Ma dove sbaglio ? #-o

Re: [C] Problemino con regex

Inviato: lun 7 gen 2008, 20:41
da Blizzard
ciao,

forse non posso esserti troppo utile perchè non conosco la libreria...
ma
regexec (&preg, str, MAX_MATCH, matches, REG_EXTENDED)
non ti controlla solo la prima stringa???

Codice: Seleziona tutto

int regexec(const  regex_t  *preg,  const  char *string, size_t nmatch,
                   regmatch_t pmatch[], int eflags);
il secondo parametro è una stringa (come puntatore a char)... di conseguenza passandogli str... non solo passi un puntatore a puntatore, ma in teoria se funziona è perche str punta alla prima locazione delle 3 stringhe.

forse sto prendendo una cantonata ma prova questo
regexec (&preg, str[0], MAX_MATCH, matches, REG_EXTENDED)
regexec (&preg, str[1], MAX_MATCH, matches, REG_EXTENDED)
insomma fai un for..

posso aver scritto parecchie ca****.... ma ad occhio e croce mi sembra una cosa simile
ciao
Gio

Re: [C] Problemino con regex

Inviato: mer 9 gen 2008, 15:44
da Dani
str è una sola stringa, espressioni come str[n] portano ad un segfault :(
regexec() vuole una sola stringa, in questa ricercherà il pattern e ne memorizzerà la posizione iniziale e finale rispettivamente nei membri rm_so ed rm_eo, della struct regmatch_t.

Re: [C] Problemino con regex

Inviato: mer 9 gen 2008, 16:46
da Blizzard
auauauauauauau scusa ho toppato! #-o
mi sembrava la dichiarazione di un array! ... =D> =D> =D> applausi per me

mmm... ma non è che regexec si ferma al primo \n \0 ????
hai provato a togliere i \n e a vedere che succede??

ciao
Gio

Re: [C] Problemino con regex

Inviato: mer 9 gen 2008, 17:11
da Dani
Togliendo i vari '\n' non cambia nulla #-o

Re: [C] Problemino con regex

Inviato: mer 9 gen 2008, 17:40
da puzuma
hai interpretato male il signicato del terzo parametro di regexec, indica il numero di sottoespressioni da valutare, non i risultati, de vi usare qualcosa del tipo:

Codice: Seleziona tutto

error = regexec (&preg, str, 1, matches, 0) ;
while (error = = 0) { 
error = regexec (&preg, matches.rm_ep, 1, &matches, REG_NOTBOL) ;
}

Re: [C] Problemino con regex

Inviato: mer 9 gen 2008, 18:09
da nuitari
Andiamo con ordine :)

Innanzitutto, ci sono un po' di erroretti. Il primo e più visibile è:

Codice: Seleziona tutto

assert (!regexec (&preg, str, MAX_MATCH, matches, REG_EXTENDED));
regexec usa flags completamente diversi da regcomp, e REG_EXTENDED è un flag di regcomp.

il secondo è:

Codice: Seleziona tutto

strncpy (buff, str + matches[i].rm_so, matches[i].rm_eo - matches[i].rm_so); 
strncpy copia pezzi di stringa SENZA aggiungere il terminatore, ovviamente. Significa che ti troverai con pezzi delle stringhe più grandi mischiati a quelli delle stringhe più piccole.. non è bello =)

Al di la di questo, il punto è:

regexec non trova tutte le occorrenze presenti in una stringa, ma solo la prima. Devi fare un ciclo se vuoi trovarle tutte, aumentando l'offset del puntatore alla stringa ogni volta ed usando ad hoc il flag REG_NOTBOL.

L'array matches è un array poichè restituisce non tutte le occorrenze di un pattern in una stringa (che per inciso è terminata da NULL, non da NEWLINE), ma le occorrenze dei subpattern, se presenti. I subpattern sono le parti della regular expression fra parentesi.
Per fartelo capire, modificherò un pelo il tuo esempio (un pelo nel senso che non lo stravolgo, anche se io l'avrei programmato diversamente):

Codice: Seleziona tutto

#include <stdio.h>
#include <string.h>
#include <regex.h>
#include <assert.h>
#define MAX_MATCH 10

int main (void)
{
        char      str[] = "AAAAAAciao1ZZZZZZAAAAAAciao5ZZZZZZ"
                , buff[50];

        regex_t preg;
        regmatch_t matches[MAX_MATCH];
        u_short i;

        assert (!regcomp (&preg, "ci(ao)", REG_EXTENDED));
        assert (!regexec (&preg, str, MAX_MATCH, matches, 0));

        for (i = 0; matches[i].rm_so >= 0 && i < MAX_MATCH; i++)
        {
                memset(buff, 0, sizeof(buff));
                strncpy (buff, str + matches[i].rm_so, matches[i].rm_eo - matches[i].rm_so);
                printf ("Match %u: %s\n", i, buff);
        }
        regfree (&preg);
        return 0;
}
Output:

Codice: Seleziona tutto

samuele@nuitari-laptop:~$ gcc prova.c && ./a.out
Match 0: ciao
Match 1: ao
Se vuoi un esempio di codice con il ciclo per trovare tutte le occorrenze, dillo =)

Re: [C] Problemino con regex

Inviato: ven 11 gen 2008, 1:35
da Dani
Per quanto riguarda gli errorini bruttini considera che è un codice scritto al volo (vedi ad esempio l'asserzione, senza verificare se regexec restituisce REG_NOMATCH...) ... Anche quando uso strncpy in genere vado a scrivere su spazio allocato con calloc(), quindi inizializzato...
A parte questo sono riuscito ad ottenere cio' che volevo, ma ancora non mi è tutto perfettamente chiaro...Le pagine di manuale delle funzioni fanno un po' pena, il manualone delle libc idem, quindi mi tocca fare prove su prove uff :(
Grazie mille !

Re: [C] Problemino con regex

Inviato: ven 11 gen 2008, 4:32
da nuitari
Dimmi esattamente cosa non hai capito e ti dirò chi s... no spè . Dimmi esattamente cosa non hai capito e ti farò un esempio .

Re: [C] Problemino con regex

Inviato: ven 11 gen 2008, 4:55
da Dani
Sono tre le cose poco chiare, e tutte probabilmente richiederebbero pagine e pagine di spiegazione .
In ogni caso prima di tutto mi sfugge ancora il compito del terzo parametro di regexec(), secondariamente il significato di un flag rispetto ad un altro in entrambe le funzioni, e per finire la ricerca dei token nella stringa. In quest'utlimo caso ci sono fin quando devo trovare qualche numero, o qualche lettera, ma quando devo cercare qualcosa di piu' complesso mi impallo . Ad esempio non saprei cercare nella stringa un "ciao[...]\n\n", dove i [...] rappresentino qualsiasi cosa...
Quindi non è tanto questione di esempi pratici, ma di teoria :(

Re: [C] Problemino con regex

Inviato: ven 11 gen 2008, 7:02
da gallows
Le regex posix sono un po' ostiche... ma andiamo con ordine:

1) Il terzo parametro di regexec() in realtà ha un ruolo molto semplice... in pratica funziona così:

Se passi REG_NOTBOL, significa che non considera l'inizio della stringa come l'inizio di una linea... ovvero:

Codice: Seleziona tutto

char str[] = ""
        "0x000A prima riga\n"
        "0x000B seconda riga\n";
		
char pattern[] = "^0x000.";

regcomp(&preg, pattern, REG_NEWLINE);
regexec(&preg, str, 1, &match, REG_NOTBOL);
Come match avrai 0x000B, perché l'inizio della stringa non viene considerato come l'inizio della prima riga, è come se prima di 0x000A ci fossero altri caratteri.

REG_NOTEOL è speculare. Vale per la fine della stringa. (Quindi con '$' invece che '^').

2) Il manuale mi sembra spieghi bene le cflags, capite le altre sei a cavallo. Cosa non ti è chiaro?

3)

Codice: Seleziona tutto

char str[] = ""
        "0123456789\n"
        "foobarciaoquxquux\n\n"
        "blablablabla\n";
char pattern[] = "ciao.*\n\n";

Re: [C] Problemino con regex

Inviato: sab 12 gen 2008, 5:39
da Dani
gallows ha scritto:

Codice: Seleziona tutto

char str[] = ""
        "0123456789\n"
        "foobarciaoquxquux\n\n"
        "blablablabla\n";
char pattern[] = "ciao.*\n\n";
Perchè se alla terza riga aggiungo un altro newline, quest'ultimo sarà l'offset finale ? Non dovrebbe fermarsi al secondo newline della seconda riga e settare qui rm_eo !?