Std :: string const char * හෝ char * බවට පරිවර්තනය කරන්නේ කෙසේද?


915

මම std::stringa char*හෝ a බවට පරිවර්තනය කරන්නේ කෙසේද const char*?


2
ඒ වෙනුවට: char * writeable = නව char [str.size () + 1]; ඔබට වර්‍ග ලිවිය හැකි [str.size () + 1] භාවිතා කළ හැකිය; එවිට ඔබට ලිවිය හැකි හෝ ව්‍යතිරේක හැසිරවීම මකා දැමීම ගැන කරදර විය යුතු නැත.

7
සම්පාදනය කරන වේලාවේ ප්‍රමාණය නොදන්නේ නම් ඔබට str.size () භාවිතා කළ නොහැක, එසේම ස්ථාවර ප්‍රමාණයේ වටිනාකම විශාල නම් එය ඔබේ තොගය පිරී ඉතිරී යනු ඇත.
paulm

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

7
gcegprakash strcpyසහ mallocඇත්ත වශයෙන්ම C ++ ක්‍රමය නොවේ.
boycy

4
නැත, නමුත් char* dest = new char[str.length() + 1]; std::copy(str.begin(), str.end(), dest)වඩාත් මුග්ධ C ++ වනු ඇත. strcpy()හා malloc()වැරදි හෝ ගැටලු සහගත නොවේ, නමුත් එය කේතය එකම වාරණ දී C ++ සමාන සමඟ C ++, සංගීත හා C පුස්තකාල පහසුකම් භාවිතා කිරීමට නොගැලපෙන බව පෙනේ.
boycy

Answers:


1089

ඔබට අවශ්‍ය 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ඔබ ස්වයංක්‍රීයව කිසිවක් ඉල්ලා නොසිටින බැවින් ඔබට මතකය කාන්දු වේ. මෙය විසඳීමට ක්ෂණික ක්‍රම දෙකක් තිබේ.

boost :: 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()

44
හුදෙක් char * result = strdup (str.c_str ()) භාවිතා කරන්න;
ජැස්පර් බෙකර්ස්

65
ඔබට හැකි නමුත් strdup යනු ac හෝ c ++ සම්මත ශ්‍රිතයක් නොවේ, එය පොසික්ස් වලින් වේ :)
ජොහැන්නස් ෂෝබ් - litb

14
මම සාමාන්‍යයෙන් කැමති වන්නේ std :: vector <char> ලිවිය හැකි (str.begin (), str.end ()); writeable.push_back ('\ 0'); char * c = & ලිවිය හැකි [0];
ජොහැන්නස් ෂෝබ් -

17
std :: copy යනු නූල් පොයින්ටරය වෙත යාමෙන් තොරව මෙය සිදු කිරීමේ c ++ ක්‍රමයයි. මට හැකි පමණින් C ශ්‍රිත භාවිතා කිරීමෙන් වැළකී සිටීමට මම උත්සාහ කරමි.
ජොහැන්නස් ෂෝබ් -

19
C ++ 17 වන std::string::data()විට , දැන් a CharT*වෙනුවට ආදේශ කරයි const CharT*. මෙම පිළිතුර යාවත්කාලීන කිරීම හොඳ අදහසක් විය හැකිය :)
Rakete1111

195

කියන දේ ...

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...

