printf dengan std::string?

Pemahaman saya adalah bahwa string adalah anggota dari std namespace, jadi mengapa tidak berikut terjadi?

#include <iostream>

int main()
{
    using namespace std;

    string myString = "Press ENTER to quit program!";
    cout << "Come up and C++ me some time." << endl;
    printf("Follow this command: %s", myString);
    cin.get();

    return 0;
}

Setiap kali program dijalankan, myString cetakan yang tampaknya string acak dari 3 karakter, seperti di output di atas.

Mengomentari pertanyaan (3)
Larutan

It's kompilasi karena printf isn't tipe aman, karena menggunakan variabel argumen di C akal1. printf tidak memiliki pilihan untuk std::string, hanya C-gaya string. Menggunakan sesuatu yang lain di tempat apa yang diharapkan pasti menang't memberikan anda hasil yang anda inginkan. It's benar-benar perilaku tidak terdefinisi, jadi apa pun bisa terjadi.

Cara termudah untuk memperbaiki hal ini, karena anda're menggunakan C++, adalah pencetakan biasanya dengan std::cout, karena std::string mendukung bahwa melalui operator overloading:


std::cout 
Komentar (2)

Silakan don't menggunakan printf("%s", your_string.c_str());

Gunakan cout << your_string; sebagai gantinya. Pendek, sederhana dan typesafe. Pada kenyataannya, ketika anda're penulisan C++, biasanya anda ingin menghindari printf seluruhnya-it's sisa dari C yang's jarang diperlukan atau berguna dalam C++.

Untuk mengapa anda harus menggunakan cout bukan printf, alasan yang lain. Berikut ini's sampling dari beberapa yang paling jelas:

  1. Sebagai pertanyaan, printf isn't type-safe. Jika jenis anda melewati berbeda dari yang diberikan dalam konversi penspesifikasi, printf akan mencoba untuk menggunakan apa pun yang ditemukannya di tumpukan seolah-olah itu adalah jenis tertentu, memberikan terdefinisi perilaku. Beberapa kompiler dapat memperingatkan tentang hal ini dalam beberapa keadaan, tetapi beberapa kompiler dapat't/tidak't pada semua, dan tidak dapat di bawah semua keadaan.
  2. printf isn't extensible. Anda hanya dapat melewati tipe primitif itu. Set conversion specifier memahami keras-kode dalam pelaksanaannya, dan ada's tidak ada cara bagi anda untuk menambahkan lebih banyak/lain-lain. Sebagian besar ditulis dengan C++ harus menggunakan jenis ini terutama untuk melaksanakan jenis berorientasi pada masalah yang sedang dipecahkan.
  3. Hal ini membuat layak format jauh lebih sulit. Untuk contoh yang jelas, bila anda're mencetak angka bagi orang-orang untuk membaca, biasanya anda ingin menyisipkan pemisah ribuan setiap beberapa digit. Jumlah yang tepat dari angka dan karakter-karakter yang digunakan sebagai pemisah bervariasi, tapi cout memiliki yang menutupi juga. Misalnya:

std::lokal loc(""); std::cout.mengilhami(loc);

std::cout << 123456.78;

Nama lokal ("") picks lokal didasarkan pada pengguna's konfigurasi. Oleh karena itu, pada mesin saya (dikonfigurasi untuk bahasa inggris) ini mencetak sebagai 123,456.78. Untuk seseorang yang memiliki komputer mereka dikonfigurasi untuk (katakanlah) Jerman, itu akan mencetak sesuatu seperti 123.456,78. Untuk seseorang yang dikonfigurasi untuk India, itu akan mencetak sebagai 1,23,456.78 (dan tentu saja ada banyak orang lain). Dengan printf saya mendapatkan tepat satu hasilnya: 123456.78. Hal ini konsisten, tetapi itu's secara konsisten salah untuk semua orang di mana-mana. Pada dasarnya satu-satunya cara untuk mengatasi ini adalah dengan melakukan format secara terpisah, kemudian menyampaikan hasilnya sebagai string untuk printf, karena printf itu sendiri hanya akan tidak melakukan pekerjaan dengan benar. 4. Meskipun mereka're cukup kompak, printf format string dapat cukup terbaca. Bahkan di antara C programmer yang menggunakan printf hampir setiap hari, saya'd tebak setidaknya 99% akan perlu untuk melihat hal-hal untuk memastikan apa # di %#x berarti, dan cara yang berbeda dari apa # di %#f berarti (dan ya, mereka berarti hal yang sama sekali berbeda).

