c++ - Std:: string को const char*या char*में कैसे परिवर्तित करें?




(6)

मैं एक std::string को char* या एक const char* कैसे परिवर्तित कर सकता हूं?


सी ++ 17

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

charT* data() noexcept;

रिटर्न: एक पॉइंटर पी जैसे कि मैं प्रत्येक के लिए पी + i == और ऑपरेटर [0, आकार ()] में हूं।

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>

सी ++ 11 से आगे, मानक कहता है:

  1. एक basic_string ऑब्जेक्ट में चार जैसी ऑब्जेक्ट्स को basic_string रूप से संग्रहीत किया जाएगा। यही है, किसी भी basic_string ऑब्जेक्ट के लिए, पहचान &*(s.begin() + n) == &*s.begin() + 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) प्रत्येक के लिए [0,size()]

एक गैर कॉन्स चरित्र सूचक प्राप्त करने के लिए अलग-अलग संभावित तरीके हैं।

1. सी ++ 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;
}

समर्थक

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

चोर

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

इसे इस्तेमाल करे

std::string s(reinterpret_cast<const char *>(Data), Size);

बस इसे देखें:

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

हालांकि, ध्यान दें कि यह एक const char * लिए एक char * लौटाएगा, इसे किसी अन्य char सरणी में कॉपी करने के लिए strcpy का उपयोग करें।


मैं एक एपीआई के साथ काम कर रहा हूं जिसमें कई कार्यों को एक इनपुट char* रूप में मिलता है।

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

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 कॉपी करने DeepString नहीं है)।


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

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

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

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


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





const