2009-04-28 22 views
24

वैकल्पिक शीर्षक (खोज सहायता करने के लिए)सी मैक्रो तार बनाने के लिए

  • एक स्ट्रिंग
  • कैसे एक सी मैक्रो का मान से एक चार स्ट्रिंग बनाने के लिए करने के लिए एक पूर्वप्रक्रमक टोकन कन्वर्ट?

मूल प्रश्न

मैं सी#define उपयोग करने के लिए संकलन समय पर शाब्दिक तार का निर्माण करना चाहते हैं।

स्ट्रिंग डोमेन जो डिबग के लिए बदल रहे हैं, जारी आदि

मैं कुछ करने के लिए इस तरह की कुछ बात करना चाहते हैं:

#ifdef __TESTING 
    #define IV_DOMAIN domain.org   //in house testing 
#elif __LIVE_TESTING 
    #define IV_DOMAIN test.domain.com  //live testing servers 
#else 
    #define IV_DOMAIN domain.com   //production 
#endif 

// Sub-Domain 
#define IV_SECURE "secure.IV_DOMAIN"    //secure.domain.org etc 
#define IV_MOBILE "m.IV_DOMAIN" 

लेकिन पूर्वप्रक्रमक के भीतर "

" कुछ भी नहीं है का मूल्यांकन
  1. क्या इसके आसपास कोई रास्ता है?
  2. क्या यह भी एक अच्छा विचार है?
+0

