एक std :: string को const char * या char * में कैसे बदलें?


893

मैं std::stringa char*या a को कैसे बदल सकता हूं const char*?


2
इसके बजाय: char * writable = new char [str.size () + 1]; आप char writable [str.size () + 1] का उपयोग कर सकते हैं; फिर आपको लिखने योग्य या अपवाद को हटाने के बारे में चिंता करने की आवश्यकता नहीं है।

7
आप str.size () का उपयोग नहीं कर सकते, जब तक कि आकार को संकलन समय पर नहीं जाना जाता है, तब भी यह आपके स्टैक को ओवरफ्लो कर सकता है यदि निश्चित आकार का मूल्य बहुत बड़ा है।
पॉलम

1
char * result = strcpy ((char *) malloc (str.length () + 1), str.c_str ());
सीगप्रकाश

7
@cegprakash strcpyऔर mallocवास्तव में C ++ तरीका नहीं है।
बॉयसी

4
नहीं, लेकिन char* dest = new char[str.length() + 1]; std::copy(str.begin(), str.end(), dest)अधिक मुहावरेदार C ++ होगा। strcpy()और malloc()गलत या समस्याग्रस्त नहीं हैं, लेकिन कोड के समान ब्लॉक में C ++ समकक्षों के साथ C ++ स्ट्रिंग और C लाइब्रेरी सुविधाओं का उपयोग करना असंगत लगता है।
लड़का

जवाबों:


1055

यदि आप केवल std::stringएक फ़ंक्शन को पास करना चाहते हैं जो const char*आपको उपयोग करने की आवश्यकता है

std::string str;
const char * c = str.c_str();

यदि आप एक योग्य प्रतिलिपि प्राप्त करना चाहते हैं, जैसे char *, आप इसके साथ ऐसा कर सकते हैं:

std::string str;
char * writable = new char[str.size() + 1];
std::copy(str.begin(), str.end(), writable);
writable[str.size()] = '\0'; // don't forget the terminating 0

// don't forget to free the string after finished using it
delete[] writable;

संपादित करें : ध्यान दें कि उपरोक्त अपवाद सुरक्षित नहीं है। यदि newकॉल और कॉल के बीच कुछ भी deleteफेंकता है, तो आप मेमोरी को लीक कर देंगे, क्योंकि कुछ भी deleteआपके लिए स्वचालित रूप से कॉल नहीं करेगा । इसे हल करने के दो तात्कालिक तरीके हैं।

बढ़ावा :: scoped_array

boost::scoped_array दायरे से बाहर जाने पर आपके लिए मेमोरी को हटा देगा:

std::string str;
boost::scoped_array<char> writable(new char[str.size() + 1]);
std::copy(str.begin(), str.end(), writable.get());
writable[str.size()] = '\0'; // don't forget the terminating 0

// get the char* using writable.get()

// memory is automatically freed if the smart pointer goes 
// out of scope

std :: वेक्टर

यह मानक तरीका है (किसी बाहरी पुस्तकालय की आवश्यकता नहीं है)। आप उपयोग करते हैं std::vector, जो आपके लिए मेमोरी को पूरी तरह से प्रबंधित करता है।

std::string str;
std::vector<char> writable(str.begin(), str.end());
writable.push_back('\0');

// get the char* using &writable[0] or &*writable.begin()

41
सीधे शब्दों में char * result = strdup (str.c_str ()) का उपयोग करें;
जैस्पर बेकर्स

63
आप कर सकते हैं, लेकिन स्ट्रैडअप एसी या सी ++ मानक फ़ंक्शन नहीं है, यह पॉज़िक्स से है :)
जोहान्स स्काउब -

14
मैं आमतौर पर क्या पसंद करूँगा std :: वेक्टर <char> writable (str.begin (), str.end ()); writable.push_back ( '\ 0'); char * c = & writable [0];
जोहान्स शहाब -

