Một trong những cạm bẫy kinh điển của macro hàm (function-like macro) trong C là: quá trình mở rộng macro chỉ là thay thế văn bản thuần túy — tham số hình thức được thay trực tiếp bằng token của đối số thực sự, không tự động bọc thêm dấu ngoặc quanh đối số. Điều này có thể làm sai lệch hoàn toàn giá trị biểu thức nếu đối số truyền vào không tự có ngoặc bảo vệ.
Ví dụ macro #define SQUARE(x) x*x. Khi gọi SQUARE(1+2), việc thay thế thuần túy cho ra biểu thức 1+2*1+2, và theo thứ tự ưu tiên toán tử chuẩn (* được tính trước +, +/- tính trái sang phải), giá trị là 1+(2×1)+2=5 — không phải 9=(1+2)2 như người lập trình có thể kỳ vọng.
Cho định nghĩa của một macro hàm NAME(param_1, ..., param_k) EXPR, trong đó EXPR là một biểu thức chỉ gồm các toán hạng là tên tham số hoặc số nguyên, nối với nhau bởi các toán tử +, -, * (không có dấu ngoặc trong EXPR). Cho một lời gọi macro với k đối số, mỗi đối số là một biểu thức số nguyên (gồm số nguyên không âm, toán tử +, -, *, và có thể có dấu ngoặc (, )).
Hãy: (1) thực hiện thay thế văn bản thuần túy — thay mỗi lần xuất hiện của mỗi tham số trong EXPR bằng đúng dãy token của đối số tương ứng (không thêm ngoặc); (2) tính giá trị biểu thức kết quả theo quy tắc ưu tiên toán tử chuẩn (* trước, rồi +/- tính trái sang phải, dấu ngoặc được ưu tiên tính trước); in ra kết quả.
Dòng 1: tên macro (không dùng đến, chỉ để tham khảo). Dòng 2: số nguyên k (1≤k≤5) — số tham số. Dòng 3: k tên tham số cách nhau bởi khoảng trắng. Dòng 4: các token của EXPR, cách nhau bởi đúng 1 khoảng trắng (mỗi token là tên tham số, số nguyên, hoặc một trong + - *; không có dấu ngoặc). Dòng 5: số nguyên c (c=k) — số đối số của lời gọi. c dòng tiếp theo, mỗi dòng là các token của một đối số (số nguyên không âm, +, -, *, (, )), cách nhau bởi đúng 1 khoảng trắng, theo đúng thứ tự tham số được khai báo ở dòng 3. Dữ liệu đảm bảo mọi biểu thức token hợp lệ về cú pháp và giá trị trung gian không vượt quá 109 về trị tuyệt đối.
In ra một số nguyên duy nhất — giá trị biểu thức sau khi thay thế văn bản thuần túy (không thêm ngoặc) và tính theo thứ tự ưu tiên toán tử chuẩn.
Ví dụ:
Đầu vào:
MEAN
2
a b
a + b
2
1 + 2
3 + 4
Đầu ra:
10
Đầu vào:
SQUARE
1
x
x * x
1
1 + 2
Đầu ra:
5
Đang tải editor...