কীভাবে একটি std :: স্ট্রিংকে কনস্ট চর * বা চর * তে রূপান্তর করবেন?


893

আমি কীভাবে একটিকে std::stringএকটি char*বা এ রূপান্তর করতে পারি const char*?


2
পরিবর্তে: চর * লিখনযোগ্য = নতুন চর [str.size () + 1]; আপনি লেখার জন্য লেখার [str.size () + 1] ব্যবহার করতে পারেন; তারপরে আপনার লেখার যোগ্য বা ব্যতিক্রম হ্যান্ডলিং মুছে ফেলার বিষয়ে চিন্তা করার দরকার নেই।

7
সংকলনের সময় আকারটি জানা না থাকলে আপনি স্ট্রাইস সাইজ () ব্যবহার করতে পারবেন না, যদি নির্দিষ্ট আকারের মানটি বিশাল হয় তবে এটি আপনার স্ট্যাককে উপচে ফেলতে পারে।
পলম

1
চর * ফলাফল = স্ট্রাইকপি ((চর *) ম্যালোক (স্ট্রাইলেথ () + 1), আরআর.সি._সেটর ());
সেগপ্রকাশ

7
@ এসিগপ্রকাশ strcpyএবং mallocআসলে সি ++ উপায় নয়।
বালক

4
না, তবে char* dest = new char[str.length() + 1]; std::copy(str.begin(), str.end(), dest)এটি আরও বেশি বুদ্ধিমান সি ++ হবে। strcpy()এবং malloc()ভুল বা সমস্যাযুক্ত নয়, তবে কোডের একই ব্লকে সি ++ সমতুল্য একটি সি ++ স্ট্রিং এবং সি লাইব্রেরি সুবিধা ব্যবহার করা অসঙ্গত বলে মনে হচ্ছে।
বালক

উত্তর:


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::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
কেবল চর * ফলাফল = স্টার্ডআপ (str.c_str ()) ব্যবহার করুন;
জ্যাস্পার বেকারস

63
আপনি পারতেন, তবে স্টার্ডআপ এসি বা সি ++ স্ট্যান্ডার্ড ফাংশন নয়, এটি
পিক্সিক্স

14
আমি সম্ভবত যা পছন্দ করি তা হ'ল std :: vector <char> Writable (str.begin (), str.end ()); writable.push_back ( '\ 0'); চর * সি = এবং লিখনযোগ্য [0];
জোহানেস স্কাউব -

17
স্ট্যান্ডিং :: অনুলিপিটি স্ট্রিং পয়েন্টারে বিনা প্রয়োজনে এটি করার সি ++ উপায়। আমি যতটা পারি সি ফাংশন ব্যবহার এড়াতে চেষ্টা করি।
জোহানেস স্কাউব -

16
সি ++ 17 হিসাবে std::string::data()এখন একটি এর CharT*পরিবর্তে একটি ফেরত দেয় const CharT*। এই উত্তরটি আপডেট করা ভাল ধারণা হতে পারে :)
Rakete1111

192

দেওয়া হয়েছে ...

std::string x = "hello";

একটি `স্ট্রিং` থেকে একটি` চর * `বা` কনস্ট চর * Get পান `

এমন একটি চরিত্রের পয়েন্টার কীভাবে পাওয়া যায় যা বৈধ অবস্থায় 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...

উপরের সমস্ত পয়েন্টার একই মান ধরে রাখবে - বাফারের প্রথম অক্ষরের ঠিকানা। এমনকি একটি খালি স্ট্রিংয়ের একটি "বাফারে প্রথম অক্ষর" রয়েছে, কারণ সি ++ 11 স্পষ্টরূপে বরাদ্দ স্ট্রিং সামগ্রীর (যেমন std::string("this\0that", 9)একটি বাফার হোল্ডিং থাকবে "this\0that\0") পরে সর্বদা অতিরিক্ত NUL / 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 লেখা নেই না পরিবর্তন stringএর size(); stringএর যেকোন সংখ্যক এন.এল.এস রাখার অনুমতি রয়েছে - তাদের দ্বারা কোনও বিশেষ চিকিত্সা দেওয়া হয় না std::string(সি ++ তে একই)।