17
std :: copy यह ऐसा करने का c ++ तरीका है, जो स्ट्रिंग पॉइंटर पर मिलने की आवश्यकता के बिना है। मैं सी फ़ंक्शंस का उपयोग करने से बचने की कोशिश करता हूं जितना मैं कर सकता हूं।
जोहान्स शहाब -

16
C ++ 17 के अनुसार, std::string::data()अब a के CharT*बजाय रिटर्न देता है const CharT*। इस उत्तर को अद्यतन करना एक अच्छा विचार हो सकता है :)
Rakete1111

192

कहते हैं ...

std::string x = "hello";

एक `स्ट्रिंग` से` चार * `या` कास्ट चार * `प्राप्त करना

वर्ण पॉइंटर कैसे प्राप्त करें जो कि xदायरे में रहते हुए मान्य है और आगे संशोधित नहीं किया गया है

सी ++ 11 चीजों को सरल करता है; निम्नलिखित सभी एक ही आंतरिक स्ट्रिंग बफर तक पहुंच प्रदान करते हैं:

const char* p_c_str = x.c_str();
const char* p_data  = x.data();
char* p_writable_data = x.data(); // for non-const x from C++17 
const char* p_x0    = &x[0];

      char* p_x0_rw = &x[0];  // compiles iff x is not const...

उपरोक्त सभी संकेत एक ही मान रखेंगे - बफर में पहले वर्ण का पता। यहां तक ​​कि एक खाली स्ट्रिंग में "बफर में पहला चरित्र" होता है, क्योंकि C ++ 11 हमेशा एक अतिरिक्त NUL / 0 टर्मिनेटर वर्ण को स्पष्ट रूप से निर्दिष्ट स्ट्रिंग सामग्री (जैसे std::string("this\0that", 9)बफर होल्डिंग होगा "this\0that\0") के बाद रखने की गारंटी देता है ।

उपरोक्त किसी भी बिंदु को देखते हुए:

char c = p[n];   // valid for n <= x.size()
                 // i.e. you can safely read the NUL at p[x.size()]

केवल गैर- constपॉइंटर p_writable_dataऔर से के लिए &x[0]:

p_writable_data[n] = c;
p_x0_rw[n] = c;  // valid for n <= x.size() - 1
                 // i.e. don't overwrite the implementation maintained NUL

स्ट्रिंग में कहीं और NUL लिखने से 's' नहीं बदलता है ; किसी भी संख्या में NUL को सम्‍मिलित करने की अनुमति है - उन्हें कोई विशेष उपचार नहीं दिया जाता है (उसी C ++ 03 में)।stringsize()stringstd::string

में सी ++ 03 , चीजें काफी अधिक जटिल थे (मुख्य अंतर पर प्रकाश डाला ):

  • x.data()

    • const char*स्ट्रिंग के आंतरिक बफ़र पर लौटता है जिसे एनयूएल के साथ समाप्त करने के लिए मानक द्वारा आवश्यक नहीं था (यानी ['h', 'e', 'l', 'l', 'o']अनधिकृत या कचरा मूल्यों के साथ हो सकता है , आकस्मिक पहुंच के साथ अपरिभाषित व्यवहार होता है )।
      • x.size()वर्णों को पढ़ने के सुरक्षित हैं, यानी x[0]के माध्यम सेx[x.size() - 1]
      • खाली स्ट्रिंग्स के लिए, आपको कुछ गैर-NULL पॉइंटर की गारंटी दी जाती है, जिसमें 0 को सुरक्षित रूप से जोड़ा जा सकता है (hurray!), लेकिन आपको उस पॉइंटर को डिरेल नहीं करना चाहिए।
  • &x[0]

    • खाली तारों के लिए इसका अपरिभाषित व्यवहार है (21.3.4)
      • उदाहरण के लिए, f(const char* p, size_t n) { if (n == 0) return; ...whatever... }आपको f(&x[0], x.size());तब कॉल नहीं करना चाहिए जब x.empty()- बस उपयोग करें f(x.data(), ...)
    • अन्यथा, x.data()लेकिन प्रति के रूप में :
      • गैर के लिए - const xयह एक गैर- const char*सूचक देता है; आप स्ट्रिंग सामग्री को अधिलेखित कर सकते हैं
  • x.c_str()

    • रिटर्न const char*एक ASCIIZ को (NUL-समाप्त) मूल्य का प्रतिनिधित्व (यानी [ 'ज', 'ई', 'एल', 'एल', 'ओ', '\ 0'])।
    • हालांकि कुछ यदि कोई कार्यान्वयन ऐसा करने के लिए चुना है, सी ++ 03 स्टैंडर्ड स्ट्रिंग कार्यान्वयन एक बनाने की स्वतंत्रता दे करने के लिए शब्दों में किया गया था अलग NUL-समाप्त बफर मक्खी पर , संभावित गैर NUL से बफर द्वारा "उजागर" समाप्त x.data()और&x[0]
    • x.size() + 1 वर्ण पढ़ने के लिए सुरक्षित हैं।
    • खाली स्ट्रिंग्स (['0']) के लिए भी सुरक्षित गारंटी।

