Cara mengkonversi std::string untuk const char* atau char*?

Bagaimana saya bisa mengkonversi sebuah std::string ke char* atau const char*?

Mengomentari pertanyaan (7)
Larutan

Jika anda hanya ingin lulus std::string untuk fungsi yang membutuhkan const char* anda dapat menggunakan

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

Jika anda ingin mendapatkan ditulisi, seperti char *, anda bisa melakukan itu dengan ini:

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;

Edit: Perhatikan bahwa di atas tidak terkecuali aman. Jika apa-apa antara baru dan delete call melempar, anda akan kebocoran memori, karena tidak ada yang akan memanggil hapus untuk anda secara otomatis. Ada dua cara-cara langsung untuk memecahkan masalah ini.

meningkatkan::scoped_array

boost::scoped_array akan menghapus memori anda pada saat akan keluar dari ruang lingkup:

std::string str;
boost::scoped_array 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::vektor

Ini adalah cara standar (tidak memerlukan library eksternal). Anda gunakan std::vektor, yang benar-benar mengelola memori untuk anda.

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

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

Mengingat mengatakan...

std::string x = "hello";

Mendapatkan `char *` atau `const char*` dari `string`

**Cara mendapatkan karakter pointer yang's berlaku sementara `x` tetap dalam lingkup dan isn't dimodifikasi lebih lanjut** **C++11** menyederhanakan hal-hal, berikut semua memberikan akses yang sama pada internal buffer string:
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...

Semua petunjuk di atas akan terus sama nilai - alamat dari karakter pertama dalam buffer. Bahkan string kosong memiliki "karakter pertama dalam buffer", karena C++11 jaminan untuk selalu menjaga ekstra NUL/0 terminator karakter setelah ditetapkan secara tegas string konten (misalnya std::string("\0that", 9) akan memiliki penyangga memegang "\0that\0"). Mengingat semua petunjuk di atas:


char c = p[n];   // valid for n 
Komentar (1)

Gunakan .c_str() metode const char *.

Anda dapat menggunakan &mystring[0] untuk mendapatkan char * pointer, tetapi ada beberapa gotcha's: anda tidak't selalu mendapatkan nol string berakhir, dan anda tidak't dapat mengubah string's ukuran. Anda terutama harus berhati-hati untuk tidak menambahkan karakter melewati akhir dari string atau anda'll mendapatkan buffer overrun (dan kemungkinan kecelakaan).

Tidak ada jaminan bahwa semua karakter akan menjadi bagian yang sama bersebelahan penyangga sampai C++11, tetapi dalam prakteknya semua dikenal implementasi std::string bekerja dengan cara itu pula, lihat Artinya "&s[0]" titik bersebelahan karakter di std::string?.

Perhatikan bahwa banyak string fungsi anggota akan mengalokasikan buffer internal dan membatalkan pointer anda mungkin telah disimpan. Terbaik untuk menggunakan mereka segera dan kemudian buang.

Komentar (5)

C++17

C++17 (standar mendatang) perubahan sinopsis template basic_string menambahkan non-const overload data():

grafik* data() noexcept;

Kembali: pointer p sedemikian sehingga p + i == &operator untuk setiap saya di [0,size()].


Grafik const * dari std::basic_string<Grafik>

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

Grafik * dari std::basic_string<Grafik>

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

C++11

Grafik const * dari std::basic_string<Grafik>

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

Grafik * dari std::basic_string<Grafik>

Dari C++11 dan seterusnya, standar says:

  1. Char-benda seperti dalam basic_string objek akan disimpan secara menyatu. Artinya, untuk setiap basic_string objek s, identitas &*(s.begin() + n) == &*s.begin() + n akan tahan untuk semua nilai n seperti itu 0 <= n < s.size().

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

Kembali: *(begin() + pos) jika pos < size(), atau referensi ke suatu objek dari jenis Grafik dengan nilai Grafik(); direferensikan nilai tidak akan diubah.


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

Kembali: pointer p seperti yang p + i == &operator[](i) untuk setiap aku dalam [0,size()].

Ada dapat dipisahkan cara yang mungkin untuk mendapatkan non-const karakter pointer.

1. Gunakan bersebelahan penyimpanan C++11

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

Pro

  • Sederhana dan pendek
  • Cepat (hanya dengan metode tidak copy terlibat)

Karena ...

  • Final&#39;\0&#39; ini tidak dapat diubah-ubah / tidak harus selalu menjadi bagian dari non-const memori.

2. Gunakan std::vektor<Grafik>

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

Pro

  • Sederhana
  • Otomatis penanganan memori
  • Dinamis

Karena ...

  • Membutuhkan string copy

3. Gunakan std::array<Grafik, N> jika N adalah waktu kompilasi konstan (dan cukup kecil)

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

Pro

  • Sederhana
  • Stack memori penanganan

Karena ...

  • Statis
  • Membutuhkan string copy

4. Baku alokasi memori dengan penyimpanan otomatis penghapusan

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

Pro

  • Footprint memori kecil
  • Penghapusan otomatis
  • Sederhana

Karena ...

  • Membutuhkan string copy
  • Statis (dinamis memerlukan penggunaan banyak lagi kode)
  • Fitur kurang dari vektor atau array

5. Baku alokasi memori dengan penanganan secara manual

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

Pro

  • Maksimum 'control'

Con

  • Membutuhkan string copy
  • Maksimum tanggung jawab terhadap kesalahan
  • Kompleks
Komentar (0)

Saya bekerja dengan API dengan banyak fungsi bisa sebagai masukan char*.

Saya telah menciptakan sebuah kelas kecil untuk menghadapi masalah seperti ini, saya telah menerapkan 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_; }
};

Dan anda dapat menggunakannya sebagai:

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

Saya telah disebut kelas DeepString karena itu adalah menciptakan mendalam dan unik menyalin (DeepString tidak copyable) yang ada string.

Komentar (1)

Hanya melihat ini :

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

Namun , perhatikan bahwa ini akan kembali const char *.Untuk char *, gunakan strcpy untuk menyalin ke lain char array.

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

Coba ini

std::string s(reinterpret_cast(Data), Size);
Komentar (0)