ইন সি ++ 03 , জিনিষ যথেষ্ট আরো জটিল হয় (মূল পার্থক্য তুলে ধরেন ):

  • x.data()

    • const char*স্ট্রিংয়ের অভ্যন্তরীণ বাফারে ফিরে আসে যা কোনও স্ট্যান্ডার্ড দ্বারা একটি এনএলইউ দিয়ে শেষ করার প্রয়োজন ছিল না (অর্থাত্ সংজ্ঞাবিহীন['h', 'e', 'l', 'l', 'o'] বা আবর্জনা মানগুলি অনুসরণ করতে পারে , এতে দুর্ঘটনাজনিত প্রবেশাধিকার রয়েছে যার সাথে অপরিবর্তিত আচরণ রয়েছে )।
      • x.size()অক্ষরগুলি পড়ার জন্য নিরাপদ, অর্থাৎ x[0]মাধ্যমেx[x.size() - 1]
      • খালি স্ট্রিংয়ের জন্য, আপনাকে এমন কিছু নন-নুল পয়েন্টার গ্যারান্টিযুক্ত দেওয়া হয়েছে যেখানে 0 টি নিরাপদে যুক্ত করা যেতে পারে (হ্যারে!) তবে আপনাকে সেই পয়েন্টারটিকে অবহেলা করা উচিত নয়।
  • &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*মানটির (যেমন ['এইচ', 'ই', 'ল', 'ল', 'ও', '\ 0']) এর উপস্থাপনা একটি এসকিআইজেড (এনএলএল-টার্মিনেটেড) এ ফিরে আসে ।
    • যদিও খুব অল্প সংখ্যক বাস্তবায়নের তা করার জন্য নির্বাচন করেছেন, সি ++ 03 স্ট্যান্ডার্ড স্ট্রিং বাস্তবায়ন একটি তৈরি করতে স্বাধীনতা দানের কথা ভাষায় ছিল স্বতন্ত্র NUL-সমাপ্ত বাফার মাছি উপর , সম্ভাব্য অ NUL থেকে বাফার দ্বারা "উদ্ভাসিত" সমাপ্ত x.data()এবং&x[0]
    • x.size() + 1 টি অক্ষর পড়া নিরাপদ।
    • এমনকি ফাঁকা স্ট্রিংয়ের জন্য নিরাপদ গ্যারান্টিযুক্ত (['\ 0'])।

আইনী সূচকগুলির বাইরের অ্যাক্সেসের ফলাফল

আপনি যে কোনও উপায়ে পয়েন্টার পান, উপরের বর্ণনায় বর্ণিত গ্যারান্টিযুক্ত অক্ষরের চেয়ে আপনাকে অবশ্যই পয়েন্টারটির সাথে মেমরি অ্যাক্সেস করতে হবে না। এটি করার চেষ্টাগুলির সাথে অপরিজ্ঞাত আচরণ রয়েছে , প্রয়োগ পড়ার ক্ষেত্রে এমনকি ক্র্যাশ এবং আবর্জনার ফলাফলের খুব প্রকৃত সম্ভাবনা রয়েছে এবং অতিরিক্তভাবে পাইকারি তথ্য, লেখার জন্য দুর্নীতি এবং / বা সুরক্ষা দুর্বলতা রয়েছে।

এই পয়েন্টারগুলি কখন অবৈধ হয়?

আপনি যদি এমন কোনও stringসদস্য ফাংশন কল করেন যা পরিবর্তনের stringক্ষমতা বা আরও ক্ষমতা সংরক্ষণ করে, উপরের যে কোনও পদ্ধতি দ্বারা পূর্বে প্রত্যাবর্তিত কোনও পয়েন্টার মান বাতিল হয়ে যায় । অন্য পয়েন্টার পেতে আপনি আবার সেই পদ্ধতিগুলি ব্যবহার করতে পারেন। (নিয়মগুলি পুনরাবৃত্তকারীগুলির ক্ষেত্রে stringগুলি হিসাবে একই )

আরও দেখুন কিভাবে পরেও একটি অক্ষর পয়েন্টার বৈধ পেতে xপাতার সুযোগ বা আরও রুপান্তরিত করা হয়েছে নিচের ....

সুতরাং, কোনটি ব্যবহার করা ভাল ?

সি ++ 11 থেকে, .c_str()এসকিআইজেড ডেটা এবং .data()"বাইনারি" ডেটার জন্য (আরও নীচে ব্যাখ্যা করা হয়েছে) ব্যবহার করুন।