कानूनी सूचकांकों के बाहर पहुँचने के परिणाम

जिस भी तरह से आपको एक पॉइंटर मिलता है, आपको पॉइंटर से आगे मेमोरी की एक्सेस नहीं करनी चाहिए। ऐसा करने के प्रयासों में अपरिभाषित व्यवहार होता है , आवेदन के दुर्घटनाओं और कचरे के परिणामों की बहुत वास्तविक संभावना के साथ, यहां तक ​​कि रीड के लिए, और इसके अतिरिक्त थोक डेटा, स्टैक भ्रष्टाचार और / या सुरक्षा कमजोरियों के लिए लिखते हैं।

उन बिंदुओं को कब अमान्य किया जाता है?

यदि आप कुछ stringसदस्य फ़ंक्शन को कॉल करते हैं, जो stringआगे की क्षमता को संशोधित करता है या सुरक्षित रखता है, तो उपरोक्त तरीकों में से किसी भी तरीके से पहले से लौटाए गए कोई भी पॉइंटर मान अमान्य हैं । आप अन्य पॉइंटर प्राप्त करने के लिए उन विधियों का फिर से उपयोग कर सकते हैं। (नियम पुनरावृत्तियों के लिए समान हैं string)।

यह भी देखें कि xपत्तियों के दायरे के बाद भी वर्ण सूचक को कैसे मान्य किया जाए या नीचे और संशोधित किया जाए ...।

तो, कौन सा उपयोग करना बेहतर है?

C ++ 11 से, .c_str()ASCIIZ डेटा के लिए, और .data()"बाइनरी" डेटा के लिए उपयोग करें (नीचे और नीचे समझाया गया है)।

सी ++ 03 में, उपयोग .c_str()जब तक निश्चित है कि .data()पर्याप्त है, और पसंद करते हैं .data()अधिक &x[0]के रूप में यह रिक्त स्ट्रिंग के लिए सुरक्षित है ....

... data()उचित होने पर उपयोग करने के लिए प्रोग्राम को समझने की कोशिश करें , या आप शायद अन्य गलतियाँ करेंगे ...

ASCII NUL '0' वर्ण की गारंटी .c_str()प्रासंगिक और सुरक्षित करने के लिए उपयोग डेटा के अंत denoting एक प्रहरी मूल्य के रूप में कई कार्यों द्वारा किया जाता है। यह C ++ दोनों पर लागू होता है - केवल फ़ंक्शन fstream::fstream(const char* filename, ...)और साझा-के-सी फ़ंक्शन जैसे कार्य करता है strchr(), और printf()

