Saya ingin mencetak isi vektor di C ++, inilah yang saya miliki:
#include <iostream>
#include <fstream>
#include <string>
#include <cmath>
#include <vector>
#include <sstream>
#include <cstdio>
using namespace std;
int main()
{
ifstream file("maze.txt");
if (file) {
vector<char> vec(istreambuf_iterator<char>(file), (istreambuf_iterator<char>()));
vector<char> path;
int x = 17;
char entrance = vec.at(16);
char firstsquare = vec.at(x);
if (entrance == 'S') {
path.push_back(entrance);
}
for (x = 17; isalpha(firstsquare); x++) {
path.push_back(firstsquare);
}
for (int i = 0; i < path.size(); i++) {
cout << path[i] << " ";
}
cout << endl;
return 0;
}
}
Bagaimana cara mencetak konten vektor ke layar?
Jawaban:
Murni untuk menjawab pertanyaan Anda, Anda dapat menggunakan iterator:
Jika Anda ingin memodifikasi konten vektor dalam for for loop, maka gunakan
iterator
alih-alihconst_iterator
.Tapi ada banyak lagi yang bisa dikatakan tentang ini. Jika Anda hanya ingin jawaban yang dapat Anda gunakan, maka Anda bisa berhenti di sini; kalau tidak, baca terus.
otomatis (C ++ 11) / typedef
Ini bukan solusi lain, tetapi suplemen untuk
iterator
solusi di atas . Jika Anda menggunakan standar C ++ 11 (atau lebih baru), maka Anda dapat menggunakanauto
kata kunci untuk membantu keterbacaan:Tetapi tipe
i
akan non-const (yaitu, kompiler akan digunakanstd::vector<char>::iterator
sebagai tipei
).Dalam hal ini, Anda mungkin hanya menggunakan a
typedef
(tidak terbatas pada C ++ 11, dan sangat berguna untuk digunakan):melawan
Anda tentu saja dapat menggunakan tipe integer untuk merekam posisi Anda dalam
for
loop:Jika Anda akan melakukan ini, lebih baik menggunakan tipe anggota penampung, jika tersedia dan sesuai.
std::vector
memiliki tipe anggota yang dipanggilsize_type
untuk pekerjaan ini: itu adalah tipe yang dikembalikan olehsize
metode.Mengapa tidak menggunakan ini saja di atas
iterator
solusinya? Untuk kasus-kasus sederhana Anda mungkin juga, tetapi intinya adalah bahwaiterator
kelas adalah objek yang dirancang untuk melakukan pekerjaan ini untuk objek yang lebih rumit di mana solusi ini tidak ideal.berbasis rentang untuk loop (C ++ 11)
Lihat solusi Jefffrey . Di C ++ 11 (dan lebih baru) Anda bisa menggunakan
for
loop berbasis rentang yang baru , yang terlihat seperti ini:Karena
path
merupakan vektor item (secara eksplisitstd::vector<char>
), objeknyai
bertipe item dari vektor (yaitu, secara eksplisit, ia bertipechar
). Objeki
memiliki nilai yang merupakan salinan dari item aktual dipath
objek. Dengan demikian, semua perubahani
pada loop tidak dipertahankan denganpath
sendirinya. Selain itu, jika Anda ingin menerapkan fakta bahwa Anda tidak ingin dapat mengubah nilai yang disalini
dalam loop, Anda dapat memaksa tipei
menjadiconst char
seperti ini:Jika Anda ingin mengubah item dalam
path
, Anda dapat menggunakan referensi:dan bahkan jika Anda tidak ingin memodifikasi
path
, jika menyalin objek mahal, Anda harus menggunakan referensi const daripada menyalin dengan nilai:std :: copy
Lihat jawaban Yosua . Anda dapat menggunakan algoritma STL
std::copy
untuk menyalin konten vektor ke aliran output. Ini adalah solusi yang elegan jika Anda merasa nyaman dengan itu (dan selain itu, ini sangat berguna, tidak hanya dalam hal ini mencetak isi vektor).std :: for_each
Lihat solusi Max . Menggunakan
std::for_each
berlebihan untuk skenario sederhana ini, tetapi ini adalah solusi yang sangat berguna jika Anda ingin melakukan lebih dari sekadar mencetak ke layar: menggunakanstd::for_each
memungkinkan Anda untuk melakukan operasi (masuk akal) apa pun pada konten vektor.overload ostream :: operator <<
Lihat jawaban Chris , ini lebih melengkapi jawaban lain karena Anda masih perlu menerapkan salah satu solusi di atas dalam kelebihan beban. Dalam contohnya dia menggunakan penghitung dalam satu
for
lingkaran. Sebagai contoh, ini adalah bagaimana Anda dapat dengan cepat menggunakan solusi Joshua :Penggunaan salah satu solusi lain harus langsung.
kesimpulan
Salah satu solusi yang disajikan di sini akan berfungsi. Terserah Anda dan kode mana yang "terbaik". Apa pun yang lebih terperinci dari ini mungkin sebaiknya ditanyakan pada masalah lain di mana pro / kontra dapat dievaluasi dengan benar; tetapi seperti biasa preferensi pengguna akan selalu berperan: tidak ada solusi yang disajikan salah, tetapi beberapa akan terlihat lebih bagus untuk masing-masing pembuat kode.
tambahan
Ini adalah solusi diperluas dari yang sebelumnya saya posting. Karena posting itu terus mendapat perhatian, saya memutuskan untuk mengembangkannya dan merujuk ke solusi hebat lainnya yang diposting di sini. Posting asli saya memiliki komentar yang menyebutkan bahwa jika Anda sedang berniat pada memodifikasi vektor Anda di dalam
for
lingkaran maka ada dua metode yang disediakan olehstd::vector
elemen akses:std::vector::operator[]
yang tidak melakukan batas memeriksa, danstd::vector::at
yang tidak melakukan batas memeriksa. Dengan kata lain,at
akan melempar jika Anda mencoba mengakses elemen di luar vektor danoperator[]
tidak mau. Saya hanya menambahkan komentar ini, awalnya, demi menyebutkan sesuatu yang mungkin perlu diketahui jika ada orang yang tidak. Dan saya tidak melihat perbedaan sekarang. Karena itu tambahan ini.sumber
0
melaluivector::size()
dan vektor tidak dimodifikasi dalam loop tidak perlu menggunakanat()
dan dikenakan batas tambahan memeriksa overhead. Yang mengatakan, saya akan pergi dengan iterator seperti yang Anda sarankan.at
jika tidak ada di memodifikasi lingkaran vektor, tapi saya pikir saya akan menyebutkannya hanya dalam kasus vektor adalah dimodifikasi dalam loop (unrecommended sebagai yang mungkin) dan karena itu tidak pernah mendapat sebutkan dan mungkin bermanfaat untuk, setidaknya, mengetahuinya.for (auto const &i: path) std::cout << i << ' ';
Cara yang lebih mudah untuk melakukan ini adalah dengan algoritma penyalinan standar :
Ostream_iterator adalah apa yang disebut adaptor iterator . Itu templatized atas jenis untuk dicetak ke aliran (dalam hal ini,
char
).cout
(alias keluaran konsol) adalah aliran yang ingin kita tulis, dan karakter spasi (" "
) adalah apa yang ingin kita cetak di antara setiap elemen yang disimpan dalam vektor.Algoritma standar ini sangat kuat dan banyak lainnya. Kekuatan dan fleksibilitas yang diberikan perpustakaan standar kepada Anda adalah apa yang membuatnya begitu hebat. Bayangkan saja: Anda dapat mencetak vektor ke konsol hanya dengan satu baris kode. Anda tidak harus berurusan dengan kasing khusus dengan karakter pemisah. Anda tidak perlu khawatir tentang for-loop. Perpustakaan standar melakukan semuanya untuk Anda.
sumber
vector<pair<int, struct node>>
. Bagaimana cara menggunakan metode di atas untuk mencetak vektor ini?operator<<
fungsi untuk pasangan spesifik Anda <>.Di C ++ 11 sekarang Anda dapat menggunakan rentang berbasis untuk loop :
sumber
char
s, kemungkinan lewatnya referensi konstan sebenarnya lebih mahal daripada nilai. Tapi di sini kita berbicara tentang optimasi super mikro.Saya pikir cara terbaik untuk melakukan ini adalah dengan kelebihan
operator<<
dengan menambahkan fungsi ini ke program Anda:Kemudian Anda dapat menggunakan
<<
operator pada kemungkinan vektor, dengan asumsi elemen-elemennya juga telahostream& operator<<
ditentukan:Keluaran:
sumber
last
kesize_t
.size_t last = v.size() - 1;
terlihat berlebihan, Anda dapat menggunakanif (i) out << ", ";
kondisi sebelumout << v[i];
tautanoperator<<
. Contohif (i != last)
setiap kali dalam lingkaran? Sebaliknya, jika wadah tidak kosong maka (a) kirim elemen pertama, dan kemudian (b) kirim loop- elemen yang tersisa , cetak separator terlebih dahulu (sebagai awalan). Tidak diperlukan tes loop dalam (terlepas dari kondisi loop itu sendiri). Hanya satu tes di luar lingkaran yang diperlukan.Bagaimana
for_each
+ ekspresi lambda :Tentu saja, rentang berbasis untuk adalah solusi paling elegan untuk tugas konkret ini, tetapi yang satu ini memberikan banyak kemungkinan lain juga.
Penjelasan
The
for_each
algoritma mengambil berbagai masukan dan objek callable , memanggil objek ini pada setiap elemen dari jangkauan. Sebuah rentang input didefinisikan oleh dua iterator . Sebuah objek callable bisa menjadi fungsi, pointer ke fungsi, objek kelas yang overload() operator
atau seperti dalam kasus ini, ekspresi lambda . Parameter untuk ekspresi ini cocok dengan jenis elemen dari vektor.Keindahan implementasi ini adalah kekuatan yang Anda dapatkan dari ekspresi lambda - Anda dapat menggunakan pendekatan ini untuk lebih banyak hal daripada hanya mencetak vektor.
sumber
Cukup salin wadah ke konsol.
Haruskah output:
sumber
Masalahnya mungkin dalam lingkaran sebelumnya:
(x = 17; isalpha(firstsquare); x++)
. Loop ini tidak akan berjalan sama sekali (jikafirstsquare
non-alpha) atau akan berjalan selamanya (jika itu alpha). Alasannya adalah itufirstsquare
tidak berubah sebagaimanax
bertambah.sumber
Di C ++ 11, rentang berbasis untuk loop mungkin merupakan solusi yang baik:
Keluaran:
sumber
Menggunakan
std::copy
tetapi tanpa pemisah tambahan tambahanAlternatif / pendekatan yang dimodifikasi menggunakan
std::copy
(seperti yang awalnya digunakan dalam jawaban @JoshuaKravtiz ) tetapi tanpa menyertakan tambahan pemisah tambahan setelah elemen terakhir:Contoh penggunaan yang diterapkan pada wadah jenis POD khusus:
sumber
operator kelebihan beban <<:
Pemakaian:
sumber
Saya melihat dua masalah. Seperti yang ditunjukkan di
for (x = 17; isalpha(firstsquare); x++)
sana, apakah ada loop tak terbatas atau tidak pernah dieksekusi sama sekali, dan jugaif (entrance == 'S')
jika karakter pintu masuk berbeda dari 'S' maka tidak ada yang didorong ke path vektor, membuatnya kosong dan dengan demikian tidak mencetak apa pun di layar. Anda dapat menguji yang terakhir untuk memeriksapath.empty()
atau mencetakpath.size()
.Either way, bukankah lebih baik menggunakan string daripada vektor? Anda dapat mengakses konten string seperti array juga, mencari karakter, mengekstraksi substring dan mencetak string dengan mudah (tanpa loop).
Melakukan semuanya dengan string mungkin merupakan cara untuk membuatnya ditulis dengan cara yang tidak berbelit-belit dan lebih mudah untuk menemukan masalahnya.
sumber
Jawaban ini didasarkan pada jawaban dari Zorawar, tetapi saya tidak dapat meninggalkan komentar di sana.
Anda dapat membuat const versi otomatis (C ++ 11) / typedef dengan menggunakan cbegin dan cend sebagai gantinya
sumber
Di C ++ 11``
sumber
sumber
Ini bekerja untuk saya:
sumber
Bagi mereka yang tertarik: Saya menulis solusi umum yang mengambil yang terbaik dari kedua dunia, lebih digeneralisasi untuk semua jenis rentang dan menempatkan tanda kutip di sekitar tipe non-aritmatika (diinginkan untuk tipe seperti string). Selain itu, pendekatan ini seharusnya tidak memiliki masalah ADL dan juga menghindari 'kejutan' (karena ditambahkan secara eksplisit berdasarkan kasus per kasus):
Sekarang cukup mudah digunakan pada rentang apa pun:
Cek seperti string menyisakan ruang untuk perbaikan. Saya juga harus
static_assert
memeriksa solusi saya untuk menghindaristd::basic_string<>
, tetapi saya meninggalkannya di sini untuk kesederhanaan.sumber
Anda dapat menulis fungsi Anda sendiri:
sumber
Untuk orang yang menginginkan one-liner tanpa loop:
Saya tidak percaya bahwa tidak ada seorang pun yang berpikir demikian, tetapi mungkin itu karena pendekatan yang lebih mirip C. Bagaimanapun, sangat aman untuk melakukan ini tanpa loop, dalam satu-liner, MENANGGUNG bahwa
std::vector<char>
null-terminated:Tapi saya akan membungkus ini di
ostream
operator, seperti yang disarankan @Zorawar, agar aman:Kita dapat mencapai perilaku serupa dengan menggunakan
printf
sebagai gantinya:CATATAN:
ostream
Operator kelebihan beban harus menerima vektor sebagai non-const. Ini mungkin membuat program tidak aman atau memperkenalkan kode yang salah. Juga, karena karakter-nol ditambahkan, realokasi yangstd::vector
mungkin terjadi. Jadi menggunakan for-loop dengan iterator kemungkinan akan lebih cepat.sumber
fprintf(stdout, "%s\n", &test[0]);
tidak berbeda daristd::cout << test.data()
, keduanya membutuhkan vektor yang diakhiri dengan nol. 2. "Tapi saya akan membungkus ini di operator ostream"<<
operator yang memodifikasi operan yang tepat adalah ide yang sangat buruk.fprintf(stdout, "%s\n", &test[0]);
kode dalam waktu lama tanpa pernah memberi saya masalah. Menarik! Dan saya setuju bahwa tidak begitu baik untuk memodifikasi vektor diostream
operator, tapi saya tidak suka perulangan secara manual dan menggunakan iterator. Entah bagaimana saya merasa untuk operasi sederhana seperti mencetakstd::vector<char>
perpustakaan standar harus menyembunyikan hal-hal ini. Tapi C ++ terus berkembang, mungkin akan segera hadir.