Bagaimana cara mencetak pon/hash melalui preprosesor C?

Saya memerlukan bantuan untuk melakukan hal berikut:

label makro praprosesor (x) akan menampilkan "#x", misalnya,

#define label(x) ...

jika saya memanggil label(aname), outputnya adalah "#aname" (tanpa tanda kutip)

Saya tahu, percobaan berikut ini adalah kesalahan.

#define label(x) #x   // leads to "x"
#define label(x) \#x  // is \"x"
#define label(x) "#x" // is "#x" (but not the content of x") "#otto"

Mungkin ada semacam escape # (pound), tapi saya tidak tahu, bagaimana cara escapenya...

Edit: Saya menjalankan "gcc -E test -o test.html" untuk mendapatkan hasilnya. Intinya: Bagaimana cara mencetak tanda pagar (#) dengan makro hanya menggunakan kemampuan preprocessor?


person tuergeist    schedule 06.09.2009    source sumber
comment
Bolehkah saya bertanya apa yang Anda coba lakukan?   -  person Chris Lutz    schedule 07.09.2009
comment
g ya. Saya akan menggunakan praprosesor untuk membuat kode html ;) label(x) harus digunakan untuk membuat tautan ke jangkar, misalnya, ‹a href=#label›...‹/a› Saya mengurangi kerumitan pertanyaan .   -  person tuergeist    schedule 07.09.2009
comment
Apakah Anda ingin kode HTML ini sebagai string, untuk digunakan dalam program C, atau sebagai kode HTML sebenarnya, langsung masuk ke browser?   -  person Chris Lutz    schedule 07.09.2009
comment
sebagai kode HTML sebenarnya, untuk langsung menuju ke browser atau untuk menyimpan dalam file. Tidak ada #define label(x) printf(#%s, x) ;)   -  person tuergeist    schedule 07.09.2009
comment
Bolehkah saya menyarankan dalam hal ini bahwa praprosesor C adalah alat yang salah untuk pekerjaan itu? Ini bukan pengolah teks yang kuat. Ini dirancang untuk bahasa C, dan berfungsi dengan baik dalam bahasa tersebut, dan agak buruk jika Anda mencoba menggunakannya untuk banyak hal lain. Anda akan berjuang keras untuk mewujudkannya. Ini adalah contoh yang bagus - Saya bahkan tidak yakin apakah Anda dapat melakukan apa yang Anda inginkan di sini.   -  person Chris Lutz    schedule 07.09.2009
comment
@Chris: saran diperhatikan, tetapi bukan jawaban atas pertanyaannya. Saya mungkin menerima jawaban I tidak mungkin dengan praprosesor c;)   -  person tuergeist    schedule 07.09.2009
comment
Saya tidak bisa mengatakan secara pasti apakah hal itu mungkin atau tidak pada saat ini, tapi saya akan memeriksanya.   -  person Chris Lutz    schedule 07.09.2009
comment
Ini sebenarnya cukup berguna jika Anda ingin menggunakan praprosesor C untuk menghasilkan tupel tanpa kotak Haskell, yang dirusak dengan hash.   -  person Edward KMETT    schedule 19.03.2010


Jawaban (5)


Jawabannya adalah:

#define hash #
#define f(x) x
#define label(a) f(hash)a

Kemudian

label(foobar)

menciptakan

#foobar

Saya menemukannya dengan bantuan kalian semua, terutama wintermute. Terima kasih banyak!

(Menggunakan gcc 4.3.3)

person tuergeist    schedule 06.09.2009
comment
tapi itu bukan jawaban untuk pertanyaan Anda: Anda meminta ekspresi yang dikutip "#foobar" - person Christoph; 07.09.2009
comment
Apakah ini terdefinisi dengan baik, atau merupakan fungsi dari implementasi praprosesor khusus yang digunakan tuergeist? - person bdonlan; 07.09.2009
comment
Saya hanya ingin mengatakan bahwa, suatu hari nanti, Anda mungkin akan kembali ke sini dan mengajukan pertanyaan lain tentang cara membuat praprosesor C melakukan X atau Y. Saya harap Anda akan mengingat apa yang saya katakan tentang perjuangan berat ini, dan Anda sangat mempertimbangkan rekomendasi saya untuk menemukan alat baru untuk pekerjaan ini. - person Chris Lutz; 07.09.2009
comment
@christoph: Saya hanya menggunakan tanda kutip untuk memperjelas apa hasilnya, maaf - person tuergeist; 07.09.2009
comment
@Chris: Saya tidak akan kembali untuk menanyakan pertanyaan praprosesor. Aku bersumpah. Saya harus menggunakan barang dari orang lain :( Orang-orang itu berpikir bahwa menggunakan praprosesor adalah ide yang bagus dan saya tidak diizinkan untuk beralih ke alat lain. Saya sangat menghargai jawaban Anda. - person tuergeist; 07.09.2009
comment
@tuergeist: baiklah, itu membuat segalanya lebih mudah ;) Saya sarankan menggunakan backticks untuk menandai output sebagai kode alih-alih tanda kutip ganda - itu akan mencegah kesalahpahaman saya - person Christoph; 07.09.2009
comment
@tuergeist - Ah, hal klasik yang mempertahankan teka-teki peretasan pintar orang lain. Saya minta maaf atas nama siapa pun yang memiliki ide cemerlang untuk menghasilkan HTML dengan preprosesor C. - person Chris Lutz; 07.09.2009
comment
@ALL: Saya akan memberi suara positif pada semua jawaban yang Anda dukung pertanyaan ini.. Terima kasih dan selamat malam. - person tuergeist; 07.09.2009
comment
Ini sangat keren tapi sayangnya praprosesor hanya berjalan sekali. Ini tidak dapat digunakan untuk menulis lebih banyak definisi - person Steven Lu; 04.01.2014