दिए .c_str()गए बफर के बारे में सी ++ 03 की गारंटी देता है कि यह एक सुपर-सेट है .data(), आप हमेशा सुरक्षित रूप से उपयोग कर सकते हैं .c_str(), लेकिन लोग इसे पसंद नहीं करते हैं:

  • .data()स्रोत कोड को पढ़ने वाले अन्य प्रोग्रामर को संचार का उपयोग करते हुए कि डेटा ASCIIZ नहीं है (बल्कि, आप स्ट्रिंग का उपयोग डेटा के एक ब्लॉक को स्टोर करने के लिए कर रहे हैं (जो कभी-कभी सच में शाब्दिक नहीं है)), या कि आप इसे पास कर रहे हैं एक अन्य फ़ंक्शन जो इसे "बाइनरी" डेटा के ब्लॉक के रूप में मानता है। यह सुनिश्चित करने में एक महत्वपूर्ण अंतर्दृष्टि हो सकती है कि अन्य प्रोग्रामर के कोड परिवर्तन डेटा को ठीक से संभालना जारी रखें।
  • C ++ 03 केवल: इस बात की थोड़ी संभावना है कि आपके stringकार्यान्वयन को NUL समाप्त बफर तैयार करने के लिए कुछ अतिरिक्त मेमोरी आवंटन और / या डेटा कॉपी करने की आवश्यकता होगी।

एक और संकेत के रूप में, यदि किसी फ़ंक्शन के मापदंडों की आवश्यकता होती है ( const), char*लेकिन प्राप्त करने पर जोर नहीं देते हैं x.size(), तो फ़ंक्शन को संभवतः ASCIIZ इनपुट की आवश्यकता होती है, इसलिए .c_str()एक अच्छा विकल्प है (फ़ंक्शन को यह जानने की आवश्यकता है कि पाठ किसी तरह कहां समाप्त होता है, इसलिए यदि यह नहीं है एक अलग पैरामीटर यह केवल एक लंबाई-उपसर्ग या प्रहरी या कुछ निश्चित अपेक्षित लंबाई की तरह एक सम्मेलन हो सकता है)।

xपत्तियों के दायरे के बाद भी वर्ण सूचक को कैसे मान्य किया जाए या आगे संशोधित किया जाए

आपको बाहर एक नए मेमोरी क्षेत्र की सामग्री को कॉपी करना होगा । यह बाहरी बफ़र कई स्थानों पर हो सकता है जैसे कि कोई अन्य या वर्ण सरणी चर, यह एक अलग दायरे में होने के कारण एक अलग जीवनकाल हो सकता है या नहीं हो सकता है (जैसे नाम स्थान, वैश्विक, स्थिर, हीप, साझा मेमोरी, मेमोरी मैप्ड फ़ाइल) ।string xxstringx

पाठ std::string xको एक स्वतंत्र वर्ण सरणी से कॉपी करने के लिए :

// USING ANOTHER STRING - AUTO MEMORY MANAGEMENT, EXCEPTION SAFE
std::string old_x = x;
// - old_x will not be affected by subsequent modifications to x...
// - you can use `&old_x[0]` to get a writable char* to old_x's textual content
// - you can use resize() to reduce/expand the string
//   - resizing isn't possible from within a function passed only the char* address

std::string old_x = x.c_str(); // old_x will terminate early if x embeds NUL
// Copies ASCIIZ data but could be less efficient as it needs to scan memory to
// find the NUL terminator indicating string length before allocating that amount
// of memory to copy into, or more efficient if it ends up allocating/copying a
// lot less content.
// Example, x == "ab\0cd" -> old_x == "ab".

// USING A VECTOR OF CHAR - AUTO, EXCEPTION SAFE, HINTS AT BINARY CONTENT, GUARANTEED CONTIGUOUS EVEN IN C++03
std::vector<char> old_x(x.data(), x.data() + x.size());       // without the NUL
std::vector<char> old_x(x.c_str(), x.c_str() + x.size() + 1);  // with the NUL

