จะพิมพ์ปอนด์ / แฮชผ่านตัวประมวลผลล่วงหน้า C ได้อย่างไร

ฉันต้องการความช่วยเหลือในการทำสิ่งต่อไปนี้:

เลเบลแมโครตัวประมวลผลล่วงหน้า (x) จะต้องส่งออก "#x" เช่น

#define label(x) ...

ถ้าฉันเรียก label(aname) ผลลัพธ์จะเป็น "#aname" (ไม่มีเครื่องหมายคำพูด)

ฉันรู้ว่าความพยายามต่อไปนี้มีข้อผิดพลาด

#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"

อาจมีหนีแบบ #(ปอนด์) แต่ไม่รู้จะหนียังไง...

แก้ไข: ฉันเรียกใช้ "gcc -E test -o test.html" เพื่อรับผลลัพธ์ ประเด็นคือ: ฉันจะพิมพ์เครื่องหมายแฮช (#) ด้วยแม็คโครโดยใช้ความสามารถของตัวประมวลผลล่วงหน้าเท่านั้นได้อย่างไร


person tuergeist    schedule 06.09.2009    source แหล่งที่มา
comment
ฉันขอถามได้ไหมว่าคุณพยายามทำอะไร?   -  person Chris Lutz    schedule 07.09.2009
comment
ใช่ ฉันจะใช้ตัวประมวลผลล่วงหน้าเพื่อสร้างโค้ด html ;) label(x) จะต้องถูกใช้เพื่อสร้างลิงก์ไปยังจุดยึด เช่น ‹a href=#label›...‹/a› ฉันลดความซับซ้อนของคำถามลง .   -  person tuergeist    schedule 07.09.2009
comment
คุณต้องการให้โค้ด HTML นี้เป็นสตริงเพื่อใช้ในโปรแกรม C หรือเป็นโค้ด HTML จริงเพื่อไปที่เบราว์เซอร์โดยตรงหรือไม่   -  person Chris Lutz    schedule 07.09.2009
comment
เป็นโค้ด HTML จริง เพื่อตรงไปที่เบราว์เซอร์หรือบันทึกเป็นไฟล์ ไม่มี #define label(x) printf(#%s, x) ;)   -  person tuergeist    schedule 07.09.2009
comment
ฉันขอแนะนำในกรณีนี้ว่าตัวประมวลผลล่วงหน้า C เป็นเครื่องมือที่ผิดสำหรับงานหรือไม่ ไม่ใช่โปรแกรมประมวลผลข้อความที่มีประสิทธิภาพ มันถูกออกแบบมาสำหรับภาษา C และใช้งานได้ดีในภาษานั้น และค่อนข้างแย่หากคุณพยายามใช้มันเพื่ออย่างอื่น คุณจะต้องต่อสู้ในการต่อสู้ที่ยากลำบากเพื่อให้มันทำสิ่งต่างๆ นี่เป็นตัวอย่างที่ดี - ฉันไม่แน่ใจด้วยซ้ำว่าคุณสามารถทำสิ่งที่คุณต้องการได้ที่นี่หรือไม่   -  person Chris Lutz    schedule 07.09.2009
comment
@Chris: มีการสังเกตข้อเสนอแนะ แต่ไม่ใช่คำตอบสำหรับคำถาม ฉันอาจยอมรับว่า I เป็นไปไม่ได้ด้วยตัวประมวลผลล่วงหน้า c ;)   -  person tuergeist    schedule 07.09.2009
comment
ฉันไม่สามารถบอกได้อย่างแน่ชัดว่า ณ จุดนี้เป็นไปได้หรือไม่ แต่ฉันจะลองดู   -  person Chris Lutz    schedule 07.09.2009
comment
สิ่งนี้ค่อนข้างมีประโยชน์จริง ๆ หากคุณต้องการใช้ตัวประมวลผลล่วงหน้าของ C เพื่อสร้างสิ่งอันดับที่ไม่มีกล่องของ Haskell ซึ่งเต็มไปด้วยแฮช   -  person Edward KMETT    schedule 19.03.2010


คำตอบ (5)


คำตอบคือ:

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

แล้ว

label(foobar)

สร้าง

#foobar

ฉันพบมันด้วยความช่วยเหลือของ พวกคุณทุกคน โดยเฉพาะอย่างยิ่งฤดูหนาว ขอบคุณมาก!

(ใช้ gcc 4.3.3)

