2012-11-21 15 views
5

के रूप में मैं पूर्वप्रक्रमक के साथ प्रपत्र "example.cpp:34" की एक स्थिर स्ट्रिंग निर्माण करने के लिए चाहते हैं, लेकिन __FILE__ मैक्रो "lib/example/example.cpp" करने का विस्तार होगा और __LINE__ एक पूर्णांक के रूप में 34 विस्तारित होती है। क्या मैं प्रीप्रोसेसर के साथ वांछित स्ट्रिंग का निर्माण कर सकता हूं? जीसीसी सीमाएं ठीक हैं।सीपीपी पूर्वप्रक्रमक और फ़ाइल नाम के basename, लाइन नंबर स्ट्रिंग

संपादित करें यहां सबसे महत्वपूर्ण हिस्सा यह है कि मुझे एक स्थिर सी-शैली स्ट्रिंग चाहिए, इसलिए मैं basename फ़ंक्शन का उपयोग नहीं कर सकता। मैं सोच रहा हूं कि प्रीप्रोसेसर में उस कार्यक्षमता को दोहराने के लिए कोई तरीका है, संभवतः बूस्ट एक्सटेंशन के साथ?

+0

है सी ++ 11 ठीक? प्रीप्रोसेसर में या स्ट्रिंग-टाइम में प्रयोग करने योग्य स्ट्रिंग चाहिए? – kennytm

+0

@ केनीटीएम नहीं, मैं सी ++ 11 का उपयोग नहीं कर सकता। मैं इसे संकलित समय पर चाहता हूं। बूस्ट भी ठीक है। –

+0

या '__FILE__' का उपयोग न करें, लेकिन ब्याज की प्रत्येक फ़ाइल के शीर्ष पर अपनी स्वयं की स्ट्रिंग अक्षर परिभाषित करें। – chill

उत्तर

0

आप के रूप __FILE__ फैलता सिर्फ basename() उपयोग करने के लिए एक स्थिरांक सी स्ट्रिंग

__FILE__ इस मैक्रो एक सी स्ट्रिंग निरंतर के रूप में, वर्तमान इनपुट फ़ाइल के नाम से फैलता में सक्षम होना चाहिए ।

printf ("%s:%d\n", basename(__FILE__), __LINE__); 
+0

मुझे एक स्थिर सी-स्ट्रिंग चाहिए, इसलिए यह किसी फ़ंक्शन का आउटपुट नहीं हो सकता है। –

+0

@pythonicmetaphor आप फ़ंक्शन के आउटपुट का क्या मतलब रखते हैं? आप इसे एक समारोह से वापस करना चाहते हैं? – iabdalkader

+0

मेरा मतलब है कि मुझे एक स्थिर स्ट्रिंग चाहिए, इसलिए मैं इसे किसी भी फ़ंक्शन का उपयोग नहीं कर सकता, केवल इसे बनाने के लिए प्रीप्रोसेसर। –

2

आप इस तथ्य का लाभ ले सकते है कि आसन्न स्ट्रिंग शाब्दिक concatenated रहे हैं:

#define STRINGIFY(s) #s 
#define FILELINE(line) __FILE__ ":" str(line) 

फिर FILELINE(__LINE__) की तरह उपयोग। मैं अक्सर ऐसा नहीं करता इसलिए __LINE__ मैक्रो पास करने से बेहतर तरीका हो सकता है। यह मेरे लिए वैसे भी काम करता है, के साथ परीक्षण:

#include <iostream> 

#define str(s) #s 
#define FILELINE(line) __FILE__ ":" str(line) 

int main(int argc, const char* argv[]) 
{ 
    std::cout << FILELINE(__LINE__) << std::endl; 
    return 0; 
} 

मैं:

main.cpp:9 
+0

है, इसलिए मुझे लगता है कि समस्या वास्तव में बेसनाम है। आपको main.cpp मिलता है क्योंकि आप किसी भिन्न निर्देशिका में फ़ाइल शामिल नहीं कर रहे थे। –

0

मैं एक तरह से basename पाने के लिए के बारे में पता नहीं है, लेकिन oyther है कि तुलना में आप stringification पूर्वप्रक्रमक ऑपरेटर इस्तेमाल किया जा सकता '#', जैसे:

#define M__(x,y) x ":" #y 
#define M_(x,y) M__(x, y) 
#define M M_(__FILE__, __LINE__) 

अब M"lib/example/example.cpp:34" को विस्तार होगा (दिए गए आप, कि लाइन पर है कि फाइल में रख ओएफसी :))

0

ठीक है, न केवल प्रीप्रोसेसर का उपयोग किया जाना चाहिए - लेकिन यह अंतिम उपयोगकर्ता को नहीं देखा जाएगा।

आप BASENAME() चाहते हैं कुछ फ़ाइल में इस्तेमाल किया जाएगा - इस हेडर फाइल basename.h का उपयोग करें:

// basename.h 
#include <string.h> 

static size_t basename_start_calc(const char* filename) 
{ 
    const char* base = strrchr(filename, '/'); 
    return base ? (base - filename + 1) : 0; 
} 
static inline size_t basename_start(const char* filename) 
{ 
    static size_t retval = basename_start_calc(filename); 
    return retval; 
} 
#define STR_(t) #t 
#define STR(t) STR_(t) 
#define BASENAME() ((__FILE__ ":" STR(__LINE__)) + basename_start(__FILE__)) 

एक ideone example here

basename_start(__FILE__) का मूल्यांकन केवल स्रोत स्रोत के लिए एक बार किया जाएगा। दुर्भाग्य से आप इस समाधान का उपयोग हेडर फ़ाइलों में नहीं कर सकते - केवल स्रोत फ़ाइलों में। आप इसे बदल सकते हैं, इसलिए इसे हर जगह इस्तेमाल किया जा सकता है - लेकिन फिर दिए गए फ़ाइल नाम के लिए आधार रेखा की शुरुआत हर बार गणना की जाएगी। basename_start_calc(__FILE__)basename_start(__FILE__) के बजाय उपयोग करें ...

मेरा मानना ​​है कि यह स्वचालित रूप से आपके पास हो सकता है।

बेशक आप हर फ़ाइल मैक्रो में हाथ से परिभाषित कर सकते हैं:

#define BASENAME() ("somefile.cpp:" STR(__LINE__)) 

लेकिन मुझे यकीन है कि यह है कि तुम क्या चाहते थे है नहीं कर रहा हूँ ....

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