सी / सी ++ मैक्रो स्ट्रिंग समवर्ती


121
#define STR1      "s"
#define STR2      "1"
#define STR3      STR1 ## STR2

क्या STR3 == "s1" को संक्षिप्त करना संभव है? आप किसी अन्य मैक्रो फ़ंक्शन में आर्गल्स पास करके ऐसा कर सकते हैं। लेकिन क्या कोई सीधा रास्ता है?


क्या यह #define STR3 STR1 ## STR2
श्रीनिधि

यह या तो नहीं होना चाहिए क्योंकि वह STR3 को परिभाषित करता है जो पूर्वप्रक्रमक टोकन STR1STR2 हो। और किसी अन्य मैक्रो फ़ंक्शन के लिए args पास करना मदद नहीं करता है, क्योंकि स्ट्रिंग शाब्दिक को एक साथ चिपकाया नहीं जा सकता है - "s" "1" एक वैध टोकन नहीं है।
जिम बाल्टर

जवाबों:


157

यदि वे दोनों तार हैं तो आप बस कर सकते हैं:

#define STR3 STR1 STR2

प्रीप्रोसेसर स्वतः समीपवर्ती तारों को समेट लेता है।

संपादित करें:

जैसा कि नीचे उल्लेख किया गया है, यह प्रीप्रोसेसर नहीं है लेकिन संकलक है जो संघनन करता है।


17
भाषा के स्तर पर तकनीकी रूप से स्ट्रिंग समवर्ती किया जाता है।
मार्टिन यॉर्क

47
प्रीप्रोसेसर ऐसा कोई काम नहीं करता है। यह सी भाषा उचित है जो आसन्न स्ट्रिंग शाब्दिक का इलाज करती है जैसे कि वे एकल स्ट्रिंग शाब्दिक थे।
जिम बेल्टर

7
यह एक तकनीकी की तुलना में अधिक है - आप CONCATENATE नहीं कर सकते हैं L"a"और "b"प्राप्त करने के लिए L"ab", लेकिन आप कर सकते हैं जोड़ L"a"और L"b"प्राप्त करने के लिए L"ab"
MSalters

115

आपको स्ट्रिंग शाब्दिकों के लिए उस तरह के समाधान की आवश्यकता नहीं है, क्योंकि वे भाषा के स्तर पर संक्षिप्त हैं, और यह वैसे भी काम नहीं करेगा क्योंकि "s" "1" एक वैध प्रीप्रोसेसर टोकन नहीं है।

[संपादित करें: गलत "बस रिकॉर्ड के लिए" टिप्पणी के जवाब में नीचे टिप्पणी की गई है कि दुर्भाग्य से कई upvotes प्राप्त हुए हैं, मैं ऊपर दिए गए कथन को दोहराऊंगा और निरीक्षण करूंगा कि प्रोग्राम टुकड़ा

#define PPCAT_NX(A, B) A ## B
PPCAT_NX("s", "1")

इस त्रुटि संदेश को gcc के प्रीप्रोसेसिंग चरण से उत्पन्न करता है: त्रुटि: "" s "" और "" 1 "" चिपकाना एक मान्य प्रीप्रोसेसिंग टोकन नहीं देता है

]

हालाँकि, सामान्य टोकन चिपकाने के लिए, यह प्रयास करें:

/*
 * Concatenate preprocessor tokens A and B without expanding macro definitions
 * (however, if invoked from a macro, macro arguments are expanded).
 */
#define PPCAT_NX(A, B) A ## B

/*
 * Concatenate preprocessor tokens A and B after macro-expanding them.
 */
#define PPCAT(A, B) PPCAT_NX(A, B)

फिर, जैसे, दोनों PPCAT_NX(s, 1)और PPCAT(s, 1)पहचानकर्ता का उत्पादन s1, जब तक कि sकोई मैक्रो, जिसमें मामले के रूप में परिभाषित किया गया है PPCAT(s, 1)का उत्पादन<macro value of s>1

विषय पर जारी ये मैक्रो हैं:

/*
 * Turn A into a string literal without expanding macro definitions
 * (however, if invoked from a macro, macro arguments are expanded).
 */
#define STRINGIZE_NX(A) #A

/*
 * Turn A into a string literal after macro-expanding it.
 */
#define STRINGIZE(A) STRINGIZE_NX(A)

फिर,

#define T1 s
#define T2 1
STRINGIZE(PPCAT(T1, T2)) // produces "s1"

इसके विपरीत,

STRINGIZE(PPCAT_NX(T1, T2)) // produces "T1T2"
STRINGIZE_NX(PPCAT_NX(T1, T2)) // produces "PPCAT_NX(T1, T2)"

#define T1T2 visit the zoo
STRINGIZE(PPCAT_NX(T1, T2)) // produces "visit the zoo"
STRINGIZE_NX(PPCAT(T1, T2)) // produces "PPCAT(T1, T2)"

8
केवल रिकॉर्ड के लिए, "s""1"C (और C ++) में मान्य है। वे दो टोकन (स्ट्रिंग शाब्दिक) हैं जो कंपाइलर स्वयं को सम्‍मिलित करेगा और एक टोकन के रूप में खतरा होगा।
शहबाज़