संभावित डुप्लिकेट [एक प्रोप्रोसेसर टोकन को एक स्ट्रिंग में कनवर्ट करें] (http://stackoverflow.com/questions/240353/convert-a-preprocessor -टेकन-टू-ए-स्ट्रिंग) –

उत्तर

31

सी में, स्ट्रिंग अक्षर स्वचालित रूप से संयोजित होते हैं। उदाहरण के लिए,

const char * s1 = "foo" "bar"; 
const char * s2 = "foobar"; 

s1 और s2 एक ही स्ट्रिंग कर रहे हैं।

तो, आपकी समस्या के लिए, इस सवाल का जवाब (टोकन चिपकाने के बिना)

#ifdef __TESTING 
    #define IV_DOMAIN "domain.org" 
#elif __LIVE_TESTING 
    #define IV_DOMAIN "test.domain.com" 
#else 
    #define IV_DOMAIN "domain.com" 
#endif 

#define IV_SECURE "secure." IV_DOMAIN 
#define IV_MOBILE "m." IV_DOMAIN 
6

## ऑपरेटर

#define IV_SECURE secure.##IV_DOMAIN 
+1

यह समस्या को हल नहीं करता है। – mouviciel

+0

मुझे लगता है कि ओपी स्ट्रिंग कॉन्सटेनेशन (#) के बारे में पूछ रहा था, टोकन पेस्टिंग (##) नहीं। हालांकि, मैंने डाउनवोट नहीं किया था। सवाल थोड़ा अस्पष्ट है। –

+0

टोकन पेस्टिंग ('##') या स्ट्रिंगिंग ('#') अतिरिक्त सामान के बिना काम नहीं करेगा। –

8

स्ट्रिंग्स है कि अगले एक साथ सी संकलक द्वारा संयोजित किया जाता है कर रहे हैं का उपयोग करें।

#define DOMAIN "example.com" 
#define SUBDOMAIN "test." DOMAIN 
const char *asCString = SUBDOMAIN; 
NSString *asNSString = @SUBDOMAIN; 
5

आपको # और ## ऑपरेटरों और स्वचालित स्ट्रिंग कॉन्सटेनेशन की आवश्यकता है।

# प्रीप्रोसेसिंग ऑपरेटर मैक्रो पैरामीटर को स्ट्रिंग में बदल देता है। ## ऑपरेटर एक साथ दो टोकन (जैसे मैक्रो पैरामीटर) चिपकाता है।

संभावना मेरे लिए मन में आता है

#define IV_DOMAIN domain.org 
#define IV_SECURE(DOMAIN) "secure." #DOMAIN 

है जो

#define IV_SECURE "secure." "domain.org" 

जो स्वचालित रूप से करने के लिए "secure.domain.org" (अनुवाद के चरणों संभालने जोड़ देगा IV_SECURE बदलना चाहिए सी ++ के रूप में सी में समान हैं)।

कोई अन्य संपादन: कृपया, कृपया टिप्पणियां पढ़ें, जो दिखाती है कि मैं उलझन में कैसे कामयाब रहा हूं। ध्यान रखें कि मुझे सी में पूरी तरह से अनुभव है, हालांकि शायद एक स्पर्श जंगली है। मैं इस जवाब को हटा दूंगा, लेकिन मैंने सोचा कि मैं इसे एक उदाहरण के रूप में छोड़ दूंगा कि सी प्रीप्रोसेसर द्वारा उलझन में कितना आसान है।

+0

## स्ट्रिंग पेस्ट नहीं करता है, यह टोकन चिपकाता है। सूक्ष्म लेकिन महत्वपूर्ण अंतर। –

+0

दुर्भाग्यवश, मेरे सिग्विन बॉक्स में चल रहे सीपीपी का संस्करण # ऑपरेटर को समझता नहीं है जैसा कि आप इसका वर्णन करते हैं। – mouviciel

+0

# ऑपरेटर केवल मैक्रो पैरामीटर पर काम करता है। अर्थात। # परिभाषित IV_SECURE (DOMAIN) "सुरक्षित"। #DOMAIN इस मामले में बहुत मदद नहीं है। –

3

दूसरों के रूप में उल्लेख किया है, टोकन चिपकाने इस्तेमाल होता है। आप यह भी जानते हैं कि

__TESTING 

मैक्रो नाम की तरह सी में आरक्षित हैं (वस्तुनिष्ठ सी के बारे में पता नहीं है) लागू करने के लिए होना चाहिए - आप उन्हें अपने खुद के कोड में उपयोग करने के लिए अनुमति नहीं है। आरक्षित नामों में डबल अंडरस्कोर और अंडरस्कोर और अपरकेस अक्षर से शुरू होने वाली कुछ भी शामिल है।

+0

उद्देश्य सी को सी का सख्त सुपरसैट माना जाता है, और इसलिए यह एक वैध नोटिस होना चाहिए। –

19

के कुछ तरीके हैं यह करने के लिए कर रहे हैं:

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

  2. अगर वहाँ स्ट्रिंग शामिल शाब्दिक के अलावा अन्य चीजों (यानी।, आप मैक्रो से नया पहचानकर्ता पैदा कर रहे) का उपयोग '## "पूर्वप्रक्रमक टोकन चिपकाने ऑपरेटर। आप शायद भी उपयोग करने की आवश्यकता होगी' # 'हो सकता है 'stringizing ऑपरेटर शाब्दिक स्ट्रिंग में अपने मैक्रो बनाने के लिए

# 1 का एक उदाहरण:।

#ifdef __TESTING 
    #define IV_DOMAIN "domain.org"      //in house testing 
#elif __LIVE_TESTING 
    #define IV_DOMAIN "test.domain.com"   //live testing servers 
#else 
    #define IV_DOMAIN "domain.com"      //production 
#endif 

// Sub-Domain 
#define IV_SECURE "secure." IV_DOMAIN   //secure.domain.org etc 
#define IV_MOBILE "m." IV_DOMAIN 

और जहाँ तक टोकन चिपकाने ऑपरेटर चला जाता है, मुझे नहीं लगता कि के सबसे कि जवाब जो सुझाव देता है टोकन पेस्टिंग प्रीप्रोसेसर ऑपरेटर का उपयोग करके टेड ने वास्तव में कोशिश की है - यह उपयोग करने में मुश्किल हो सकती है।

, जवाब है कि अक्सर एक संकलक त्रुटि हो जब तुम IV_SECURE मैक्रो का उपयोग करने की कोशिश करेंगे सुझाव का उपयोग करना है क्योंकि:

#define IV_SECURE "secure."##IV_DOMAIN 

फैलता करने के लिए:

"secure"domain.org 

आप का प्रयास करना चाहें ' # `'' स्ट्रिंगिंग 'ऑपरेटर का उपयोग करने के लिए:

#define IV_SECURE "secure." #IV_DOMAIN 

लेकिन था टी काम नहीं करेगा क्योंकि यह केवल मैक्रो तर्कों पर काम करता है - न केवल किसी पुराने मैक्रो।

जब आप टोकन-पेस्ट ('##') या स्ट्रिंगिंग ('#') प्रीप्रोसेसिंग ऑपरेटरों का उपयोग कर रहे हैं, तो यह जानना एक बात है कि आपको उनके लिए सही तरीके से काम करने के लिए एक अतिरिक्त स्तर का संकेत देना है सभी मामलों में।

यदि आप ऐसा नहीं करते हैं और टोकन-पेस्ट ऑपरेटर के लिए पारित आइटम मैक्रो खुद को कर रहे हैं, आप परिणाम है कि शायद कर रहे हैं मिल जाएगा कि तुम क्या नहीं करना चाहता:

#include <stdio.h> 

#define STRINGIFY2(x) #x 
#define STRINGIFY(x) STRINGIFY2(x) 
#define PASTE2(a, b) a##b 
#define PASTE(a, b) PASTE2(a, b) 

#define BAD_PASTE(x,y) x##y 
#define BAD_STRINGIFY(x) #x 

#define SOME_MACRO function_name 

int main() 
{ 
    printf("buggy results:\n"); 
    printf("%s\n", STRINGIFY(BAD_PASTE(SOME_MACRO, __LINE__))); 
    printf("%s\n", BAD_STRINGIFY(BAD_PASTE(SOME_MACRO, __LINE__))); 
    printf("%s\n", BAD_STRINGIFY(PASTE(SOME_MACRO, __LINE__))); 

    printf("\n" "desired result:\n"); 
    printf("%s\n", STRINGIFY(PASTE(SOME_MACRO, __LINE__))); 
} 

उत्पादन:

buggy results: 
SOME_MACRO__LINE__ 
BAD_PASTE(SOME_MACRO, __LINE__) 
PASTE(SOME_MACRO, __LINE__) 

desired result: 
function_name21 

तो ऊपर से अपने मूल IV_DOMAIN परिभाषित करता है और utilty मैक्रो का उपयोग कर, आप ऐसा कर सकता है आप क्या चाहते हैं पाने के लिए:

// Sub-Domain 
#define IV_SECURE "secure." STRINGIFY(IV_DOMAIN) //secure.domain.org etc 
#define IV_MOBILE "m." STRINGIFY(IV_DOMAIN) 
6

मुझे आपके पहले प्रश्न के बहुत अच्छे और सही उत्तर दिखाई देते हैं, लेकिन आपके दूसरे के लिए कोई नहीं, इसलिए यह है: मुझे लगता है कि यह एक भयानक विचार है। सर्वर नाम बदलने के लिए आपको अपने सॉफ़्टवेयर (विशेष रूप से रिलीज़ संस्करण) का पुनर्निर्माण क्यों करना होगा? साथ ही, आप कैसे जानेंगे कि आपके सॉफ़्टवेयर का कौन सा संस्करण सर्वर पर इंगित करता है? रनटाइम पर जांचने के लिए आपको एक तंत्र में निर्माण करना होगा। यदि यह आपके प्लेटफ़ॉर्म पर बिल्कुल व्यावहारिक है, तो मैं आपको कॉन्फ़िगरेशन फ़ाइल से डोमेन/यूआरएल लोड करने की सलाह देता हूं। एम्बेडेड प्लेटफॉर्म का केवल सबसे छोटा ही उद्देश्य उस उद्देश्य के लिए "व्यावहारिक" नहीं हो सकता है :)

संबंधित मुद्दे