Repository 32bit  Forum
Repository 64bit  Wiki

[C] Problemino con regex

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.

[C] Problemino con regex

Messaggioda Dani » lun gen 07, 2008 19:41

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
Dani
Linux 3.x
Linux 3.x
 
Messaggi: 1447
Iscritto il: mer apr 26, 2006 0:52
Desktop: gnome
Distribuzione: arch

Re: [C] Problemino con regex

Messaggioda Blizzard » lun gen 07, 2008 20:41

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
Avatar utente
Blizzard
Master
Master
 
Messaggi: 1509
Iscritto il: mar gen 02, 2007 22:53
Nome Cognome: Giovanni Santostefano
Slackware: 12.2
Kernel: 2.6.27.7-smp
Desktop: Fluxbox

Re: [C] Problemino con regex

Messaggioda Dani » mer gen 09, 2008 15:44

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.
Dani
Linux 3.x
Linux 3.x
 
Messaggi: 1447
Iscritto il: mer apr 26, 2006 0:52
Desktop: gnome
Distribuzione: arch

Re: [C] Problemino con regex

Messaggioda Blizzard » mer gen 09, 2008 16:46

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
Avatar utente
Blizzard
Master
Master
 
Messaggi: 1509
Iscritto il: mar gen 02, 2007 22:53
Nome Cognome: Giovanni Santostefano
Slackware: 12.2
Kernel: 2.6.27.7-smp
Desktop: Fluxbox

Re: [C] Problemino con regex

Messaggioda Dani » mer gen 09, 2008 17:11

Togliendo i vari '\n' non cambia nulla #-o
Dani
Linux 3.x
Linux 3.x
 
Messaggi: 1447
Iscritto il: mer apr 26, 2006 0:52
Desktop: gnome
Distribuzione: arch

Re: [C] Problemino con regex

Messaggioda puzuma » mer gen 09, 2008 17:40

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) ;
}
The quiet ones are the ones who change the world. The loud ones only take the credit.
Avatar utente
puzuma
Linux 2.4
Linux 2.4
 
Messaggi: 481
Iscritto il: mar lug 04, 2006 16:14
Località: Udine
Nome Cognome: Stefano Salvador
Slackware: current
Kernel: 2.6.32.2
Desktop: KDE 4.4.0

Re: [C] Problemino con regex

Messaggioda nuitari » mer gen 09, 2008 18:09

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 =)
Avatar utente
nuitari
Linux 2.6
Linux 2.6
 
Messaggi: 777
Iscritto il: dom ott 14, 2007 11:51
Località: San Colombano al Lambro
Slackware: 12.0

Re: [C] Problemino con regex

Messaggioda Dani » ven gen 11, 2008 1:35

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 !
Dani
Linux 3.x
Linux 3.x
 
Messaggi: 1447
Iscritto il: mer apr 26, 2006 0:52
Desktop: gnome
Distribuzione: arch

Re: [C] Problemino con regex

Messaggioda nuitari » ven gen 11, 2008 4:32

Dimmi esattamente cosa non hai capito e ti dirò chi s... no spè . Dimmi esattamente cosa non hai capito e ti farò un esempio .
Avatar utente
nuitari
Linux 2.6
Linux 2.6
 
Messaggi: 777
Iscritto il: dom ott 14, 2007 11:51
Località: San Colombano al Lambro
Slackware: 12.0

Re: [C] Problemino con regex

Messaggioda Dani » ven gen 11, 2008 4:55

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 :(
Dani
Linux 3.x
Linux 3.x
 
Messaggi: 1447
Iscritto il: mer apr 26, 2006 0:52
Desktop: gnome
Distribuzione: arch

Re: [C] Problemino con regex

Messaggioda gallows » ven gen 11, 2008 7:02

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";
Avatar utente
gallows
Staff
Staff
 
Messaggi: 3466
Iscritto il: dom set 19, 2004 23:00
Località: Palermo
Kernel: FreeBSD 8.0-RELEASE-p3
Desktop: ratpoison

Re: [C] Problemino con regex

Messaggioda Dani » sab gen 12, 2008 5:39

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 !?
Dani
Linux 3.x
Linux 3.x
 
Messaggi: 1447
Iscritto il: mer apr 26, 2006 0:52
Desktop: gnome
Distribuzione: arch


Torna a Programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 3 ospiti