ඉහත සියළු දර්ශකයන් එකම අගයක් දරයි - බෆරයේ පළමු අක්‍ෂරයේ ලිපිනය. හිස් නූලකට පවා "බෆරයේ පළමු අක්‍ෂරය" ඇත, මන්ද පැහැදිලිවම පවරා ඇති නූල් අන්තර්ගතයෙන් පසුව සෑම විටම අමතර NUL / 0 ටර්මිනේටර් අක්‍ෂරයක් තබා ගැනීමට C ++ 11 සහතික කරයි (උදා: 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 ලියන කරන්නේ නෑ වෙනස් stringගේ size(); stringඕනෑම NUL ගණනක් අඩංගු කිරීමට අවසර ඇත - ඔවුන්ට විශේෂ ප්‍රතිකාර ලබා නොදේ std::string(C ++ 03 හි).

දී C ++ 03 , දේවල් සැලකිය යුතු ලෙස වැඩි සංකීර්ණ විය (යතුරු වෙනස්කම් ඉස්මතු ):

  • x.data()

    • NUL සමඟ නිගමනය කිරීමට සම්මතයට අවශ්‍ය නොවූconst char* නූල් අභ්‍යන්තර බෆරය වෙත නැවත පැමිණේ (එනම්, ආරම්භක හෝ කසළ අගයන් අනුගමනය කළ හැකිය , අහම්බෙන් ප්‍රවේශ වීමත් සමඟ නිර්වචනය නොකළ හැසිරීමක් ඇත ). ['h', 'e', 'l', 'l', 'o']
      • x.size()අක්ෂර කියවීමට ආරක්ෂිතයි, එනම් x[0]හරහාx[x.size() - 1]
      • හිස් නූල් සඳහා, ඔබට 0 ආරක්ෂිතව එකතු කළ හැකි NULL නොවන දර්ශකයක් සහතික කර ඇත (ඉක්මන් කරන්න!), නමුත් ඔබ එම දර්ශකය අවලංගු නොකළ යුතුය.
  • &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-අවසන්) වටිනාකම නියෝජනය (එනම් [ 'H', 'ඊ', 'මම', 'මම', 'O', '\' 0 ']).
    • ඕනෑම ක්රියාත්මක කිරිමේදි එසේ කිරීමට තීරණය නම්, C ++ 03 සම්මත වැල ක්රියාත්මක කිරීම සඳහා නිර්මාණය කිරීමට නිදහස ඉඩ එක්කම කිහිපයක් තිබුණත් පැහැදිලි NUL-අවසන් බෆරය පියාසර තහනම් මත , විභව්ය නොවන NUL අවසන් සිට විසින් "නිරාවරණය" ස්වාරක්ෂක x.data()හා&x[0]
    • x.size() + 1 අක්ෂර කියවීමට ආරක්ෂිතයි.
    • හිස් නූල් සඳහා පවා ආරක්ෂිත බව සහතික කර ඇත (['\ 0']).

බාහිර නෛතික දර්ශක වලට ප්‍රවේශ වීමේ ප්‍රතිවිපාක

ඔබට දර්ශකයක් ලැබෙන්නේ කුමන ආකාරයෙන් වුවද, ඉහත විස්තර කර ඇති බවට සහතික කර ඇති අක්ෂරවලට වඩා ඔබ දර්ශකයේ සිට මතකයට ප්‍රවේශ නොවිය යුතුය. එසේ කිරීමට දරන උත්සාහයන් නිර්වචනය නොකළ හැසිරීමක් ඇති අතර , කියවීම් සඳහා පවා යෙදුම් බිඳවැටීම් සහ කසළ ප්‍රති results ල සඳහා සැබෑ අවස්ථාවක් ඇති අතර, ඊට අමතරව තොග දත්ත, තොග දූෂණය සහ / හෝ ලිවීමේ ආරක්ෂක දුර්වලතා.

එම දර්ශකයන් අවලංගු වන්නේ කවදාද?

තව දුරටත් ධාරිතාව stringවෙනස් කරන stringහෝ වෙන් කර ඇති යම් සාමාජික ශ්‍රිතයක් ඔබ අමතන්නේ නම් , ඉහත සඳහන් ඕනෑම ක්‍රමයක් මඟින් කලින් ලබා දුන් ඕනෑම දර්ශක අගයක් අවලංගු වේ. වෙනත් දර්ශකයක් ලබා ගැනීම සඳහා ඔබට එම ක්‍රම නැවත භාවිතා කළ හැකිය. (නීති රීති අනුකාරකයන්ට strings ට සමාන වේ).

කොළ විෂය පථයෙන් පසුව xහෝ තව දුරටත් වෙනස් කිරීමෙන් පසුව පවා අක්ෂර දර්ශකයක් වලංගු වන්නේ කෙසේද යන්නද බලන්න ....

ඉතින්, භාවිතා කිරීමට වඩා හොඳ කුමක්ද?

C ++ 11 සිට, .c_str()ASCIIZ දත්ත .data()සඳහා සහ "ද්විමය" දත්ත සඳහා භාවිතා කරන්න (තවදුරටත් පහත විස්තර කර ඇත).

සී ++, 03, භාවිතය .c_str(), එම නිශ්චිත මිස .data()ප්රමාණවත් වන අතර, කැමති .data()පුරා &x[0]එය හිස් නූල් සඳහා ආරක්ෂිත ලෙස ....

... data()සුදුසු අවස්ථාවලදී භාවිතා කිරීමට තරම් වැඩසටහන තේරුම් ගැනීමට උත්සාහ කරන්න , නැතහොත් ඔබ වෙනත් වැරදි සිදු කරනු ඇත ...

