Valutazione di espressioni regolari

di il
7 risposte

Valutazione di espressioni regolari

Salve, mi è stato assegnato un laboratorio, di cui allego di seguito il testo:

Una espressione regolare (o regexp) è una sequenza di simboli (quindi una stringa) che identifica un
insieme di stringhe. Si scriva una funzione in C in grado di individuare (cercare) eventuali occorrenze di
una data regexp all'interno di una stringa di input.
La funzione sia caratterizzata dal seguente prototipo:

char *cercaRegexp(char *src, char *regexp);
dove :
? il parametro src rappresenta la stringa sorgente in cui cercare.
? il parametro regexp rappresenta l'espressione regolare da cercare.
? il valore di ritorno della funzione è un puntatore alla prima occorrenza di regexp in src (NULL
se non trovata).

Ai fini dell'esercizio si consideri di valutare solamente stringhe composte da caratteri alfabetici. Si
considerino inoltre solamente espressioni regolari composte da caratteri alfabetici e dai seguenti
metacaratteri:
? . trova un singolo carattere (cioè qualunque carattere può corrispondere a un punto)
? [] trova un singolo carattere contenuto nelle parentesi (cioè uno qualsiasi dei caratteri tra parentesi
va bene)
? [^ ] trova ogni singolo carattere non contenuto nelle parentesi (cioè tutti i caratteri tra parentesi
non vanno bene)
? \a trova un carattere minuscolo
? \A trova un carattere maiuscolo

Esempi di espressioni regolari:
.oto corrisponde a ogni stringa di quattro caratteri terminante con “oto”, es. "voto", "noto",
"foto", ...
[mn]oto rappresenta solamente "moto" e "noto"
[^f]oto rappresenta tutte le stringhe terminanti in “oto” ad eccezione di "foto"
\aoto rappresenta ogni stringa di quattro caratteri (come "voto", "noto", "foto", ... ) iniziante per
lettere minuscola e terminante in “oto”
\Aoto rappresenta ogni stringa di quattro caratteri (come "Voto", "Noto", "Foto", ...) iniziante per
lettere maiuscola e terminante in “oto”.

Ho cercato di risolverlo con dei costrutti if-else e poi la strstr, ma la funzione mi ritorna sempre NULL. Sto letteralmente impazzendo!
Metto come esempio l'if dell'occorenza '.'

char *cercaRegexp(char *src, char *regexp) {
    char *ris;
        while (*regexp != '\0') {
            if (*regexp == '.') {
                while(*src!='\0'){
                    if(*(regexp+1)==*src){
                        printf("%c", *(src-1));
                        return strstr(src,regexp);
                    }
                    src++;
                }

            } else if (*regexp == '[') {

            } else if (*regexp == '[' && *(regexp + 1) == '^') {

            } else if (*regexp == '\\') {

            }

        }
        regexp++;
        return ris;
    }