Komentar (23)

gunakan myString.c_str() jika anda ingin c-seperti string (const char*) untuk digunakan dengan printf

terima kasih

Komentar (0)

Gunakan std::printf dan c_str() contoh:

std::printf("Follow this command: %s", myString.c_str());
Komentar (0)

Printf sebenarnya cukup baik untuk digunakan jika ukuran itu penting. Artinya jika anda menjalankan sebuah program di mana memori merupakan masalah, maka printf sebenarnya sangat baik dan di bawah rater solusi. Cout dasarnya pergeseran bit di atas untuk membuat ruang untuk string, sedangkan printf hanya berlangsung dalam beberapa jenis parameter dan mencetaknya ke layar. Jika anda adalah untuk mengkompilasi sederhana hello world program printf akan mampu menyusun itu dalam waktu kurang dari 60, 000 bit sebagai lawan cout, itu akan mengambil lebih dari 1 juta bit untuk mengkompilasi.

Untuk situasi anda, id sarankan menggunakan cout hanya karena hal ini jauh lebih nyaman untuk digunakan. Meskipun, saya berpendapat bahwa printf adalah sesuatu yang baik untuk tahu.

Komentar (0)

Alasan utama mungkin adalah bahwa C++ string adalah sebuah struct yang termasuk saat ini-suhu udara turun nilai, bukan hanya alamat urut-urutan dari karakter yang diakhiri dengan 0 byte. Printf dan kerabat berharap untuk menemukan urutan seperti itu, tidak struct, dan oleh karena itu bingung dengan C++ string.

Berbicara untuk diri saya sendiri, saya percaya bahwa printf memiliki tempat yang dapat't dengan mudah diisi oleh C++ fitur sintaksis, seperti struktur tabel dalam html memiliki tempat yang dapat't dengan mudah diisi oleh div. Sebagai Dykstra kemudian menulis tentang goto, dia didn't berniat untuk memulai sebuah agama dan itu benar-benar hanya berdebat melawan menggunakannya sebagai kludge untuk menebus buruk dirancang kode.

Itu akan cukup bagus jika proyek GNU akan menambah printf keluarga mereka g++ ekstensi.

Komentar (0)

printf menerima sejumlah variabel argumen. Mereka hanya dapat memiliki Plain Old Data (POD) jenis. Kode yang melewati sesuatu yang lain dari POD printf hanya mengkompilasi karena compiler mengasumsikan anda punya format yang tepat. %s berarti bahwa masing-masing argumen ini seharusnya menjadi pointer ke char. Dalam kasus anda itu adalah std::string tidak const char*. printf tidak tahu itu karena argumen tipe pergi hilang dan seharusnya dikembalikan dari format parameter. Ketika balik yang std::string argumen ke const char* yang dihasilkan pointer akan menunjuk ke beberapa yang tidak relevan wilayah dari memori bukan yang anda inginkan C string. Untuk alasan bahwa kode anda mencetak omong kosong.

Sementara printf adalah pilihan istimewa untuk mencetak teks yang diformat, (terutama jika anda berniat untuk memiliki padding), hal ini dapat berbahaya jika anda belum't diaktifkan compiler peringatan. Selalu mengaktifkan peringatan karena kesalahan-kesalahan seperti ini sebenarnya dapat dengan mudah dihindari. Tidak ada alasan untuk menggunakan kikuk std::cout mekanisme jika printf keluarga dapat melakukan tugas yang sama dalam waktu yang jauh lebih cepat dan lebih cantik cara. Pastikan anda telah mengaktifkan semua peringatan (-Dinding -Wextra) dan anda akan baik. Dalam kasus anda menggunakan kustom anda sendiri printf implementasi anda harus menyatakan dengan __atribut__ mekanisme yang memungkinkan compiler untuk memeriksa format string terhadap parameter yang diberikan.

Komentar (0)