// USING STACK WHERE MAXIMUM SIZE OF x IS KNOWN TO BE COMPILE-TIME CONSTANT "N"
// (a bit dangerous, as "known" things are sometimes wrong and often become wrong)
char y[N + 1];
strcpy(y, x.c_str());

// USING STACK WHERE UNEXPECTEDLY LONG x IS TRUNCATED (e.g. Hello\0->Hel\0)
char y[N + 1];
strncpy(y, x.c_str(), N);  // copy at most N, zero-padding if shorter
y[N] = '\0';               // ensure NUL terminated

// USING THE STACK TO HANDLE x OF UNKNOWN (BUT SANE) LENGTH
char* y = alloca(x.size() + 1);
strcpy(y, x.c_str());

// USING THE STACK TO HANDLE x OF UNKNOWN LENGTH (NON-STANDARD GCC EXTENSION)
char y[x.size() + 1];
strcpy(y, x.c_str());

// USING new/delete HEAP MEMORY, MANUAL DEALLOC, NO INHERENT EXCEPTION SAFETY
char* y = new char[x.size() + 1];
strcpy(y, x.c_str());
//     or as a one-liner: char* y = strcpy(new char[x.size() + 1], x.c_str());
// use y...
delete[] y; // make sure no break, return, throw or branching bypasses this

// USING new/delete HEAP MEMORY, SMART POINTER DEALLOCATION, EXCEPTION SAFE
// see boost shared_array usage in Johannes Schaub's answer

// USING malloc/free HEAP MEMORY, MANUAL DEALLOC, NO INHERENT EXCEPTION SAFETY
char* y = strdup(x.c_str());
// use y...
free(y);

char*या से const char*उत्पन्न होने के लिए अन्य कारणstring

तो, ऊपर आपने देखा है कि मूल ( const) से char*स्वतंत्र पाठ की प्रतिलिपि कैसे बनाई जाती है string, लेकिन आप इसके बारे में क्या कर सकते हैं ? उदाहरणों का एक बेतरतीब ख़ुशामद ...

  • "C" कोड को C ++ stringके टेक्स्ट तक पहुँच दें , जैसे किprintf("x is '%s'", x.c_str());
  • xअपने फ़ंक्शन के कॉलर (उदाहरण strncpy(callers_buffer, callers_buffer_size, x.c_str())), या डिवाइस I / O (जैसे for (const char* p = x.c_str(); *p; ++p) *p_device = *p;) के लिए उपयोग की जाने वाली वाष्पशील मेमोरी द्वारा निर्दिष्ट बफ़र पर पाठ की प्रतिलिपि बनाएँ
  • संलग्न xएक चरित्र सरणी के पाठ पहले से ही कुछ ASCIIZ पाठ (जैसे युक्त strcat(other_buffer, x.c_str())) - बफर लंघन के प्रति सावधान रहें (कई स्थितियों में आप उपयोग करना पड़ सकता है strncat)
  • एक वापसी const char*या char*एक समारोह से (ऐतिहासिक कारणों से शायद - ग्राहक के अपने मौजूदा एपीआई का उपयोग कर - या सी अनुकूलता के लिए आप एक वापस जाने के लिए नहीं करना चाहते हैं std::string, लेकिन अपने नकल करना चाहते हैं stringफोन करने वाले के लिए के डेटा कहीं)
    • एक पॉइंटर को वापस न करने के लिए सावधान रहें stringजो एक स्थानीय चर के बाद कॉल करने वाले द्वारा डिरेल्ड हो सकता है, जिसमें उस पॉइंटर ने बाएं स्कोप को छोड़ दिया है
    • अलग-अलग std::stringकार्यान्वयन के लिए संकलित / साझा की गई साझा वस्तुओं के साथ कुछ परियोजनाएं (जैसे STLport और संकलक-मूल) संघर्षों से बचने के लिए ASCIIZ के रूप में डेटा पारित कर सकती हैं।

