2013-05-17 15 views
5

tôi cần phải chia chuỗi có chứa biểu thức toán học cơ bản, chẳng hạn như:
"(a+b)*c"
hoặc
" (a - c)/d"
Các delimiters là + - * /() và không gian và tôi cần họ như một dấu hiệu độc lập. Về cơ bản kết quả sẽ giống như thế này:Làm cách nào tôi có thể sử dụng chuỗi # split để tách một chuỗi với dấu phân cách + - * /() và dấu cách và giữ chúng dưới dạng mã thông báo bổ sung?

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

Và đối với ví dụ thứ hai:

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

Tôi đọc rất nhiều câu hỏi về vấn đề tương tự với delimiters ít phức tạp và câu trả lời phổ biến là sử dụng không gian lookahead tích cực và - phía sau.
Như thế này: (?<=X | ?=X)
Và X đại diện cho delimiters, nhưng đặt chúng trong một lớp học như thế này:
[\\Q+-*()\\E/\\s]
không hoạt động theo cách mong muốn.
Vì vậy, làm thế nào để tôi phải định dạng các dấu phân cách để làm cho công việc chia làm thế nào tôi cần nó?

--- Cập nhật ---
Ký tự lớp từ và kết hợp dài hơn không được chia nhỏ.
Chẳng hạn như "ab" "c1" hoặc "12".
Hoặc trong ngắn hạn, tôi cần kết quả tương tự như StringTokenizer sẽ có, cung cấp các tham số "- + * /()" và đúng.

+2

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

+0

Làm thế nào để 'a + ab-c1 + 12' được tách ra? Có 'ab' một mã thông báo hoặc tập hợp' a * b' và kết quả cho phần này phải là 'a'' * '' b'? Các số có thể có trong chuỗi của bạn không? – Pshemo

+0

"ab" nên ở lại "ab" cũng như "c1" và "12" –

Trả lời

1

Hãy thử tách dữ liệu của bạn sử dụng

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

tôi cho rằng vấn đề bạn có là không \\Q+-*()\\E phần nhưng trong (?<=X | ?=X) < - nó phải được (?<=X)|(?=X) vì nó nên sản xuất tìm-sau và tìm kiếm-phía trước.


demo cho "_a+(ab-c1__)+12_" (BTW _ sẽ được thay thế bằng không gian trong mã. SO cho thấy hai không gian là một, vì vậy phải sử dụng __ để trình bày cho họ bằng cách nào đó)

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

kết quả

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

cảm ơn! bây giờ nó chia tách một cách chính xác –

+0

Ngoài câu trả lời của bạn "(? <= [\\ Q + - *() \\ E/\\ s]) | (? = (?! ^) [\\ Q + - *() \ \ E/\\ s]) "là cần thiết vì dấu tách hàng đầu như dấu ngoặc đơn sẽ gây ra chuỗi rỗng. –

+0

@ThiemoKrause Đúng, tôi đã cập nhật câu trả lời của mình trước đó với '(? = [\\ Q + - *() \\ E/\\ s]) (? Pshemo

0

Hãy thử điều này thay vì:

[-+*()\\s] 

Dấu gạch ngang phải đến đầu tiên hoặc cuối cùng trong một lớp nhân vật để không đại diện cho một loạt . Phần còn lại của các nhân vật không cần phải thoát (có lẽ là những gì bạn đang cố gắng làm với \\Q\\E) bởi vì hầu hết các ký tự được chụp theo nghĩa đen trong lớp nhân vật.

Ngoài ra, tôi không biết cú pháp, (?<=X|?=X). Nếu nó hoạt động, thì tuyệt vời.Nhưng nếu nó không, hãy thử mở rộng tương đương này, có cú pháp tôi biết không công việc:

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

'\ Q' và' \ E' hoạt động bên trong lớp ký tự. – nhahtdh

+0

Tôi đã thay đổi biểu thức thành (?: (? <= [- + * /() \\ s]) | (? = [- + * /() \\ s])) nhưng không chia tách một lần nếu không có khoảng trắng trong chuỗi đầu vào ví dụ: (b + 2) * 6 –

0

Bạn có thể sử dụng regex sau:

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

?<= làm khẳng định zero-witdh, mà là, chúng khớp nhau, nhưng sẽ không bao gồm cụm từ phù hợp trong nhóm. Các \s* sẽ chăm sóc của không gian dấu.

Mã dụ:

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

Output:

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

(Vui lòng sửa regex ở trên cùng). – nhahtdh

+0

@nhahtdh Đối với sự rõ ràng (và nghi ngờ vì lợi ích), tôi thường thoát khỏi mọi thứ, nhưng trong trường hợp này công việc của bạn là tốt. Với lý do của bạn, tôi đã cập nhật câu trả lời. Cảm ơn! – acdcjunior

+0

Tôi không biết làm thế nào thoát khỏi mọi thứ làm cho nó rõ ràng hơn, nhưng tôi hiểu tại sao bạn làm điều đó khi bạn đang nghi ngờ.Đối với tôi, việc theo dõi các nhân vật trong lớp nhân vật càng khó khăn hơn khi hầu hết trong số họ bị tẩu thoát. – nhahtdh

1

Đó là một điều nếu bạn đang làm điều này như làm của học sinh, nhưng trên thực tế đây là chi tiết của một công việc cho một phân tích từ vựng và trình phân tích cú pháp. Trong C, bạn sẽ sử dụng lexyacc hoặc GNU flexbison. Trong Java, bạn sẽ sử dụng ANTLR hoặc JavaCC.

Nhưng bắt đầu bằng cách viết ngữ pháp BNF cho đầu vào dự kiến ​​của bạn (thường được gọi là ngôn ngữ nhập ).

Các vấn đề liên quan