সি ++ 03 সালে, ব্যবহার .c_str()যদি না নিশ্চিত যে .data()পর্যাপ্ত, এবং পছন্দ .data()উপর &x[0]যেমন খালি স্ট্রিং জন্য নিরাপদ ....

... data()উপযুক্ত হলে প্রোগ্রামটি যথেষ্ট পরিমাণে বোঝার চেষ্টা করুন , বা আপনি সম্ভবত অন্যান্য ভুল করবেন ...

ASCII NUL '\ 0' অক্ষরটি গ্যারান্টীযুক্ত .c_str()অনেকগুলি ফাংশন দ্বারা প্রাসঙ্গিক মান হিসাবে প্রাসঙ্গিক এবং সুরক্ষিত থেকে অ্যাক্সেস ডেটার সমাপ্তি নির্দেশ করে used এটি সি ++ উভয়ের ক্ষেত্রেই প্রযোজ্য - কেবলমাত্র বলার মতো ফাংশনগুলি fstream::fstream(const char* filename, ...)এবং সি-এর মতো ভাগ করা-যেমন ফাংশন strchr()এবং printf()

.c_str()ফিরে আসা বাফার সম্পর্কে সি ++ 03 এর গ্যারান্টি দেওয়া হ'ল একটি সুপার সেট .data(), আপনি সর্বদা নিরাপদে ব্যবহার করতে পারেন .c_str()তবে লোকেরা কখনও কখনও তা করেন না:

  • .data()সোর্স কোডটি পড়ার জন্য অন্যান্য প্রোগ্রামারদের সাথে যোগাযোগ করে যে ডেটা ASCIIZ নয় (বরং, আপনি স্ট্রিংটি ডেটা ব্লক (যা কখনও কখনও এমনকি প্রকৃত পাঠ্যও হয় না) সংরক্ষণ করার জন্য ব্যবহার করছেন) বা আপনি এটিতে পাস করছেন অন্য ফাংশন যা এটিকে "বাইনারি" ডেটা ব্লক হিসাবে গণ্য করে। অন্যান্য প্রোগ্রামারদের কোড পরিবর্তনগুলি সঠিকভাবে ডেটা পরিচালনা করতে অব্যাহত রাখার ক্ষেত্রে এটি একটি গুরুত্বপূর্ণ অন্তর্দৃষ্টি হতে পারে।
  • কেবলমাত্র C ++ 03: আপনার stringবাস্তবায়নের জন্য NU টার্মিনেটেড বাফারটি প্রস্তুত করার জন্য কিছু অতিরিক্ত মেমরি বরাদ্দ এবং / অথবা ডেটা অনুলিপি করতে হবে এমন সামান্য সুযোগ রয়েছে there's

আরও একটি ইঙ্গিত হিসাবে, যদি কোনও ফাংশনটির প্যারামিটারগুলির প্রয়োজন হয় ( const) char*তবে পাওয়ার জন্য জোর করবেন না x.size(), ফাংশনটির সম্ভবত একটি এসকিআইজেড ইনপুট প্রয়োজন, তাই .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তবে আপনি এটি দিয়ে কী করতে পারেন ? উদাহরণগুলির এলোমেলো ছদ্মবেশ ...

  • "সি" কোডটিকে সি ++ 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*(সম্ভবত historicalতিহাসিক কারণে - ক্লায়েন্টের আপনার বিদ্যমান এপিআই ব্যবহার করছে - বা সি সামঞ্জস্যের জন্য আপনি কোনও ফিরে আসতে চান না std::string, তবে আপনার stringডেটা কলারের জন্য কোথাও অনুলিপি করতে চান )
    • স্থানীয় stringভেরিয়েবলের পরে যে পয়েন্টারটি পয়েন্টটি রেখে গেছে তার পরে কলার দ্বারা চিহ্নিত হওয়া পয়েন্টারটি না ফেরানোর জন্য সতর্ক থাকুন
    • বিভিন্ন std::stringবাস্তবায়নের জন্য সংযুক্ত / সংযুক্ত / যুক্ত লিঙ্কযুক্ত কিছু প্রকল্প (যেমন এসটিএলপোর্ট এবং সংকলক-নেটিভ) বিরোধগুলি এড়াতে ASCIIZ হিসাবে ডেটা পাস করতে পারে