4
अच्छा है। चार * (नॉन कास्ट) चाहने का एक और कारण एमपीआई प्रसारण के साथ काम करना है। यह अच्छा लग रहा है अगर आपको आगे और पीछे की नकल नहीं करनी है। मैंने व्यक्तिगत रूप से स्ट्रिंग के लिए एक चार * कॉन्स्टेंट गेट्टर की पेशकश की होगी। कास्ट पॉइंटर, लेकिन संपादन योग्य स्ट्रिंग। हालांकि यह
कास्ट

33

के लिए .c_str()विधि का प्रयोग करें const char *

आप &mystring[0]एक char *पॉइंटर प्राप्त करने के लिए उपयोग कर सकते हैं , लेकिन एक जोड़ी है गोचा: आपको आवश्यक रूप से एक शून्य समाप्त स्ट्रिंग नहीं मिलेगा, और आप स्ट्रिंग के आकार को बदलने में सक्षम नहीं होंगे। आपको विशेष रूप से सावधान रहना होगा कि स्ट्रिंग के अंत में वर्णों को न जोड़ें या आपको एक बफर ओवररन (और संभावित दुर्घटना) मिलेगा।

इस बात की कोई गारंटी नहीं थी कि सभी पात्र C ++ 11 तक एक ही सन्निहित बफर का हिस्सा होंगे, लेकिन व्यवहार में std::stringवैसे भी काम करने वाले सभी ज्ञात कार्यान्वयन ; देखें "& s [0]" एक std :: string में सन्निहित पात्रों को इंगित करता है?

ध्यान दें कि कई stringसदस्य फ़ंक्शंस आंतरिक बफर को फिर से व्यवस्थित करेंगे और आपके द्वारा सहेजे गए किसी भी संकेत को अमान्य कर देंगे। उन्हें तुरंत उपयोग करने और फिर त्यागने के लिए सर्वश्रेष्ठ।


1
आपको ध्यान देना चाहिए कि डेटा () रिटर्न कास्ट चार * :) आपका मतलब क्या है & str [0], जो एक सन्निहित रिटर्न देता है, लेकिन नेकसरी शून्य समाप्त स्ट्रिंग नहीं।
जोहान्स शाउब -

1
@litb, अर्घ! यही मुझे एक त्वरित उत्तर कोड़ा मारने की कोशिश के लिए मिलता है। मैंने अतीत में आपके समाधान का उपयोग किया है, पता नहीं क्यों यह पहली बात नहीं थी जो दिमाग में आई थी। मैंने अपना उत्तर संपादित कर दिया है।
मार्क रैनसम 19

2
तकनीकी रूप से, std :: string स्टोरेज केवल C ++ 0x में सन्निहित होगा।
MSALERS

1
@MSalters, धन्यवाद - मुझे नहीं पता था। मैं एक कार्यान्वयन को खोजने के लिए कड़ी मेहनत करूँगा जहाँ यह मामला नहीं था, हालाँकि।
मार्क रैनसम

2
char * result = strcpy (malloc (str.length () + 1), str.c_str ());
सीगप्रकाश

21

सी ++ 17

C ++ 17 (आगामी मानक) basic_stringएक गैर कॉन्स्टेबल अधिभार जोड़ने वाले टेम्पलेट के सिनॉप्सिस को बदल देता है data():

charT* data() noexcept;

रिटर्न: एक पॉइंटर पी ऐसा कि p + i == & ऑपरेटर के लिए प्रत्येक i [0, size ()] में।


CharT const * से std::basic_string<CharT>

std::string const cstr = { "..." };
char const * p = cstr.data(); // or .c_str()

CharT * से std::basic_string<CharT>

std::string str = { "..." };
char * p = str.data();

सी ++ 11

CharT const * से std::basic_string<CharT>

std::string str = { "..." };
str.c_str();

CharT * से std::basic_string<CharT>