Saya rasa Anda tidak bisa, yang tidak sepenuhnya tidak masuk akal karena keluaran dari praprosesor C tidak boleh menghasilkan '#' tanpa tanda kutip karena itu akan menunjukkan arahan pra-prosesor, dan Anda tidak dapat membuat arahan pra-prosesor dengan cepat seperti itu.

Dengan kata lain, praprosesor C adalah praprosesor untuk C (dan C++) dan bukan alat yang sepenuhnya bertujuan umum.

Gunakan prosesor makro alternatif (m4 adalah rekomendasi standar pada sistem mirip Unix), atau lakukan hal yang berbeda.

Misalnya, dapatkan pengganti makro:

#define label(x)    !@!x

Kemudian pasca-proses hasilnya dengan mengganti '!@!' dengan '#'.

(Program imake menggunakan aksi serupa; praprosesor C melakukan sebagian besar pekerjaan, namun outputnya tidak mempertahankan jeda baris yang diperlukan oleh 'make', jadi 'imake' menggunakan notasi '@@\' atau sekitar itu untuk menunjukkan di mana jeda baris perlu dimasukkan setelah praprosesor C melakukan yang terburuk.)

person Jonathan Leffler    schedule 06.09.2009

Anda dapat melakukan sesuatu seperti ini:

#define f(x) x
#define label(a) f(#)a

Saya mengujinya dengan menjalankannya langsung melalui cpp (praprosesor C) alih-alih melalui gcc. Contoh:

cpp test > test.html

Menggunakan cpp yang merupakan bagian dari gcc versi 4.0.1.

Satu-satunya masalah yang saya perhatikan adalah saya mendapatkan beberapa keluaran tambahan yang tidak diinginkan, yaitu 4 baris pertama file adalah sebagai berikut:

# 1 "test"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "test"
person E.M.    schedule 06.09.2009
comment
@tuergeist - Sebenarnya saya mengujinya sedikit berbeda dari Anda. Lihat posting saya yang diperbarui. - person E.M.; 07.09.2009
comment
baris pertama ini oke dan dapat diabaikan. - person tuergeist; 07.09.2009
comment
@wintermute: gcc 4.3.3 saya membawa kesalahan yang saya posting sebelumnya :| Tapi itu berhasil dengan definisi hash - person tuergeist; 07.09.2009
comment
Garis yang tidak diinginkan dapat ditekan dengan tombol -P. - person Jeff Sharp; 20.06.2015

String literal dalam C akan digabungkan, jadi Anda bisa melakukannya

#define label(x) "#" #x

Saya rasa itu tidak mungkin terjadi tanpa penggabungan string (yaitu tanpa memanggil kompiler C seperti yang ingin Anda lakukan):

Anda dapat melakukan beberapa hal mewah dengan tingkat tipuan tambahan dan saya bahkan mendapatkan praprosesor untuk menghasilkan keluaran yang diinginkan melalui

#define hash #
#define quote(x) #x
#define in_between(c, d) quote(c ## d)
#define join(c, d) in_between(c, d)
#define label(x) join(hash, x)
label(foo)

Masalahnya adalah ini juga akan menghasilkan pesan kesalahan saat in_between() diperluas ke #foo, yang bukan merupakan token praprosesor yang valid. Saya tidak melihat ada jalan lain untuk mengatasi hal ini.

Saran saya adalah memilih alat yang tepat untuk pekerjaan itu: beralihlah ke bahasa makro lain seperti m4 atau bahkan ML/I jika Anda suka bertualang atau gunakan bahasa skrip seperti PHP atau Perl. GPP sepertinya juga bagus dan mungkin lebih cocok.

person Christoph    schedule 06.09.2009
comment
mengarah ke '# string' yang bukan '#string' bolehkah saya bertanya bagaimana Anda menguji jawaban Anda? - person tuergeist; 07.09.2009
comment
Dalam bahasa C, penulisan char *c = "#" "string"; identik dengan penulisan char *c = "#string"; - bahasa tersebut menggabungkan string literal yang bersebelahan. Jadi, ini tidak berfungsi dengan praprosesor, tetapi berfungsi dengan bahasa C. - person Chris Lutz; 07.09.2009
comment
Saat saya menulis, saya akan menggunakan keluaran praprosesor, tidak ada kompiler c tambahan yang akan dijalankan. - person tuergeist; 07.09.2009

Mencoba:

#define label(x) "#"x
person Neil    schedule 06.09.2009
comment
hanya ok jika digunakan sebagai char* di c - person tuergeist; 07.09.2009