7 Risposte

  • Re: Valutazione di espressioni regolari

    Hai usato "strstr", è consentito? Se sì il primo if viene molto più semplice di come l'hai fatto tu.

    https://en.cppreference.com/w/c/string/byte/strst
  • Re: Valutazione di espressioni regolari

    Alexv ha scritto:


    Hai usato "strstr", è consentito? Se sì il primo if viene molto più semplice di come l'hai fatto tu.

    https://en.cppreference.com/w/c/string/byte/strst
    Non ho idea se sia permesso o meno, il testo dell'esercizio è quello che leggi. Io ho abbozzato una soluzione ipotetica. Ma nella realtà dei fatti vorrei vedere il programma risolto da qualcun altro per capire meglio.
  • Re: Valutazione di espressioni regolari

    Non puoi chiedere il compito svolto, è contro il regolamento.
    Ti chiedevo se potevi usare strstr perché fa, in parte, quello che ti serve, cioè cercare una sottostringa.
    Ti scrivo il primo if e un main per provare la funzione:
    
    if (*regexp == '.') {
    	ris = strstr(src, regexp+1); //+1 perché il "." non va confrontato
    	if(ris == src || ris==NULL)
    		return ris;
    	else 
    		return ris-1;
    }
    
    (ris va inizializzato a NULL).

    Il main
    
    #include <stdio.h>
    #include <string.h>
    int main()
    {
    	char src[]="Myamoto";
    	char regexp[]=".oto";
    	char* ris = NULL;
    	
    	ris=cercaRegexp(src, regexp);
    	
    	if (ris==NULL)
    		printf("<nessuna espressione trovata>\n");
    	else
    		printf("%s",ris);
    	
    	return 0;
    }
    
  • Re: Valutazione di espressioni regolari

    Alexv ha scritto:


    Non puoi chiedere il compito svolto, è contro il regolamento.
    Ti chiedevo se potevi usare strstr perché fa, in parte, quello che ti serve, cioè cercare una sottostringa.
    Ti scrivo il primo if e un main per provare la funzione:
    
    if (*regexp == '.') {
    	ris = strstr(src, regexp+1); //+1 perché il "." non va confrontato
    	if(ris == src || ris==NULL)
    		return ris;
    	else 
    		return ris-1;
    }
    
    (ris va inizializzato a NULL).

    Il main
    
    #include <stdio.h>
    #include <string.h>
    int main()
    {
    	char src[]="Myamoto";
    	char regexp[]=".oto";
    	char* ris = NULL;
    	
    	ris=cercaRegexp(src, regexp);
    	
    	if (ris==NULL)
    		printf("<nessuna espressione trovata>\n");
    	else
    		printf("%s",ris);
    	
    	return 0;
    }
    
    Sisi, so che non posso chiedere l'esercizio risolto. Per questo ho messo la funzione che ho cercato di implementare io, per capire se il ragionamento era corretto. Per quanto riguarda la funzione strstr non è vietato nulla. Si può usare qualunque libreria e qualunque funzione messa a disposizione da tale libreria tranne la regex.h.
    La funzione come me la presenti tu avevo già provato a farla ma non mi ritornava i risultati corretti con input da tastiera. Il codice che ho postato è il millesimo tentativo
  • Re: Valutazione di espressioni regolari

    Non serve NESSUNA funzione della libreria standard del C//C++, ma SOLO

    OLIO DI GOMITO.

    Tra l'altro, quella proposta non e' nemmeno una RE degna di questo nome, perche' manca come minimo '*' (match di QUALUNQUE sequenza di caratteri)

    La funzione e' SOLO comparazione REGOLA CON CARATTERE.

    MOOOOOOLTO banale.

    Devi ragionare SOLO in termini di REGOLA da una parte e SINGOLO CARATTERE dall'altra, e di ARRAY di caratteri, dove da una parte hai un UNICO carattere da analizzare alla volta, dall'altro UNO o PIU' caratteri (le regole), E STOP.

    UNICO CICLO FOR, piu' qualche implementazione dedicata per certe tipologie di regole


    Usare PIU' FUNZIONI NON E' VIETATO.
    Si puo' fare anche con una singola funzione, ma usandone di piu' si mantiene il codice piu' ordinato.
  • Re: Valutazione di espressioni regolari

    Ledriana ha scritto:


    Sisi, so che non posso chiedere l'esercizio risolto. Per questo ho messo la funzione che ho cercato di implementare io, per capire se il ragionamento era corretto. Per quanto riguarda la funzione strstr non è vietato nulla. Si può usare qualunque libreria e qualunque funzione messa a disposizione da tale libreria tranne la regex.h.
    La funzione come me la presenti tu avevo già provato a farla ma non mi ritornava i risultati corretti con input da tastiera. Il codice che ho postato è il millesimo tentativo
    Allora, torno un attimo sull'esempio che ho postato prima. La traccia non specifica se l'espressione trovata deve essere valida nel caso coincida con l'inizio di "src". Qualora volessi che non lo sia, ti basta mettere NULL anche nel primo return.

    Sui punti successivi, è solo un po' meno banale estrapolare i caratteri nelle parentesi. Quanto a cercare l'espressione, puoi usare lo stesso approccio del primo caso, solo che devi controllare se il primo carattere delle occorrenze trovate (ris-1) è valido facendo gli appositi confronti con quelli nella regex di input.

    Per rendere in codice più ordinato, puoi usare una struttura switch-case almeno per quanto riguarda il primo carattere della regex, e poi usare apposite sotto funzioni come ha detto @migliorabile.
    
    switch(regex[0]){
    case '.':
    	funzione1();
    	break;
    case '[':
    	funzione2();
    	break;
    //ecc...
    }
    
    Adesso però abbiamo detto troppo.
    Per escludere bug dovuti alla lettura da tastiera (es. eventuali buffer non svuotati), ti conviene testare la funzione con delle stringhe prefissate nel main come ho fatto io (le puoi anche cambiare, ovviamente), e solo dopo "complicare" con la lettura da tastiera. Fai una cosa per volta e tieni sempre in mente che la probabilità di errori cresce con la lunghezza del codice.
  • Re: Valutazione di espressioni regolari

    Alexv ha scritto:


    Ledriana ha scritto:


    Sisi, so che non posso chiedere l'esercizio risolto. Per questo ho messo la funzione che ho cercato di implementare io, per capire se il ragionamento era corretto. Per quanto riguarda la funzione strstr non è vietato nulla. Si può usare qualunque libreria e qualunque funzione messa a disposizione da tale libreria tranne la regex.h.
    La funzione come me la presenti tu avevo già provato a farla ma non mi ritornava i risultati corretti con input da tastiera. Il codice che ho postato è il millesimo tentativo
    Allora, torno un attimo sull'esempio che ho postato prima. La traccia non specifica se l'espressione trovata deve essere valida nel caso coincida con l'inizio di "src". Qualora volessi che non lo sia, ti basta mettere NULL anche nel primo return.

    Sui punti successivi, è solo un po' meno banale estrapolare i caratteri nelle parentesi. Quanto a cercare l'espressione, puoi usare lo stesso approccio del primo caso, solo che devi controllare se il primo carattere delle occorrenze trovate (ris-1) è valido facendo gli appositi confronti con quelli nella regex di input.

    Per rendere in codice più ordinato, puoi usare una struttura switch-case almeno per quanto riguarda il primo carattere della regex, e poi usare apposite sotto funzioni come ha detto @migliorabile.
    
    switch(regex[0]){
    case '.':
    	funzione1();
    	break;
    case '[':
    	funzione2();
    	break;
    //ecc...
    }
    
    Adesso però abbiamo detto troppo.
    Per escludere bug dovuti alla lettura da tastiera (es. eventuali buffer non svuotati), ti conviene testare la funzione con delle stringhe prefissate nel main come ho fatto io (le puoi anche cambiare, ovviamente), e solo dopo "complicare" con la lettura da tastiera. Fai una cosa per volta e tieni sempre in mente che la probabilità di errori cresce con la lunghezza del codice.
    La switch l'avevo già implementata ma non ancora inserita perchè non riuscivo a trovare la formula giusta per l'implementazione delle varie funzioni, adesso è molto più chiaro! Sei stato gentilissimo! Grazie
Devi accedere o registrarti per scrivere nel forum
7 risposte