4
आप मेरी टिप्पणी और सी भाषा दोनों को गलत समझते हैं। मैंने कहा "s""1" isn't a valid token- यह सही है; यह है, जैसा कि आप कहते हैं, दो टोकन। लेकिन ## के साथ एक साथ व्यवहार करने से उन्हें एक एकल टोकन होगा, न कि दो टोकन, और इसलिए संकलक एक संघटन नहीं करेगा, बल्कि लेक्सर उन्हें अस्वीकार कर देगा (भाषा को निदान की आवश्यकता है)।
जिम बेल्टर

8
@ mr5 टिप्पणियों को ध्यान से पढ़ें। मैक्रो तर्कों के रूप में पारित मैक्रो नामों को पारित होने से पहले विस्तारित नहीं किया जाता है। हालांकि, वे मैक्रो के शरीर में विस्तारित हैं। इसलिए यदि A को FRED के रूप में परिभाषित किया जाता है, तो STRINGIZE_NX (A) "A" तक फैलता है, लेकिन STRINGIZE (A) STRINGIZE_NX (FRED) तक फैल जाता है, जो "FRED" तक फैल जाता है।
जिम बेल्टर

1
@bharath परिणामी स्ट्रिंग "PPCAT (T1, T2)" है - जैसा कि अपेक्षित और वांछित है। और अपेक्षित "s1" नहीं - बिल्कुल भी अपेक्षित नहीं। हमें एक अतिरिक्त अप्रत्यक्ष / घोंसले के शिकार की आवश्यकता क्यों है? - कोड टिप्पणी, और ऊपर 6 टिप्पणी के साथ मेरी टिप्पणी पढ़ें। केवल मैक्रोज़ के निकायों का विस्तार किया जाता है; मैक्रो निकायों के बाहर, मैक्रो में पारित होने से पहले कोष्ठक के बीच मैक्रो तर्क का विस्तार नहीं किया जाता है। इसलिए STRINGIZE_NX(whatever occurs here)"जो कुछ भी यहां होता है", जो भी घटित होता है, या यहाँ के लिए किसी भी स्थूल परिभाषा की परवाह किए बिना विस्तारित होता है।
जिम बाल्टर

1
@bharath निश्चित रूप से यह "Name A" नहीं छापता है - A पैरामीटर नाम है, मैक्रो का तर्क नहीं है, जो कि ALEX है। आपने दावा किया if A is defined as FRED then STRINGIZE_NX(A) still expands to "FRED"- यह गलत है, और आपके परीक्षण जैसा कुछ नहीं है। आप इस अधिकार को समझने या न पाने के लिए कठिन प्रयास कर रहे हैं, और मैं आपको आगे जवाब देने नहीं जा रहा हूं।
जिम बाल्टर

24

संकेत: STRINGIZEऊपर दिया गया मैक्रो शांत है, लेकिन यदि आप कोई गलती करते हैं और उसका तर्क स्थूल नहीं है - तो आपको नाम में एक टाइपो था, या भूल गया#include हेडर फ़ाइल में - तब कंपाइलर प्रसन्नतापूर्वक स्थूल मैक्रो नाम में डाल देगा कोई त्रुटि के साथ स्ट्रिंग।

यदि आप चाहते हैं कि तर्क STRINGIZEहमेशा एक सामान्य सी मान के साथ एक मैक्रो है, तो

#define STRINGIZE(A) ((A),STRINGIZE_NX(A))

एक बार इसका विस्तार करेगा और वैधता के लिए इसकी जांच करेगा, इसे छोड़ देगा, और फिर इसे एक स्ट्रिंग में फिर से विस्तारित करेगा।

मुझे यह पता लगाने में थोड़ा समय लगा कि मैं इसके बजाय क्यों STRINGIZE(ENOENT)समाप्त हो रहा था ... मैंने शामिल नहीं किया था ।"ENOENT""2"errno.h


2
,ऑपरेटर के उचित उपयोग के लिए महत्वपूर्ण अवलोकन, और +1 । :)
जेसी चिशोल्म

2
कोई विशेष कारण नहीं है कि स्ट्रिंग की सामग्री एक मान्य सी अभिव्यक्ति होनी चाहिए। यदि आप ऐसा करना चाहते हैं, तो मैं इसे अलग नाम देने की सलाह देता हूं, जैसे STRINGIZE_EXPR।
जिम बाल्टर

वह चाल अलगाव में काम कर सकती है। लेकिन यह संकलक को तार के एक क्रम को देखने से रोकता है जिसे वह समतल करेगा। (परिणामस्वरूप ((1),"1") "." ((2),"2")सिर्फ़ "1" "के बजाय" "" 2 ") जैसे अनुक्रम
ऑटोमोर्फिक

बस यह स्पष्ट करने के लिए कि ऑटोमोर्फिक क्या कह रहा है: मूल STRINGIZEपरिभाषा के साथ, "The value of ENOENT is " STRINGIZE(ENOENT)काम करता है, जबकि "The value of ENOENT is" STRINGIZE_EXPR(X)एक त्रुटि पैदा करता है।
जिम बेल्टर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.