Tiền xử lý C có hai toán tử đặc biệt trong thân macro có tham số: toán tử chuỗi hóa #p (biến tham số p thành một chuỗi ký tự đặt trong dấu ngoặc kép, giữ nguyên văn bản của đối số truyền vào) và toán tử dán token ## (nối liền hai token liền kề, không có khoảng trắng ở giữa, có thể dán liên tiếp nhiều token).
Cho n định nghĩa macro có tham số. Mỗi định nghĩa gồm 2 dòng:
NAME p_1 p_2 \dots p_k — tên macro và danh sách k tham số (k≥0), cách nhau khoảng trắng.# + tên tham số (chuỗi hóa: thay bằng đối số tương ứng đặt trong dấu ngoặc kép "..."), token ## (toán tử dán, nối token ngay trước và token ngay sau nó lại thành một token duy nhất — cho phép dán liên tiếp, ví dụ a ## b ## c cho ra một token), hoặc một token chữ/số bất kỳ khác (giữ nguyên).Cho tiếp m lời gọi macro, mỗi lời gọi là một dòng NAME a_1 a_2 \dots a_k với ai là các đối số (mỗi đối số là một token duy nhất, không chứa khoảng trắng, không phải lời gọi macro khác).
Với mỗi lời gọi: (1) thay từng token tham số/chuỗi hóa trong thân macro bằng đối số tương ứng; (2) áp dụng phép dán ## theo đúng thứ tự trái sang phải để ghép các token liền kề; rồi in ra dãy token kết quả, các token còn lại cách nhau đúng một khoảng trắng.
Ví dụ: CONCAT(a,b) có thân a ## b, gọi CONCAT(foo,bar) → foobar. STR(x) có thân #x, gọi STR(hello) → "hello".
Dòng đầu tiên chứa số nguyên n (1≤n≤30). Với mỗi macro: dòng đầu là NAME p_1 \dots p_k (0≤k≤6), dòng sau là thân macro — danh sách token cách nhau khoảng trắng (có thể là dòng rỗng nếu thân macro không có token nào).
Dòng tiếp theo chứa số nguyên m (1≤m≤30). m dòng tiếp theo, mỗi dòng là một lời gọi NAME a_1 \dots a_k$ với $k$ đúng bằng số tham số của NAME`.
In ra m dòng, dòng thứ j là kết quả khai triển (đã áp dụng chuỗi hóa và dán token) của lời gọi thứ j.
Ví dụ:
Đầu vào:
2
MACRO p
pre ## p val
NOOP x
begin x end
2
MACRO 123
NOOP token
Đầu ra:
pre123 val
begin token end
Đầu vào:
3
CONCAT a b
a ## b
STR x
#x
CHAIN a b c
a ## b ## c
3
CONCAT foo bar
STR hello
CHAIN x y z
Đầu ra:
foobar
"hello"
xyz
Đang tải editor...