4
সুন্দর. চর * (নন কনস্ট) চাওয়ার আরেকটি কারণ হ'ল এমপিআই সম্প্রচারের মাধ্যমে পরিচালনা করা। যদি আপনার পিছনে পিছনে অনুলিপি না করতে হয় তবে এটি দেখতে সুন্দর লাগছে। আমি ব্যক্তিগতভাবে স্ট্রিংয়ের জন্য একটি চর * কনস্টেটর গেটার অফার করতাম। কনস্ট পয়েন্টার, তবে সম্পাদনাযোগ্য স্ট্রিং। যদিও এটি
কনস্ট

33

এর .c_str()জন্য পদ্ধতিটি ব্যবহার করুন const char *

আপনি &mystring[0]একটি char *পয়েন্টার পেতে ব্যবহার করতে পারেন , তবে কয়েকটি গোটাছা রয়েছে: আপনি অগত্যা শূন্য সমাপ্ত স্ট্রিং পাবেন না এবং আপনি স্ট্রিংয়ের আকার পরিবর্তন করতে পারবেন না। আপনার বিশেষত সতর্কতা অবলম্বন করতে হবে যে স্ট্রিংটির শেষের শেষে অক্ষরগুলি যুক্ত না করা বা আপনি একটি বাফারকে ছাড়িয়ে যাবেন (এবং সম্ভাব্য ক্র্যাশ)।

গ্যারান্টি ছিল না যে সমস্ত চরিত্রগুলি সি ++ 11 অবধি একই মিলিত বাফারের অংশ হয়ে উঠবে, তবে বাস্তবে std::stringসেভাবে যাবতীয়ভাবে পরিচিত সমস্ত বাস্তবায়ন কার্যকর হয়েছিল ; দেখুন "& s [0]" একটি স্ট্যান্ড :: স্ট্রিংগুলিতে সংলগ্ন অক্ষরগুলিকে নির্দেশ করে?

নোট করুন যে অনেক stringসদস্যের ফাংশনগুলি অভ্যন্তরীণ বাফারটিকে পুনরায় প্রত্যাবর্তন করবে এবং আপনার সংরক্ষণ করা কোনও পয়েন্টারকে অকার্যকর করবে। এগুলি অবিলম্বে ব্যবহার করা এবং তারপরে বাতিল করা ভাল।


1
আপনার অবশ্যই লক্ষ্য করা উচিত যে ডেটা () কনস্ট চার্জ প্রদান করে * :) আপনি যা বোঝাতে চেয়েছেন তা হল & str [0], যা প্রত্যাশিত, তবে নেসেসারি নাল টার্মিনেটেড স্ট্রিংকে দেয় না।
জোহানেস স্কাউব -

1
@ লিটব, আরগ! একটি দ্রুত উত্তর বেতার চেষ্টা করার জন্য আমি এটি পেয়েছি। আমি আপনার সমাধানটি অতীতে ব্যবহার করেছি, কেন জানি না কেন এটি প্রথম জিনিস মনে আসেনি। আমি আমার উত্তর সম্পাদনা করেছি।
মার্ক মুক্তিদান

2
প্রযুক্তিগতভাবে, স্ট্যান্ড :: স্ট্রিং স্টোরেজটি কেবল সি ++ 0 এক্স-এর সাথে মিলবে।
এমএসএলটাররা

1
@ এসএমএলটাররা, ধন্যবাদ - আমি এটি জানতাম না। যদিও এমন পরিস্থিতি ছিল না এমন বাস্তবায়ন খুঁজে পেতে আমাকে কঠোর চাপ দেওয়া হবে।
মার্ক রান্সম

2
চর * ফলাফল = স্ট্রিপিপি (ম্যালোক (স্ট্রাইলেথ () + 1), আরআর।
সেগপ্রকাশ

21

সি ++ 17

সি ++ 17 (আগত মান) টেমপ্লেটের সংক্ষিপ্তসারকে basic_stringএকটি অবিচ্ছিন্ন ওভারলোড যুক্ত করে data():

charT* data() noexcept;

রিটার্নস: প্রতিটি পয়েন্টের জন্য [+, আকার ()] এর জন্য পি + আই == এবং অপারেটর হিসাবে একটি পয়েন্টার পি।


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বস্তুর জন্য 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. সি ++ 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());

স্বপক্ষে

  • সহজ
  • স্ট্যাক মেমরি হ্যান্ডলিং

কনস

  • স্থির
  • স্ট্রিং কপি প্রয়োজন