සහතික කර ඇති ASCII NUL '\ 0' අක්‍ෂරය .c_str()බොහෝ කාර්යයන් මගින් සෙන්ඩිනල් අගයක් ලෙස භාවිතා කරයි. මෙම අවස්ථා දෙකම C ++ අදාළ - මතය වැනි කාර්යයන් පමණක් fstream::fstream(const char* filename, ...)වැනි හා හවුල්-සමග-C කාර්යයන් strchr(), සහ printf().

.c_str()ආපසු ලබා දුන් බෆරය පිළිබඳ C ++ 03 හි සහතිකය සුපිරි කට්ටලයක් බැවින් .data()ඔබට සැමවිටම ආරක්ෂිතව භාවිතා කළ හැකිය .c_str(), නමුත් මිනිසුන් සමහර විට එසේ නොකරන්නේ:

  • .data()දත්ත ASCIIZ නොවන මූලාශ්‍ර කේතය කියවන වෙනත් ක්‍රමලේඛකයන්ට සන්නිවේදනය භාවිතා කිරීම (ඒ වෙනුවට, ඔබ දත්ත කාණ්ඩයක් ගබඩා කිරීම සඳහා නූල් භාවිතා කරයි (සමහර විට එය ඇත්ත වශයෙන්ම පා ual මය නොවේ)), හෝ ඔබ එය වෙත යවනවා එය "ද්විමය" දත්ත කාණ්ඩයක් ලෙස සලකන තවත් ශ්‍රිතයකි. අනෙකුත් ක්‍රමලේඛකයන්ගේ කේත වෙනස්වීම් අඛණ්ඩව දත්ත නිසි ලෙස හැසිරවීම සහතික කිරීම සඳහා මෙය තීරණාත්මක අවබෝධයක් විය හැකිය.
  • C ++ 03 පමණි: stringNUL අවසන් කළ බෆරය සකස් කිරීම සඳහා ඔබේ ක්‍රියාත්මක කිරීම සඳහා අමතර මතක වෙන් කිරීමක් සහ / හෝ දත්ත පිටපත් කිරීමක් කිරීමට සුළු අවස්ථාවක් තිබේ.

තවත් ඉඟියක් ලෙස, ශ්‍රිතයක පරාමිතීන් සඳහා ( const) අවශ්‍ය char*නමුත් ලබා ගැනීමට බල නොකරන්නේ නම් x.size(), ශ්‍රිතයට බොහෝ විට ASCIIZ ආදානයක් අවශ්‍ය වේ, එබැවින් .c_str()හොඳ තේරීමක් වේ (ශ්‍රිතය කෙසේ හෝ අවසන් වන්නේ කොතැනදැයි දැන ගැනීමට අවශ්‍ය වේ, එබැවින් එය එසේ නොවේ නම් වෙනම පරාමිතියක් එය විය හැක්කේ දිග-උපසර්ගය හෝ සෙන්ඩිනල් හෝ ස්ථාවර අපේක්ෂිත දිග වැනි සම්මුතියක් පමණි).

xවිෂය පථයෙන් ඉවත්ව ගිය පසු හෝ තවදුරටත් වෙනස් කළද අක්‍ෂර දර්ශකයක් වලංගු වන්නේ කෙසේද?

ඔබට පිටතින් නව මතක ප්‍රදේශයකට අන්තර්ගතය පිටපත් කිරීමට අවශ්‍ය වනු string xඇත x. මෙම බාහිර බෆරය වෙනත් stringහෝ අක්ෂර අරාව විචල්‍යයක් වැනි බොහෝ ස්ථානවල විය හැකිය, එය xවෙනත් විෂය පථයක සිටීම නිසා වෙනස් ජීවිත කාලයක් තිබිය හැකිය හෝ නොතිබිය හැකිය (උදා: නාම අවකාශය, ගෝලීය, ස්ථිතික, ගොඩවල්, හවුල් මතකය, මතක සිතියම්ගත කළ ගොනුව) .

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

A char*හෝ const char*ජනනය කිරීමට අවශ්‍ය වෙනත් හේතුstring