C ++ 11 से, मानक कहता है:

  1. किसी basic_stringऑब्जेक्ट में चार जैसी वस्तुओं को संचित रूप से संग्रहीत किया जाएगा। है यही कारण है, किसी के लिए basic_stringवस्तु s, पहचान &*(s.begin() + n) == &*s.begin() + nके सभी मानों के लिए पकड़ करेगा nऐसी है कि 0 <= n < s.size()

  1. const_reference operator[](size_type pos) const;
    reference operator[](size_type pos);

    रिटर्न: *(begin() + pos)यदि pos < size(), अन्यथा CharTमूल्य के साथ प्रकार की वस्तु का संदर्भ CharT(); संदर्भित मूल्य को संशोधित नहीं किया जाएगा।


  1. const charT* c_str() const noexcept;
    const charT* data() const noexcept;

    रिटर्न: एक पॉइंटर पी ऐसा जिसमें p + i == &operator[](i)प्रत्येक iके लिए[0,size()]

नॉन कास्ट कैरेक्टर पॉइंटर पाने के लिए गंभीर संभव तरीके हैं।

1. C ++ 11 के सन्निहित भंडारण का उपयोग करें

std::string foo{"text"};
auto p = &*foo.begin();

समर्थक

  • सरल और छोटा
  • फास्ट (केवल एक प्रतिलिपि के साथ विधि)

विपक्ष

  • अंतिम '\0' को गैर-कांस्टेबल मेमोरी का हिस्सा नहीं बदलना / जरूरी नहीं है।

2. उपयोग करें std::vector<CharT>

std::string foo{"text"};
std::vector<char> fcv(foo.data(), foo.data()+foo.size()+1u);
auto p = fcv.data();

समर्थक

  • सरल
  • स्वचालित मेमोरी हैंडलिंग
  • गतिशील

विपक्ष

  • स्ट्रिंग कॉपी की आवश्यकता है

3. std::array<CharT, N>यदि Nसंकलित समय स्थिर है (और पर्याप्त छोटा) का उपयोग करें

std::string foo{"text"};
std::array<char, 5u> fca;
std::copy(foo.data(), foo.data()+foo.size()+1u, fca.begin());

समर्थक

  • सरल
  • स्टैक मेमोरी हैंडलिंग

विपक्ष

  • स्थिर
  • स्ट्रिंग कॉपी की आवश्यकता है

4. स्वचालित भंडारण विलोपन के साथ कच्चा मेमोरी आवंटन

std::string foo{ "text" };
auto p = std::make_unique<char[]>(foo.size()+1u);
std::copy(foo.data(), foo.data() + foo.size() + 1u, &p[0]);

समर्थक

  • छोटे स्मृति पदचिह्न
  • स्वचालित विलोपन
  • सरल

विपक्ष

  • स्ट्रिंग कॉपी की आवश्यकता है
  • स्थैतिक (गतिशील उपयोग के लिए बहुत अधिक कोड की आवश्यकता होती है)
  • वेक्टर या सरणी से कम सुविधाएँ

5. मैनुअल हैंडलिंग के साथ रॉ मेमोरी आवंटन

std::string foo{ "text" };
char * p = nullptr;
try
{
  p = new char[foo.size() + 1u];
  std::copy(foo.data(), foo.data() + foo.size() + 1u, p);
  // handle stuff with p
  delete[] p;
}
catch (...)
{
  if (p) { delete[] p; }
  throw;
}

समर्थक

  • अधिकतम 'नियंत्रण'

चोर

  • स्ट्रिंग कॉपी की आवश्यकता है
  • त्रुटियों के लिए अधिकतम देयता / संवेदनशीलता
  • जटिल

9

मैं एक एपीआई के साथ काम कर रहा हूं जिसमें बहुत सारे फ़ंक्शन इनपुट के रूप में मिलते हैं char*

मैंने इस तरह की समस्या का सामना करने के लिए एक छोटा वर्ग बनाया है, मैंने RAII मुहावरा लागू किया है।

class DeepString
{
        DeepString(const DeepString& other);
        DeepString& operator=(const DeepString& other);
        char* internal_; 