person tuergeist    schedule 06.09.2009
comment
แต่นั่นไม่ใช่คำตอบสำหรับคำถามของคุณ: คุณถามถึงนิพจน์ที่ยกมา "#foobar" - person Christoph; 07.09.2009
comment
สิ่งนี้มีการกำหนดไว้อย่างชัดเจนหรือมีการใช้ฟังก์ชันของ tuergeist การใช้งานตัวประมวลผลล่วงหน้าเฉพาะหรือไม่ - person bdonlan; 07.09.2009
comment
ฉันแค่อยากจะบอกว่า สักวันหนึ่งเร็วๆ นี้ คุณอาจพบว่าตัวเองกลับมาที่นี่และถามคำถามอื่นเกี่ยวกับวิธีทำให้ตัวประมวลผลล่วงหน้า C ทำ X หรือ Y ฉันหวังว่าคุณจะจำสิ่งที่ฉันพูดเกี่ยวกับการต่อสู้ที่ยากลำบากครั้งนี้ และคุณพิจารณาคำแนะนำของฉันอย่างยิ่งในการหาเครื่องมือใหม่สำหรับงานนี้ - person Chris Lutz; 07.09.2009
comment
@christoph: ฉันใช้เครื่องหมายคำพูดเพื่อให้ชัดเจนว่าผลลัพธ์คืออะไรขออภัย - person tuergeist; 07.09.2009
comment
@Chris: ฉันจะไม่กลับมาถามคำถามของผู้ประมวลผลล่วงหน้า ผมสาบานเลย. ฉันต้องใช้ของจากคนอื่น :( คนเหล่านั้นคิดว่าเป็นความคิดที่ดีที่จะใช้พรีโปรเซสเซอร์และฉันไม่ได้รับอนุญาตให้เปลี่ยนเป็นเครื่องมืออื่น ฉันซาบซึ้งกับคำตอบของคุณมาก - person tuergeist; 07.09.2009
comment
@tuergeist: นั่นทำให้สิ่งต่าง ๆ ง่ายขึ้น;) ฉันขอแนะนำให้ใช้ backticks เพื่อทำเครื่องหมายเอาต์พุตเป็นโค้ดแทนที่จะเป็นเครื่องหมายคำพูดคู่ - นั่นจะช่วยป้องกันความเข้าใจผิดของฉัน - person Christoph; 07.09.2009
comment
@tuergeist - อ่า คลาสสิกที่รักษาปริศนาแฮ็คอันชาญฉลาดของคนอื่น ฉันขอโทษในนามของใครก็ตามที่มีความคิดที่ยอดเยี่ยมในการสร้าง HTML ด้วยตัวประมวลผลล่วงหน้า C - person Chris Lutz; 07.09.2009
comment
@ALL: ฉันจะโหวตคำตอบทั้งหมดที่คุณสนับสนุนคำถามนี้ .. ขอบคุณและราตรีสวัสดิ์ - person tuergeist; 07.09.2009
comment
มันเจ๋งมาก แต่น่าเสียดายที่ตัวประมวลผลล่วงหน้าทำงานเพียงครั้งเดียว สิ่งนี้ไม่สามารถใช้ในการเขียนคำจำกัดความเพิ่มเติมได้ - person Steven Lu; 04.01.2014

ฉันไม่คิดว่าคุณจะทำได้ ซึ่งไม่ใช่เรื่องที่ไม่สมเหตุสมผลเลย เนื่องจากเอาต์พุตของตัวประมวลผลล่วงหน้า C ไม่ควรสร้าง '#' ที่ไม่มีเครื่องหมายคำพูด เพราะนั่นจะบ่งบอกถึงคำสั่งของตัวประมวลผลล่วงหน้า และคุณไม่สามารถสร้างคำสั่งตัวประมวลผลล่วงหน้าได้ทันทีเช่น ที่.

กล่าวอีกนัยหนึ่ง C preprocessor คือ preprocessor สำหรับ C (และ C++) และไม่ใช่เครื่องมือที่ใช้งานทั่วไปโดยสมบูรณ์

ใช้ตัวประมวลผลมาโครสำรอง (m4 เป็นคำแนะนำมาตรฐานสำหรับระบบที่คล้าย Unix) หรือดำเนินการบางอย่างที่แตกต่างออกไป

ตัวอย่างเช่น ให้แทนที่แมโคร:

#define label(x)    !@!x

จากนั้นโพสต์ประมวลผลเอาต์พุตแทนที่ '!@!' กับ '#'.

