Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 27 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
27
Dung lượng
807,85 KB
Nội dung
Chương Xử lí dãy lệnh biểu thức 2.1 Val Cho biến gán trị a = 0, b = 1, c = 2, , z = 25 Tính trị biểu thức số học viết cú pháp, chứa tên biến, phép toán +, –, *, / (chia nguyên) cặp ngoặc () Thí dụ, biểu thức, (b+c)*(e–b) + (y–x) có giá trị (1+2)*(4–1)+ (24–23) = 3*3+1 = 10 Thuật toán Do phải ưu tiên thực phép toán nhân (*) chia (/) trước phép toán cộng (+) trừ (), ta qui ước phép toán nhân chia có bậc cao bậc phép toán cộng trừ Gọi s string chứa biểu thức, ta duyệt kí tự s[i] s sử dụng hai ngăn xếp v c để xử lí tình sau: Nếu s[i] biến 'a', 'b',… ta nạp trị tương ứng biến vào ngăn xếp (stack) v Nếu s[i] dấu mở ngoặc '(' ta nạp dấu vào ngăn xếp c Nếu s[i] phép tốn '+', '–', '*', '/' ta so sánh bậc phép toán với bậc phép toán p ngăn xếp c 3.1 Nếu Bac(s[i]) Bac(p) ta lấy phép tốn p khỏi ngăn xếp c thực phép tốn với phần tử ngăn xếp v Bước lặp đến Bac(s[i]) > Bac(p) Sau làm tiếp bước 3.2 3.2 Nạp phép toán s[i] vào ngăn xếp c Nếu s[i] dấu đóng ngoặc ')' ta dỡ dần thực phép toán ngăn xếp c gặp dấu '(' nạp trước Thuật tốn xây dựng giả thiết biểu thức s viết cú pháp Về chất, thuật toán xử lý tính tốn đồng thời trị biểu thức s theo ngun tắc phép tốn sau kí pháp Ba Lan nhà toán học Ba Lan Lucasievics đề xuất Theo kí pháp này, biểu thức (b+c)*(e–b) + (y–x) viết thành bc+eb–*yx–+ thực ngăn xếp v sau Gọi iv trỏ ngăn xếp v, iv khởi trị 0: Nạp trị biến b vào ngăn xếp v: iv := iv + 1; v[iv] := (b); (b) trị biến b Nạp trị biến c vào ngăn xếp v: iv := iv + 1; v[iv] := (c); Thực phép cộng hai phần tử ngăn xếp v, ghi kết vào ngăn dưới, bỏ ngăn trên: v[iv–1] := v[iv–1] + v[iv]; iv := iv –1; Nạp trị e vào ngăn xếp v: iv := iv + 1; v[iv] := (e); Nạp trị b vào ngăn xếp v: iv := iv + 1; v[iv] := (b); Thực phép trừ hai phần tử ngăn xếp v, ghi kết vào ngăn dưới, bỏ ngăn trên: v[iv–1] := v[iv–1] – v[iv]; iv := iv –1; Thực phép nhân hai phần tử ngăn xếp v, ghi kết vào ngăn dưới, bỏ ngăn trên: v[iv–1] := v[iv–1] * v[iv]; iv := iv –1; Nạp trị y vào ngăn xếp v: iv := iv + 1; v[iv] := (y); Nạp trị x vào ngăn xếp v: iv := iv + 1; v[iv] := (x); 10 Thực phép trừ hai phần tử ngăn xếp v, ghi kết vào ngăn dưới, bỏ ngăn trên: v[iv–1] := v[iv–1] – v[iv]; iv := iv –1; 11 Thực phép cộng hai phần tử ngăn xếp v, ghi kết vào ngăn dưới, bỏ ngăn trên: v[iv–1] := v[iv–1] + v[iv]; iv := iv –1; Kết cuối có v[iv] Bạn nhớ khởi trị ngăn xếp c kí tự khơng có biểu thức, thí dụ '#' Phép tốn có bậc dùng làm phần tử đệm để xử lý tình Bạn cần đặt kí hiệu # vào đáy ngăn xếp c để làm lính canh Vì định có nạp phép tốn p vào ngăn xếp c ta cần so sánh bậc p với bậc phép toán ngăn xếp c Như # có bậc Bạn thêm phép kiểm tra để phát lỗi "chia cho 0" thực phép chia Bạn phát triển thêm chương trình để xử lí biểu thức có chứa phép tốn !, ++, – – lời gọi hàm Độ phức tạp cỡ n, n số kí hiệu biểu thức (* Val.pas *) uses crt; const fn = 'val.inp'; gn = 'val.out'; nl = #13#10; bl = #32; mn = 500; var c: array[0 mn] of char; {Ngăn xếp c chứa phép toán} ic: integer; v: array[0 mn] of integer; {Ngăn xếp v chứa trị biến} iv: integer; function LaBien(c: char): Boolean; begin LaBien := (c in ['a' 'z']); end; function LaPhepToan(c: char): Boolean; begin LaPhepToan := (c in ['+','-','*','/']) end; function Val(c: char): integer; { trị biến c } begin Val := Ord(c)-ord('a'); end; function Bac(p: char): integer; { Bậc phép toán p } begin if (p in ['+','-']) then Bac := else if (p in ['*','/']) then Bac := else Bac := 0; end; (* Thực phép tốn ngơi ngăn xếp v *) procedure Tinh(p: char); begin case p of '+': begin v[iv-1] := v[iv-1] + v[iv]; dec(iv) end; '-': begin v[iv-1] := v[iv-1] - v[iv]; dec(iv) end; '*': begin v[iv-1] := v[iv-1] * v[iv]; dec(iv) end; '/': begin v[iv-1] := v[iv-1] div v[iv]; dec(iv) end; end end; procedure XuLiToan(p: char); begin while (Bac(c[ic]) >= Bac(p)) begin Tinh(c[ic]); dec(ic) end; inc(ic); c[ic] := p; { nap phep toan p } end; procedure XuLiNgoac; begin while (c[ic] '(') begin Tinh(c[ic]); dec(ic) end; dec(ic); { Bo ngoac } end; function XuLi(s: string): integer; var i: integer; begin ic := 0; c[ic] := '#'; iv := -1; for i := to length(s) if LaBien(s[i]) then begin inc(iv); v[iv] := Val(s[i]) end else if s[i] = '(' then begin inc(ic); c[ic] := '(' end else if LaPhepToan(s[i]) then XuLiToan(s[i]) else if s[i] = ')' then XuLiNgoac; while (ic > 0) begin Tinh(c[ic]); dec(ic) end; XuLi := v[iv]; end; BEGIN writeln(nl,XuLi('(b+c)*(f-a+b-c+d)/(c*d+b)')); { } readln; END // DevC++: Val #include #include #include #include using namespace std; // Mo ta Dư lieu va bien const int mn = 500; char s[mn]; // bieu thuc char c[mn]; //ngan xep phep toan va dau ( int ic; // trỏ ngăn xếp c int v[mn]; //ngan xep tinh toan int iv; // trỏ ngăn xếp v int kq; // ket qua int n; // len – số ki tự biểu thức // Khai báo hàm int XuLi(); bool LaBien(char c); // kiem tra c la bien ? bool LaPhepToan(char c); // kiem tra c la phep toan +, –, *, / ? void XuLiPhepToan(char pt); void XuLiNgoac(); int Bac(char pt); // Bac cua phep toan +, – (1), *, / (2) int Val(char c); // Tinh tri cua bien c void Tinh(char pt); // thuc hien phep toan pt // Cai dat int main() { strcpy(s,"(b+c)*(e-b) + (y-x)"); cout