    public:
        explicit DeepString( const string& toCopy): 
            internal_(new char[toCopy.size()+1]) 
        {
            strcpy(internal_,toCopy.c_str());
        }
        ~DeepString() { delete[] internal_; }
        char* str() const { return internal_; }
        const char* c_str()  const { return internal_; }
};

और आप इसका उपयोग कर सकते हैं:

void aFunctionAPI(char* input);

//  other stuff

aFunctionAPI("Foo"); //this call is not safe. if the function modified the 
                     //literal string the program will crash
std::string myFoo("Foo");
aFunctionAPI(myFoo.c_str()); //this is not compiling
aFunctionAPI(const_cast<char*>(myFoo.c_str())); //this is not safe std::string 
                                                //implement reference counting and 
                                                //it may change the value of other
                                                //strings as well.
DeepString myDeepFoo(myFoo);
aFunctionAPI(myFoo.str()); //this is fine

मैंने कक्षा को बुलाया है DeepStringक्योंकि यह DeepStringएक मौजूदा स्ट्रिंग की गहरी और अनोखी प्रतिलिपि (प्रतिलिपि नहीं है) बना रही है।


3
मैं इस नामकरण सम्मेलन से बचूंगा। c_str()जैसा कि std"सी-स्ट्रिंग" नहीं "कास्ट स्ट्रिंग" के लिए एक संक्षिप्त नाम है और str()हमेशा एक रिटर्न देता है std::basic_string, नहीं char*(उदाहरण के लिए std::stringstream::str())
bcrist 5'15

8
char* result = strcpy((char*)malloc(str.length()+1), str.c_str());

1
फैंसी लग रहा है, लेकिन समझने में मुश्किल है ... सरल सबसे अच्छा IMO है
नईम ए मलिक

4
strcpy (), मॉलोक (), लंबाई () और c_str () बुनियादी कार्य हैं और इसमें कुछ भी मुश्किल नहीं है। बस मेमोरी और कॉपी आवंटित करना।
सीगप्रकाश

5
हाँ फ़ंक्शंस बेसिक हैं, लेकिन आपने उन्हें घुमाया और उन्हें स्पेगेटी या एक लाइनर फ्रेंकस्टीन के राक्षस की तरह दिखने के लिए झुका दिया :)
नईम ए मलिक

4
हां फ़ंक्शंस बुनियादी हैं, लेकिन क्या आपको याद है कि जब आप एक प्रोग्रामिंग भाषा से निपटना शुरू करते हैं? समझाने के लिए कुछ पंक्तियाँ और यह वास्तव में यह जानने के लिए एक
नवजात शिशु की

2
@cegprakash: जब भी कोई मॉलोक () होता है, वहाँ भी एक फ्री () होना होता है। अन्यथा कोड स्मृति को लीक करता है, और इसलिए आपके उत्तर में समाधान होता है। स्मृति को कम से कम आवश्यक सौदेबाजी के लिए आवंटित करना इस तरह के सवालों के लिए बुरा अभ्यास है।
स्ट्रीज़ेल

7

बस इसे देखें:

string str1("stackoverflow");
const char * str2 = str1.c_str();

हालाँकि, ध्यान दें कि यह वापस आ जाएगा const char *

A के लिए char *, strcpyइसे किसी अन्य charसरणी में कॉपी करने के लिए उपयोग करें ।


23
नमस्ते, जो आपने पोस्ट किया है वह पहले से ही कई बार कहा गया है, अधिक विवरण के साथ, 5 साल पुराने प्रश्न के अन्य उत्तर में। पुराने प्रश्नों का उत्तर देना ठीक है, लेकिन केवल तभी जब आप नई जानकारी जोड़ते हैं। अन्यथा, यह सिर्फ शोर है।
चटाई

7
निजी तौर पर, मैं सादगी की सराहना करता हूं।
टैंकरस्मैश

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.