Các lượt nộp
    Danh sách bài
    Trang chủ
    Báo lỗi

    solution

    Đề bài: [Trình biên dịch] Toán tử dán token ## và chuỗi hóa # trong macro

    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 nnn định nghĩa macro có tham số. Mỗi định nghĩa gồm 2 dòng:

    • Dòng 1: NAME p_1 p_2 \dots p_k — tên macro và danh sách kkk tham số (k≥0k \ge 0k≥0), cách nhau khoảng trắng.
    • Dòng 2: thân macro dưới dạng dãy token cách nhau khoảng trắng (có thể rỗng). Mỗi token là một trong: tên tham số (được thay bằng đối số tương ứ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 mmm 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 aia_iai​ 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".

    • Định dạng đầu vào:

      Dòng đầu tiên chứa số nguyên nnn (1≤n≤301 \le n \le 301≤n≤30). Với mỗi macro: dòng đầu là NAME p_1 \dots p_k (0≤k≤60 \le k \le 60≤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 mmm (1≤m≤301 \le m \le 301≤m≤30). mmm 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`.

    • Định dạng đầu ra:

      In ra mmm dòng, dòng thứ jjj 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ứ jjj.

    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...