ඉතින්, ඉහත ඔබ දැක ඇත්තේ ( const) ලබා char*ගන්නේ කෙසේද සහ මුල් පිටපතෙන් ස්වාධීනව පිටපතක් සාදා ගන්නේ කෙසේද යන්නයි string, නමුත් ඔබට එය සමඟ කළ හැක්කේ කුමක්ද? අහඹු ලෙස උදාහරණ කුඩා කිරීම ...

  • C ++ stringහි පෙළට "C" කේත ප්‍රවේශය ලබා දෙන්න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 තිහාසික හේතූන් මත - සේවාදායකයා ඔබගේ පවතින API භාවිතා කරයි - හෝ සී අනුකූලතාව සඳහා ඔබට නැවත පැමිණීමට අවශ්‍ය නැත std::string, නමුත් stringඅමතන්නා සඳහා ඔබේ දත්ත කොහේ හෝ පිටපත් කිරීමට අවශ්‍යද )
    • දේශීය stringවිචල්‍යයකින් පසුව, එම දර්ශකය පෙන්වා ඇති විෂය පථයෙන් ඉවත්ව ගිය ඇමතුම මඟින් අවලංගු කළ හැකි දර්ශකයක් ආපසු නොයැවීමට වගබලා ගන්න.
    • විවිධ std::stringක්‍රියාත්මක කිරීම් සඳහා සම්පාදනය කරන ලද / සම්බන්ධිත හවුල් වස්තු සහිත සමහර ව්‍යාපෘති (උදා: STLport සහ සම්පාදක-ස්වදේශික) ගැටුම් වළක්වා ගැනීම සඳහා ASCIIZ ලෙස දත්ත යැවිය හැක.

4
කදිම එකක්. වර්‍ගයක් අවශ්‍ය වීමට තවත් හේතුවක් * (කොන්ස් නොවන) MPI විකාශනය සමඟ ක්‍රියාත්මක වීමයි. ඔබට පිටුපසට පිටපත් කිරීමට අවශ්‍ය නැතිනම් එය වඩාත් හොඳ බව පෙනේ. මම පෞද්ගලිකව නූලට වර්‍ගයක් ලබා දෙන්නෙමි. කොන්ස්ට් පොයින්ටරය, නමුත් සංස්කරණය කළ හැකි නූල්.
කොන්ස්ට්

34

සඳහා .c_str()ක්රමය භාවිතා කරන්න const char *.

ඔබට දර්ශකයක් &mystring[0]ලබා ගැනීමට භාවිතා කළ හැකිය char *, නමුත් ගොචා කිහිපයක් තිබේ: ඔබට අවශ්‍යයෙන්ම ශුන්‍යයෙන් අවසන් වූ නූලක් නොලැබෙන අතර, ඔබට නූල් ප්‍රමාණය වෙනස් කිරීමට නොහැකි වනු ඇත. ඔබ විශේෂයෙන් පරිස්සම් විය යුත්තේ නූල් කෙළවරට ඔබ්බෙන් අක්ෂර එකතු නොකිරීමට හෝ ඔබට බෆරයක් අභිබවා යාමට (සහ බිඳවැටීමට ඉඩ ඇත).

C ++ 11 වන තෙක් සියලුම අක්ෂර එකම පරස්පර බෆරයේ කොටසක් බවට කිසිදු සහතිකයක් නොතිබුණි, නමුත් ප්‍රායෝගිකව දන්නා පරිදි සියලු ක්‍රියාත්මක කිරීම් std::stringකෙසේ හෝ ක්‍රියාත්මක විය ; බලන්න “& s [0]” std :: string එකක පරස්පර අක්ෂර වෙත යොමු වේද? .

බොහෝ stringසාමාජික ක්‍රියාකාරකම් මඟින් අභ්‍යන්තර බෆරය නැවත ස්ථානගත කර ඔබ සුරකින ලද ඕනෑම දර්ශකයක් අවලංගු කරනු ඇති බව සලකන්න . ඒවා වහාම භාවිතා කර ඉවතලෑම වඩාත් සුදුසුය.


1
දත්ත () මඟින් ප්‍රතිස්ථාපන වර්‍ගය * ලබා දෙන බව ඔබ සටහන් කළ යුතුය.
ජොහැන්නස් ෂෝබ් -

1
it ලිට්බ්, ආග්! ඉක්මන් පිළිතුරක් දීමට උත්සාහ කිරීම නිසා මට ලැබෙන්නේ එයයි. මම අතීතයේ දී ඔබේ විසඳුම භාවිතා කර ඇත්තෙමි, එය මතකයට එන්නේ ඇයි දැයි නොදනී. මම මගේ පිළිතුර සංස්කරණය කර ඇත.
මාර්ක් රැන්සම්

2
තාක්ෂණික වශයෙන්, std :: string ආචයනය අඛණ්ඩව පවතින්නේ C ++ 0x වලින් පමණි.
MSalters

