आधुनिक C ++ इस सुपर को सरल बनाता है।
सी ++ 20
C ++ 20 परिचय std::format
देता है, जो आपको वास्तव में ऐसा करने की अनुमति देता है। यह अजगर के समान ही प्रतिस्थापन क्षेत्रों का उपयोग करता है :
#include <iostream>
#include <format>
int main() {
std::cout << std::format("Hello {}!\n", "world");
}
की जाँच करें पूर्ण प्रलेखन ! यह जीवन का एक बड़ा गुण है।
सी ++ 11
साथ सी ++ 11 रों std::snprintf
, यह पहले से ही एक बहुत आसान और सुरक्षित कार्य बन गया।
#include <memory>
#include <string>
#include <stdexcept>
template<typename ... Args>
std::string string_format( const std::string& format, Args ... args )
{
size_t size = snprintf( nullptr, 0, format.c_str(), args ... ) + 1; // Extra space for '\0'
if( size <= 0 ){ throw std::runtime_error( "Error during formatting." ); }
std::unique_ptr<char[]> buf( new char[ size ] );
snprintf( buf.get(), size, format.c_str(), args ... );
return std::string( buf.get(), buf.get() + size - 1 ); // We don't want the '\0' inside
}
ऊपर कोड स्निपेट CC0 1.0 के तहत लाइसेंस प्राप्त है ।
लाइन द्वारा लाइन स्पष्टीकरण:
उद्देश्य:char*
उपयोग करके लिखेंstd::snprintf
और फिर उसे एक में परिवर्तित करेंstd::string
।
सबसे पहले, हम एक विशेष स्थिति का उपयोग करके चार सरणी की वांछित लंबाई निर्धारित करते हैं snprintf
। से cppreference.com :
प्रतिलाभ की मात्रा
[...] यदि परिणामी स्ट्रिंग को buf_size सीमा के कारण छोटा कर दिया जाता है, तो फ़ंक्शन कुल वर्णों को वापस कर देता है (समाप्त करने योग्य नल-बाइट को शामिल नहीं करता है), जो कि सीमा लागू नहीं होने पर लिखा होता।
इसका मतलब यह है कि वांछित आकार वर्णों की संख्या प्लस एक है , जिससे कि नल-टर्मिनेटर अन्य सभी पात्रों के बाद बैठ जाएगा और यह फिर से स्ट्रिंग निर्माता द्वारा काट दिया जा सकता है। इस मुद्दे को टिप्पणियों में @ alexk7 द्वारा समझाया गया था।
size_t size = snprintf( nullptr, 0, format.c_str(), args ... ) + 1;
snprintf
यदि कोई त्रुटि हुई है, तो एक ऋणात्मक संख्या लौटाएगा, इसलिए हम फिर से जाँच करेंगे कि क्या स्वरूपण वांछित के रूप में काम करता है। ऐसा न करने से मूक त्रुटियां हो सकती हैं या भारी बफर का आवंटन हो सकता है, जैसा कि टिप्पणियों में @ead द्वारा बताया गया है।
if( size <= 0 ){ throw std::runtime_error( "Error during formatting." ); }
अगला, हम एक नया वर्ण सरणी आवंटित करते हैं और इसे असाइन करते हैं std::unique_ptr
। यह आमतौर पर सलाह दी जाती है, क्योंकि आपको delete
इसे फिर से मैन्युअल नहीं करना होगा ।
ध्यान दें कि यह unique_ptr
उपयोगकर्ता-परिभाषित प्रकारों के साथ आवंटित करने का एक सुरक्षित तरीका नहीं है क्योंकि आप मेमोरी को नहीं दे सकते हैं यदि निर्माण एक अपवाद फेंकता है!
std::unique_ptr<char[]> buf( new char[ size ] );
उसके बाद, हम निश्चित रूप से बस snprintf
इसके इच्छित उपयोग के लिए उपयोग कर सकते हैं और स्वरूपित स्ट्रिंग को लिख सकते हैं char[]
।
snprintf( buf.get(), size, format.c_str(), args ... );
अंत में, हम std::string
उस से एक नया बनाते हैं और वापस करते हैं, जिससे अंत में अशक्त-टर्मिनेटर को छोड़ना सुनिश्चित होता है।
return std::string( buf.get(), buf.get() + size - 1 );
आप यहां कार्रवाई में एक उदाहरण देख सकते हैं ।
यदि आप भी std::string
तर्क सूची में उपयोग करना चाहते हैं, तो इस जिस्ट पर एक नज़र डालें ।
विजुअल स्टूडियो उपयोगकर्ताओं के लिए अतिरिक्त जानकारी :
के रूप में में विस्तार से बताया इस जवाब , माइक्रोसॉफ्ट का नया नाम दिया std::snprintf
करने के लिए _snprintf
(हाँ, बिना std::
)। एमएस आगे इसे पदावनत के रूप में सेट करता है और _snprintf_s
इसके बजाय उपयोग करने की सलाह देता है , हालांकि _snprintf_s
बफर को स्वरूपित आउटपुट से शून्य या छोटा होने के लिए स्वीकार नहीं करेगा और ऐसा होने पर आउटपुट लंबाई की गणना नहीं करेगा। इसलिए संकलन के दौरान पदावनति चेतावनियों से छुटकारा पाने के लिए, आप फ़ाइल के शीर्ष पर निम्न पंक्ति सम्मिलित कर सकते हैं जिसमें निम्न का उपयोग होता है _snprintf
:
#pragma warning(disable : 4996)
अंतिम विचार
इस प्रश्न के बहुत सारे उत्तर C ++ 11 के समय से पहले लिखे गए थे और निश्चित बफर लंबाई या वेरिएग का उपयोग करते थे। जब तक आप C ++ के पुराने संस्करणों के साथ फंस नहीं जाते, मैं उन समाधानों का उपयोग करने की अनुशंसा नहीं करता। आदर्श रूप से, C ++ 20 तरीका जाना।
क्योंकि इस उत्तर में C ++ 11 समाधान टेम्प्लेट का उपयोग करता है, यह बहुत अधिक कोड उत्पन्न कर सकता है यदि यह बहुत अधिक उपयोग किया जाता है। हालाँकि, जब तक आप बायनेरिज़ के लिए बहुत सीमित स्थान वाले वातावरण के लिए विकसित नहीं कर रहे हैं, यह एक समस्या नहीं होगी और यह अभी भी स्पष्टता और सुरक्षा दोनों में अन्य समाधानों पर एक बड़ा सुधार है।
यदि अंतरिक्ष दक्षता सुपर महत्वपूर्ण है, तो इन दो समाधानों के साथ vargs और vsnprintf उपयोगी हो सकते हैं।
निश्चित बफर लंबाई के साथ किसी भी समाधान का उपयोग न करें , वह सिर्फ परेशानी के लिए पूछ रहा है।
boost::format
(जैसा कि kennytm का समाधान यहां उपयोग करता है )।boost::format
पहले से ही C ++ स्ट्रीम ऑपरेटर्स को भी सपोर्ट करता है! उदाहरण:cout << format("helloworld. a=%s, b=%s, c=%s") % 123 % 123.123 % "this is a test" << endl;
।boost::format
कोड की कम से कम पंक्तियाँ हैं ... सहकर्मी की समीक्षा की गई है और सी ++ धाराओं के साथ अच्छी तरह से एकीकृत करता है।