|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Aug 2007
Messaggi: 1469
|
[C] Creare parser per analisi breve testo naturale
Ciao a tutti,
vorrei creare un parser in C che mi permetta, dato in ingresso un testo abbastanza breve, di poter estrarre determinati termini in base a delle regole che stabilirò io. Le regole vorrei implementarle nel programma in modo che poi faccia tutto in automatico. Secondo voi da dove dovrei partire?? Ho scelto come linguaggio il C perchè è quello che conosco decentemente....
__________________
Ho concluso transazioni con: gimor78, Taz83, Phopho, HighVoltage, PsychoWood, lexman, sandru, Alkaiser, Baccomatto, selu, Chris70, devil_luca, Novus88, anakin71, redpepper, renatofast, nucatolo, 8310, JeanCaneo e sirjd |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Nov 2003
Città: Il Poli
Messaggi: 992
|
potresti utilizzare la funzione strtok() (la trovi nell'header string.h). La funzione riceve due parametri: il primo è l'indirizzo del vettore contente la stringa, il secondo un delimitatore (o una serie di delimitatori) racchiuso tra apici. Ogni volta che la funzione individua un carattere delimitatore inizia la scansione alla ricerca del delimitatore successivo. Arrivato al delimitatore successivo crea il cosìdetto "token" inserendo un tappo dopo il delimitatore. Questa funzione modifica la stringa che stai manipolando quindi ti consiglio di copiarla in un vettore provvisorio prima di applicarla. Quando richiami la strtok devi sempre distinguere la prima chiamata inserendo il nome della stringa --> strtok(stringa,"delimitatore/i") dalle successive chiamate dove il primo parametro deve essere un valore NULL --> strtok(NULL,"delimitatore/i"). Non ti preoccupare perchè comunque la funzione dalla chiamate successive ricomincerà a tokenizzare da dove aveva interrotto. restituisce il valore NULL se no ha trovato delimitatori o se ha finito di tokenizzare la stringa. Ciao spero di esserti stato utile e non di averti confuso le idee
|
|
|
|
|
|
#3 |
|
Member
Iscritto dal: Jul 2009
Messaggi: 210
|
Guarda, se cerchi indietro nei threads trovi il contest 16 dedicato proprio alla implementazione di parser. Ci sono varie risorse ed esempi, potresti prenderne spunto per capire come funziona il tutto -un parser con la P maiuscola-
Poi dipende da quello che devi analizzare, dalla complessità delle regole e da come queste si applicano al testo. Saluti.
__________________
La disumanità del computer sta nel fatto che, una volta programmato e messo in funzione, si comporta in maniera perfettamente onesta.
Isaac Asimov |
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2793
|
Ma non avevi già aperto un thread sullo stesso argomento? Potresti continuare lì, stava venendo una bella discussione.
|
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Mar 2005
Città: ~
Messaggi: 740
|
meglio ancora la strtok_r (piattaforme *nix) oppure strtok_s (piattaforma win), sono thread safe rispetto alla strtok. ok, magari non sta facendo un'applicazione multithread, però male non fa
__________________
Ciao ciao cagnolino Billy MacMini late 2009, 2.53GHz, 4GB ram, 320GB hard disk, Snow Leopard 10.8.2 - iPod Nano 6th gen. XBOX Live GamerTag: InsaneMau |
|
|
|
|
|
#6 | |
|
Senior Member
Iscritto dal: Aug 2007
Messaggi: 1469
|
Quote:
Ora sono quasi sicuro che mi serve un parser o meglio forse un tokenizzatore. Ho dato un occhio al contest 16, proprio dove si parla di interpreti. Da quel che ricordo io il parser fa un'analisi di un linguaggio strutturato, ma a pensarci bene non è il mio caso. Io ho un linguaggio naturale, scritto così come viene in italiano...quindi non ho nulla di strutturato. Credo proprio che si tratti di un tokenizzatore e l'idea di Jecko e maulattu penso siano quelle corrette. Ovviamente ora cercherò della documentazione su queste funzioni! Chi avesse altre dritte posti pureee!
__________________
Ho concluso transazioni con: gimor78, Taz83, Phopho, HighVoltage, PsychoWood, lexman, sandru, Alkaiser, Baccomatto, selu, Chris70, devil_luca, Novus88, anakin71, redpepper, renatofast, nucatolo, 8310, JeanCaneo e sirjd Ultima modifica di phantom85 : 03-10-2009 alle 13:14. |
|
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Aug 2007
Messaggi: 1469
|
Ho dato un occhio alla funzione strtok, ma mi sorge un dubbio.
Se non ho capito male questa funzione serve per spezzare una stringa in base a dei caratteri di separazione...appunto in base a dei caratteri, e non delle stringhe. Mi spiego: Codice:
char s[]="1abch8dejdkj37390ms"; char c[]="0123456789"; char *p; Codice:
p=strtok(s,c); */p="abch"/* Codice:
p=strtok(NULL,c); */p="dejdkj"/* p=strtok(NULL,c); */p="ms"/* Ma se volessi isolare dei termini tra delle parole, ad esempio: "devo trovare un gatto rosso" mi interessa isolare "gatto" e "rosso", del resto non mi interessa. Cioè voglio isolare l'oggetto centrale della frase e la sua caratteristica La funzione strtok mi potrebbe aiutare??!
__________________
Ho concluso transazioni con: gimor78, Taz83, Phopho, HighVoltage, PsychoWood, lexman, sandru, Alkaiser, Baccomatto, selu, Chris70, devil_luca, Novus88, anakin71, redpepper, renatofast, nucatolo, 8310, JeanCaneo e sirjd |
|
|
|
|
|
#8 |
|
Senior Member
Iscritto dal: Aug 2007
Messaggi: 1469
|
Piccola parentesi...
...se volessi fare un programma in C che dato in input un testo scritto da tastiera, lo divida in token in base allo spazio, come dovrei fare? Codice:
#include <stdio.h>
#include <string.h>
#define MAX 100
int main() {
char input[MAX];
int i=0;
printf ("Inserisci testo e premi invio:\n");
while (input[i]!='\n') {
for (i=0;i<MAX;i++) {
scanf("%c", &input[i]);
}
}
int x;
char *str1;
str1 = strtok(input, " ");
printf("%i: %s\n", x, str1);
while (1) {
str1 = strtok(NULL, " ");
if (str1 == NULL) {
printf("Tokenizing complete\n");
exit(0);
}
printf("%i: %s\n", x, str1);
x++;
}
return 0;
}
Devo aver cannato qualcosa nel codice
__________________
Ho concluso transazioni con: gimor78, Taz83, Phopho, HighVoltage, PsychoWood, lexman, sandru, Alkaiser, Baccomatto, selu, Chris70, devil_luca, Novus88, anakin71, redpepper, renatofast, nucatolo, 8310, JeanCaneo e sirjd |
|
|
|
|
|
#9 |
|
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2793
|
Un problema è sicuramente nel while, il resto non l'ho guardato, comunque questo è il tuo codice:
Codice:
while (input[i]!='\n') {
for (i=0;i<MAX;i++) {
scanf("%c", &input[i]);
}
}
input[100]!='\n' strano che a sto punto non ti dia errore, perché sei andato oltre il limite del tuo array, probabilmente ora stai puntando a qualche altra variabile che hai dichiarato, magari i stessa... Comunque ancora una volta presumibilmente questo valore è diverso da '\n' e quindi rientra nel ciclo. Quello che volevi fare tu molto probabilmente era questo: Codice:
i=0;
scanf("%c", &input[i]);
while (i<MAX && input[i]!='\n') {
i++;
scanf("%c", &input[i]);
}
|
|
|
|
|
|
#10 |
|
Senior Member
Iscritto dal: Aug 2007
Messaggi: 1469
|
Grazie,appena avrò modo modificherò il codice e farò il test. Si la mia idea era proprio quella, solo che sono leggermente arrugginito
Grazie!
__________________
Ho concluso transazioni con: gimor78, Taz83, Phopho, HighVoltage, PsychoWood, lexman, sandru, Alkaiser, Baccomatto, selu, Chris70, devil_luca, Novus88, anakin71, redpepper, renatofast, nucatolo, 8310, JeanCaneo e sirjd |
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Il problema era probabilmente nella lettura tramite scanf. Infatti la lettura non terminava fino a MAX caratteri.
Usa fgets per leggere l'input !!! char str[MAX]; fgets(str, MAX, stdin); |
|
|
|
|
|
#12 | |
|
Senior Member
Iscritto dal: Aug 2007
Messaggi: 1469
|
Quote:
Ora ho realizzato un semplicissimo tokenizzatore che divide in token secondo gli spazi bianchi. Ma se volessi che il mio tokenizzatore (che brutto termine ) dividesse i token oltre che per spazi bianchi, anche per segni di punteggiatura?!Come dovrei modificare strtok? edit ho dichiarato un array con i caratteri che devono dividere le varie parole e ho passato il puntatore nell'argomento della strtok. Unico problema è che non posso inserire come separatore le virgolette " (all'interno dell'array tk) Codice:
char tk[]=".,;:-_'*+ ";
__________________
Ho concluso transazioni con: gimor78, Taz83, Phopho, HighVoltage, PsychoWood, lexman, sandru, Alkaiser, Baccomatto, selu, Chris70, devil_luca, Novus88, anakin71, redpepper, renatofast, nucatolo, 8310, JeanCaneo e sirjd Ultima modifica di phantom85 : 06-10-2009 alle 12:32. |
|
|
|
|
|
|
#13 |
|
Senior Member
Iscritto dal: Aug 2007
Messaggi: 1469
|
Al di là del problema del separatore, mi chiedevo come posso fare un confronto all'interno del ciclo, cioè confrontare un token con una determinata parola.
ES: se un token è uguale alla parola "con" vorrei che l'output sia "ingrediente: con cioccolato" (dove "cioccolato" è la parola/token successiva a "con"). Esempio: Input: voglio fare una torta con cioccolato Output 1: voglio 2: fare 3: una 4: torta 5: Ingrediente: con cioccolato E' possibile farlo??
__________________
Ho concluso transazioni con: gimor78, Taz83, Phopho, HighVoltage, PsychoWood, lexman, sandru, Alkaiser, Baccomatto, selu, Chris70, devil_luca, Novus88, anakin71, redpepper, renatofast, nucatolo, 8310, JeanCaneo e sirjd |
|
|
|
|
|
#15 |
|
Senior Member
Iscritto dal: Aug 2007
Messaggi: 1469
|
grazie, ora mi sto dedicando alla strcmp.
Secondo voi è possibile creare una sorta di struttura che contenga tutte le parole che confrontate con il token porti poi alla stampa di "ingrediente"? Mi spiego: prima ho detto che se il tokenizer trova "con" allora deve stampare "ingrediente: con..." Ma se volessi estendere questa cosa ad altre parole, oltre a "con"? Potrei creare un if con una serie di OR Codice:
if ( (strcmp(str,"con")==0) || (strcmp (str,"al") ==0) )
printf ("Ingrediente: ");
__________________
Ho concluso transazioni con: gimor78, Taz83, Phopho, HighVoltage, PsychoWood, lexman, sandru, Alkaiser, Baccomatto, selu, Chris70, devil_luca, Novus88, anakin71, redpepper, renatofast, nucatolo, 8310, JeanCaneo e sirjd Ultima modifica di phantom85 : 06-10-2009 alle 15:26. |
|
|
|
|
|
#16 |
|
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2793
|
Puoi creare un array di stringhe in cui mettere "con" "al" e tutto quello che vuoi e poi usare un ciclo per fare i vari confronti e se almeno uno dei confronti va a buon fine stampare "ingrediente: ..."
Stai cercando di individuare delle parole chiave per definire una grammatica giusto? |
|
|
|
|
|
#17 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
Codice:
for(i = 0; i < N; ++i)
{
if(strcmp(str, strings[i]) == 0)
{
printf ("Ingrediente: ");
break;
}
}
|
|
|
|
|
|
|
#18 | |
|
Member
Iscritto dal: Jan 2007
Città: Asti
Messaggi: 256
|
Quote:
A questo punto al posto di usare la strcmp per verificare se il tuo token è uguale alla parola "con" usi , ad esempio, una funzione is_present( parola, matr[][] ) booleana che restituisce TRUE se il token è una parola speciale contenuta nel tuo vettore bidimensionale e FALSE se non lo è. A questo punto se ti è stato restituito il valore TRUE stampi "Ingrediente bla bla bla" mentre stampi semplicemnete la parola se hai ricevuto FALSE
__________________
![]() ![]() Ho concluso affari con: Samurri, kosimiro, mAiDeN75, Raziel1984, deidara, billy99. gertuzz |
|
|
|
|
|
|
#19 |
|
Senior Member
Iscritto dal: Aug 2007
Messaggi: 1469
|
Ho seguito la dritta di cionci realizzando l'or con un ciclo for e devo dire che tutta funzia bene
Ora se volessi che la parola "ingrediente" venisse stampata DOPO le parola "con" o "al" ? Codice:
Adesso il programma esegue questo, se rileva "al" o "con" ... token Ingrediente: con cioccolato token ... Codice:
... token Ingrediente: al curry token ... Codice:
... token con Ingrediente: cioccolato token ... Come potrei fare? vi ringrazio ancora tutti PS: @wingman: si più o meno è quello che vorrei fare, diciamo che dato un testo vorrei fare una prima "scrematura" o meglio "raffinarlo" e strutturalo EDIT: sono riuscito a fare quello che volevo, nell'if che verificava la presenza di una parola ho semplicemente richiamato un'altra volta la printf del token e nuovamente la funzione strtok Sicuramente posterò ancora per porre nuove modifiche o nuove feature del programmino!
__________________
Ho concluso transazioni con: gimor78, Taz83, Phopho, HighVoltage, PsychoWood, lexman, sandru, Alkaiser, Baccomatto, selu, Chris70, devil_luca, Novus88, anakin71, redpepper, renatofast, nucatolo, 8310, JeanCaneo e sirjd Ultima modifica di phantom85 : 07-10-2009 alle 11:18. |
|
|
|
|
|
#20 |
|
Senior Member
Iscritto dal: Aug 2007
Messaggi: 1469
|
Ho un problema con il programma, un bug.
Ho notato che se verifico la presenza delle parole con o al che indicano la presenza di un ingrediente (token successivo) tutto funziona, ma se impongo un if in cui verifico che nel caso un token sia uguale ad una determinata parola, il programma deve stampare una parola (lasciamo sempre ingrediente), se la parola compare alla fine del testo non stampa nulla (ovvero se la parola è l'ultimo token), altrimenti se la parola non è alla fine tutto gira! Cioè ... char *strings[]= {"con","al"}; char *str; str = strtok(input, tk); ... while (1) { str = strtok(NULL, tk); if (str == NULL) { printf("Analisi completata\n"); exit(0); } for (i=0;i<2;i++) { if ( (strcmp (str,strings[i]) == 0) ) { printf ("Ingrediente "); } } if ( strcmp (str,"farina") == 0) printf ("Ingrediente: "); printf("%s\n", str); }
__________________
Ho concluso transazioni con: gimor78, Taz83, Phopho, HighVoltage, PsychoWood, lexman, sandru, Alkaiser, Baccomatto, selu, Chris70, devil_luca, Novus88, anakin71, redpepper, renatofast, nucatolo, 8310, JeanCaneo e sirjd |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 12:12.












) dividesse i token oltre che per spazi bianchi, anche per segni di punteggiatura?!