1
@ එම්එස්එල්ටර්ස්, ස්තූතියි - මම ඒක දැනගෙන හිටියේ නැහැ. එය එසේ නොවන තැනක ක්‍රියාත්මක කිරීමක් සොයා ගැනීමට මට අපහසු වනු ඇත.
මාර්ක් රැන්සම්

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

21

සී ++ 17

C ++ 17 (ඉදිරි සම්මත) සැකිල්ල පිළිබඳ සාරාංශයක් පහත වෙනස් basic_stringක නොවන const අධි බර එකතු data():

charT* data() noexcept;

ප්‍රතිලාභ: [0, ප්‍රමාණය ()] හි එක් එක් i සඳහා p + i == සහ ක්‍රියාකරු වැනි දර්ශක p.


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සියලු අගයන් සඳහා රඳවා තබා ගනී .n0 <= 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ඇතුළත සඳහා දර්ශක p [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;
}

ප්‍රෝ

  • උපරිම 'පාලනය'

කොන්

  • නූල් පිටපතක් අවශ්‍යයි
  • දෝෂ සඳහා උපරිම වගකීම / සංවේදීතාව
  • සංකීර්ණ

9

මම ආදාන ලෙස ලබා ගන්නා කාර්යයන් රාශියක් ඇති API සමඟ වැඩ කරමි char*.

මේ ආකාරයේ ගැටලුවකට මුහුණ දීම සඳහා මම කුඩා පංතියක් නිර්මාණය කර ඇති අතර, මම RAII idiom ක්‍රියාත්මක කර ඇත්තෙමි.

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"C-string" "const string" නොවේ කෙටි යෙදුමක් වන අතර, str()සෑම විටම නැවත std::basic_stringනොව char*(උදාහරණයක් std::stringstream::str())
bcrist

9

මෙය බලන්න:

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

කෙසේ වෙතත්, මෙය නැවත ලබා දෙන බව සලකන්න const char *.

A සඳහා char *, strcpyඑය වෙනත් charඅරාවකට පිටපත් කිරීමට භාවිතා කරන්න .


24
හායි, ඔබ පළ කළ දෙය දැනටමත් අවුරුදු 5 ක් පැරණි ප්‍රශ්නයට වෙනත් පිළිතුරු වලින් වැඩි විස්තර සහිතව පවසා ඇත. පැරණි ප්‍රශ්නවලට පිළිතුරු සැපයීම හොඳයි, නමුත් ඔබ නව තොරතුරු එකතු කළහොත් පමණි. එසේ නොමැති නම් එය ශබ්දය පමණි.
මතෙ

9
පෞද්ගලිකව මම සරල බව අගය කරමි.
ටැන්කර්ස්මාෂ්

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

1
මනස්කාන්ත පෙනුමක් ඇති නමුත් තේරුම් ගැනීමට අපහසුය ... සරලයි හොඳම IMO
නයීම් ඒ. මලික්

4
strcpy (), malloc (), දිග () සහ c_str () මූලික කාර්යයන් වන අතර මෙහි අමාරු කිසිවක් නොමැත. මතකය වෙන් කිරීම සහ පිටපත් කිරීම පමණි.
cegprakash

5
ඔව් කාර්යයන් මූලික නමුත් ඔබ ඒවා විකෘති කොට ස්පැගටි පාත්‍රයක් හෝ ෆ්‍රැන්කන්ස්ටයින්ගේ රාක්ෂයා මෙන් පෙනේ. :)
නයීම් ඒ. මලික්

4
ඔව්, කාර්යයන් මූලික නමුත් ... ඔබ ක්‍රමලේඛන භාෂාවක් සමඟ ගනුදෙනු කිරීමට පටන් ගත් විට ඔබට මතකද? පැහැදිලි කිරීමට තවත් පේළි කිහිපයක් ඇති අතර එය
නියෝෆයිටයකට

2
gcegprakash: malloc () ඇති විට, නොමිලේ () ද තිබිය යුතුය. එසේ නොමැතිනම් කේතය මතකය කාන්දු වන අතර ඔබේ පිළිතුරෙහි විසඳුමද එසේමය. අවම වශයෙන් අවශ්‍ය විසර්ජනය පිළිබඳ ඉඟියක්වත් නොමැතිව මතකය වෙන් කිරීම එවැනි ප්‍රශ්න සඳහා නරක පුරුද්දකි.
ස්ට්‍රයිසෙල්

-4

මේක උත්සාහ කරන්න

std::string s(reinterpret_cast<const char *>(Data), Size);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.