2013-05-17 16 views
5

Ho bisogno di dividere stringhe contenenti espressioni matematiche di base, come ad esempio:
"(a+b)*c"
o
" (a - c)/d"
I delimitatori sono + - * /() e lo spazio e ho bisogno di loro come un token indipendente. In sostanza il risultato dovrebbe essere simile a questo:Come posso usare string # split per dividere una stringa con i delimitatori + - * /() e lo spazio e mantenerli come token extra?

"("
"a"
"+"
"b"
")"
"*"
"c"

E per il secondo esempio:

" "
"("
"a"
" "
"-"
...

Ho letto un sacco di domande su problemi simili con meno delimitatori complesse e la risposta comune è stato quello di utilizzare lo spazio a zero lookahead positivo e - dietro a.
Ti piace questa: (?<=X | ?=X)
E X rappresenta il delimitatori, ma mettendoli in una classe come questa:
[\\Q+-*()\\E/\\s]
non funziona nel modo desiderato.
Quindi, come devo formattare i delimitatori per fare in modo che la divisione funzioni come ne ho bisogno?

--- Aggiornamento ---
I caratteri della classe Word e le combinazioni più lunghe non devono essere divisi.
Ad esempio "ab" "c1" o "12".
In breve, ho bisogno dello stesso risultato di StringTokenizer, dare i parametri "- + * /()" e true.

+2

http://stackoverflow.com/questions/2226863/whats-a-good-library-for-parsing-mathematical-expressions-in-java – Zutty

+0

Come si deve dividere 'a + ab-c1 + 12'? È 'ab' un token o un insieme di' a * b' e il risultato per questa parte dovrebbe essere 'a'' * '' b'? I numeri sono possibili nella tua stringa? – Pshemo

+0

"ab" dovrebbe rimanere "ab" come pure "c1" e "12" –

risposta

1

provare a dividere i dati utilizzando

yourString.split("(?<=[\\Q+-*()\\E/\\s])|(?=[\\Q+-*()\\E/\\s])(?<!^)")); 

Suppongo che problema hai avuto non era in \\Q+-*()\\E parte ma in (?<=X | ?=X) < - dovrebbe essere (?<=X)|(?=X) in quanto dovrebbe produrre look-dietro e look-ahead.


demo "_a+(ab-c1__)+12_" (BTW _ sarà sostituito con spazio nel codice. Mostra SO due spazi come uno, quindi dovuto usare __ presentarle qualche modo)

String[] tokens = " a+(ab-c1 )+12 " 
     .split("(?<=[\\Q+-*()\\E/\\s])|(?=[\\Q+-*()\\E/\\s])(?<!^)"); 
for (String token : tokens) 
    System.out.println("\"" + token + "\""); 

risultato

" " 
"a" 
"+" 
"(" 
"ab" 
"-" 
"c1" 
" " 
" " 
")" 
"+" 
"12" 
" " 
+0

grazie! ora si divide correttamente –

+0

In aggiunta alla risposta "(? <= [\\ Q + - *() \\ E/\\ s]) | (? = (?! ^) [\\ Q + - *() \ \ E/\\ s]) "è necessario perché un delimitatore iniziale come le parentesi causerebbe una stringa vuota. –

+0

@ThiemoKrause È vero, ho aggiornato la mia risposta in precedenza con '(? = [\\ Q + - *() \\ E/\\ s]) (? Pshemo

0

Prova a modificare:

[-+*()\\s] 

trattini devono venire prima o l'ultima in una classe di caratteri in modo da non rappresentare un intervallo. Il resto dei personaggi non ha bisogno di scappare (presumibilmente quello che stavi cercando di fare con \\Q e \\E) perché la maggior parte dei personaggi sono presi letteralmente in ogni caso in una classe di personaggi.

Inoltre, non ero a conoscenza della sintassi, (?<=X|?=X). Se funziona, allora fantastico.Ma se non lo fa, provate questa espansione equivalente, la cui sintassi So fa lavoro:

(?:(?<=X)|(?=X)) 
+1

'\ Q' e' \ E' funziona all'interno della classe di caratteri. – nhahtdh

+0

Ho cambiato l'espressione in (?: (? <= [- + * /() \\ s]) | (? = [- + * /() \\ s])) ma non una singola divisione se non ci sono spazi nella stringa di input, ad esempio: (b + 2) * 6 –

0

È possibile utilizzare la seguente espressione regolare:

\s*(?<=[()+*/a-z-])\s* 

?<= fa affermazioni zero witdh, che è, corrispondono, ma non includono l'espressione abbinata nel gruppo. Lo \s* si prenderà cura degli spazi finali.

Codice esempio:

String a = " (a - c)/d *  x "; 
String regex = "\\s*(?<=[()+*/a-z-])\\s*"; 
String[] split = a.split(regex); 
System.out.println(Arrays.toString(split)); 

uscita:

[ (, a, -, c,), /, d, *, x] 
+0

(Si prega di correggere la regex anche in alto). – nhahtdh

+0

@nhahtdh Per chiarezza (e dubbio) di solito scappo a tutto, ma in questo caso il tuo funziona altrettanto bene. Con la tua scusa, ho aggiornato la risposta. Grazie! – acdcjunior

+0

Non so come scappare tutto rende più chiaro, ma capisco perché lo fai quando sei in dubbio.Per me, è più difficile tenere traccia dei personaggi nella classe personaggio quando la maggior parte di loro è fuggita. – nhahtdh

1

Un conto è se si sta facendo questo come lavoro degli studenti, ma in pratica questo è più di un lavoro per un analizzatore lessicale e parser. In C, si utilizza lex e yacc o GNU flex e bison. In Java, dovresti usare ANTLR o JavaCC.

Ma iniziare scrivendo una grammatica BNF per l'input previsto (in genere chiamato lingua).

Problemi correlati