(โปรแกรม imake ใช้การแสดงความสามารถที่คล้ายกัน โดยตัวประมวลผลล่วงหน้าของ C จะทำงานส่วนใหญ่ แต่เอาต์พุตของมันไม่ได้คงการขึ้นบรรทัดใหม่ที่จำเป็นสำหรับ 'make' ดังนั้น 'imake' จึงใช้สัญลักษณ์ '@@\' หรือสิ่งที่เกี่ยวข้องเพื่อระบุว่าอยู่ที่ไหน ต้องแทรกตัวแบ่งบรรทัดหลังจากที่ตัวประมวลผลล่วงหน้า C ทำงานได้แย่ที่สุด)

person Jonathan Leffler    schedule 06.09.2009

คุณสามารถทำสิ่งนี้:

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

ฉันทดสอบสิ่งนี้โดยรันโดยตรงผ่าน cpp (ตัวประมวลผลล่วงหน้า C) แทนที่จะผ่าน gcc ตัวอย่าง:

cpp test > test.html

การใช้ cpp ที่เป็นส่วนหนึ่งของ gcc เวอร์ชัน 4.0.1

ปัญหาเดียวที่ฉันสังเกตเห็นคือฉันได้รับเอาต์พุตที่ไม่ต้องการเพิ่มเติม กล่าวคือ 4 บรรทัดแรกของไฟล์มีดังนี้:

# 1 "test"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "test"
person E.M.    schedule 06.09.2009
comment
@tuergeist - จริง ๆ แล้วฉันทดสอบมันแตกต่างจากคุณเล็กน้อย ดูโพสต์ที่อัปเดตของฉัน - person E.M.; 07.09.2009
comment
บรรทัดแรกเหล่านี้ใช้ได้และสามารถละเว้นได้ - person tuergeist; 07.09.2009
comment
@wintermute: gcc 4.3.3 ของฉันนำข้อผิดพลาดที่ฉันโพสต์ไว้ก่อนหน้านี้ :| แต่มันใช้ได้กับคำจำกัดความของแฮช - person tuergeist; 07.09.2009
comment
เส้นที่ไม่ต้องการสามารถระงับได้ด้วยสวิตช์ -P - person Jeff Sharp; 20.06.2015

ตัวอักษรสตริงใน C จะถูกต่อเข้าด้วยกัน ดังนั้นคุณจึงทำได้

#define label(x) "#" #x

ฉันไม่คิดว่ามันเป็นไปได้หากไม่มีการต่อสตริง (เช่นโดยไม่ต้องเรียกใช้คอมไพเลอร์ C ตามที่คุณต้องการ):

คุณสามารถทำสิ่งพิเศษบางอย่างได้ด้วยระดับทางอ้อมเพิ่มเติม และฉันยังมีตัวประมวลผลล่วงหน้าเพื่อสร้างเอาต์พุตที่ต้องการด้วย

#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)

ปัญหาคือมันจะสร้างข้อความแสดงข้อผิดพลาดเมื่อ in_between() ขยายเป็น #foo ซึ่งไม่ใช่โทเค็นตัวประมวลผลล่วงหน้าที่ถูกต้อง ฉันไม่เห็นวิธีแก้ไขปัญหานี้

คำแนะนำของฉันคือเลือกเครื่องมือที่เหมาะสมสำหรับงาน: เปลี่ยนเป็นภาษามาโครอื่นเช่น m4 หรือแม้แต่ ML/I หากคุณรู้สึกอยากผจญภัยหรือใช้ภาษาสคริปต์เช่น PHP หรือ Perl GPP ก็ดูดีเช่นกันและอาจเหมาะสมกว่า

person Christoph    schedule 06.09.2009
comment
นำไปสู่ ​​'# string' ซึ่งไม่ใช่ '#string' ฉันขอถามคุณว่าคุณทดสอบคำตอบของคุณอย่างไร - person tuergeist; 07.09.2009
comment
ในภาษา C การเขียน char *c = "#" "string"; เหมือนกับการเขียน char *c = "#string"; - ภาษาจะเชื่อมตัวอักษรสตริงที่อยู่ติดกัน ดังนั้นสิ่งนี้จึงใช้ไม่ได้กับตัวประมวลผลล่วงหน้า แต่จะใช้ได้กับภาษา C - person Chris Lutz; 07.09.2009
comment
ตามที่ฉันเขียน ฉันจะใช้เอาต์พุตของตัวประมวลผลล่วงหน้า โดยจะไม่มีคอมไพเลอร์ c เพิ่มเติมทำงาน - person tuergeist; 07.09.2009

พยายาม:

#define label(x) "#"x
person Neil    schedule 06.09.2009
comment
ใช้ได้เฉพาะถ้าใช้เป็น char* ใน c - person tuergeist; 07.09.2009