৪. স্বয়ংক্রিয় স্টোরেজ মোছার সাথে কাঁচা মেমরির বরাদ্দ

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

স্বপক্ষে

  • ছোট স্মৃতি পায়ের ছাপ
  • স্বয়ংক্রিয়ভাবে মোছা
  • সহজ

কনস

  • স্ট্রিং কপি প্রয়োজন
  • স্ট্যাটিক (গতিশীল ব্যবহারের জন্য আরও অনেক কোডের প্রয়োজন)
  • ভেক্টর বা অ্যারের চেয়ে কম বৈশিষ্ট্য

৫. ম্যানুয়াল হ্যান্ডলিংয়ের সাথে কাঁচা মেমরির বরাদ্দ

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;
}

স্বপক্ষে

  • সর্বাধিক 'নিয়ন্ত্রণ'

বিরূদ্ধে

  • স্ট্রিং কপি প্রয়োজন
  • ত্রুটির জন্য সর্বাধিক দায় / সংবেদনশীলতা bility
  • জটিল

9

আমি একটি এপিআই দিয়ে কাজ করছি অনেকগুলি ফাংশন দিয়ে একটি ইনপুট হিসাবে পাই 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একটি বিদ্যমান স্ট্রিংয়ের একটি গভীর এবং অনন্য অনুলিপি (এটি অনুলিপিযোগ্য নয়) তৈরি করছে।


3
আমি এই নামকরণের সম্মেলনটি এড়িয়ে যাব। c_str()ব্যবহৃত হিসাবে দ্বারা std"সি STRING" নয় "const STRING" এর জন্য একটি সমাহার এবং str()সবসময় একটি ফেরৎ std::basic_stringনা char*(উদাহরণস্বরূপ std::stringstream::str())
bcrist

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

1
অভিনব দেখায় তবে বুঝতে খুব কষ্ট হয় ... সহজ হ'ল সেরা আইএমও
এ। মালিক

4
strcpy (), malloc (), দৈর্ঘ্য () এবং c_str () মূল ফাংশন এবং এর মধ্যে শক্ত কিছু নেই। শুধু স্মৃতি বরাদ্দ এবং অনুলিপি।
cegpraकाश

5
হ্যাঁ ফাংশনগুলি মৌলিক তবে আপনি স্প্যাগেটির বাটি বা একটি লাইনার ফ্র্যাঙ্কেনস্টাইনের
এ। মালিক

4
হ্যাঁ ফাংশনগুলি মৌলিক তবে ... আপনি যখন কোনও প্রোগ্রামিং ভাষার সাথে ডিল করতে শুরু করেছিলেন তখন কি মনে আছে? আরও কিছু লাইন ব্যাখ্যা করার জন্য এবং উদাহরণস্বরূপ এই উত্তরটির চেয়ে আলাদা বা ভাল কেন এটি
নিওফাইটকে বুঝতে সহায়তা করবে

2
@ এসিগপ্রকাশ: যখনই কোনও মালক () আছে, সেখানেও একটি ফ্রি () থাকতে হবে। অন্যথায় কোডটি মেমরি ফাঁস করে এবং তাই আপনার উত্তরটিতে সমাধানও করে। কমপক্ষে প্রয়োজনীয় ক্ষয়ক্ষতি সম্পর্কে ইঙ্গিত না করে মেমরি বরাদ্দ করা এই জাতীয় প্রশ্নের খারাপ অভ্যাস।
স্ট্রিজেল

7

শুধু এটি দেখুন:

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

যাইহোক, দ্রষ্টব্য যে এটি একটি ফিরে আসবে const char *

একটির জন্য char *, strcpyএটি অন্য charঅ্যারেতে অনুলিপি করতে ব্যবহার করুন ।


23
হাই, আপনি যা পোস্ট করেছেন তা ইতিমধ্যে একাধিকবার বলা হয়েছে, আরও বিশদ সহ, 5 বছরের পুরানো প্রশ্নের অন্য উত্তরে। পুরানো প্রশ্নের উত্তর দেওয়া ভাল, তবে আপনি যদি নতুন তথ্য যুক্ত করেন তবেই। অন্যথায়, এটি কেবল গোলমাল।
মাদুর

7
ব্যক্তিগতভাবে, আমি সরলতার প্রশংসা করি।
ট্যাঙ্কোরস্যামশ

-4

এটা চেষ্টা কর

std::string s(reinterpret_cast<const char *>(Data), Size);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.