Pustaka standar C ++ tidak hanya menawarkan serangkaian kelas, tetapi juga menentukan bagaimana program ditulis. Artikel ini membahas persyaratan umum untuk mengimplementasikan program menggunakan STL.
Pertimbangkan tugas berikut:
Baca array bilangan bulat yang dipisahkan oleh whitespace dari file input.txt. Sortir dan tulis ke output.txt
Anda dapat menulis solusi berikut:
#include <vector> #include <algorithm> #include <fstream> int main(){ // input.txt std::ifstream fin("input.txt"); // output.txt std::ofstream fout("output.txt"); // std::vector<int> v; // , std::copy(std::istream_iterator<int>(fin), std::istream_iterator<int>(), std::inserter(v, v.end())); // std::sort(v.begin(), v.end()); // , std::copy(v.begin(), v.end(), std::ostream_iterator<int>(fout, " ")); return 0; }
Beberapa kata tentang "sihir" dalam kode:
- Salah satu fondasi perpustakaan adalah iterator, serta setengah interval yang mereka tentukan. Dengan semantik (baca - oleh perilaku) mereka bertepatan dengan pointer. Yaitu, operator dereferencing * akan mengembalikan kepada Anda elemen yang dirujuk oleh iterator, ++ akan menerjemahkan iterator ke elemen berikutnya. Secara khusus, setiap wadah diwakili oleh iterator ujungnya [mulai, akhir), di mana mulai menunjuk ke elemen pertama, ujung - untuk yang terakhir ;
- Algoritma yang bekerja dengan wadah, karena parameter mengambil awal dan akhir wadah (atau bagiannya);
- Algoritma salin menyalin hanya menulis ulang elemen dari satu setengah interval ke yang lain. Jika tidak ada memori yang dialokasikan dalam wadah target, perilaku tidak dapat diprediksi [ salinan ];
- Fungsi inserter memasukkan nilai ke dalam wadah sebelum iterator yang ditentukan [ inserter ]
- istream_iterator dan ostream_iterator menyediakan akses gaya wadah ke stream [ istream_iterator , ostream_iterator ]
Contoh ini sebenarnya cukup sederhana. Namun, ia dapat membantu kami dalam memecahkan masalah berikut:
File input.txt berisi daftar yang berisi informasi tentang orang-orang: nama belakang, nama depan, usia (setiap baris adalah catatan, data dipisahkan oleh spasi). Baca data ini ke dalam array, urutkan berdasarkan usia dan tulis ke file output.txt. Tampilkan informasi tentang seseorang yang usianya lebih dari 20 tetapi kurang dari 25 tahun.
Pada prinsipnya, solusinya akan hampir sama. Namun, untuk menyelamatkan keputusan tersebut, perlu dilakukan pekerjaan persiapan, yaitu:
- Deklarasikan struktur data. - Anda dapat mendefinisikan sesuatu yang bermanfaat, tetapi dalam kasus tertentu, struct cukup:
struct man{ std::string firstname, secondname; size_t age; };
Saya sangat menyarankan agar Anda mempertimbangkan implementasi copy constructor, dengan parameter default dan operator fotokopi. Dengan pengembangan lebih lanjut dari proyek ini, Anda pasti akan membutuhkannya. - Operator I / O yang berlebihan - operator ini dimanipulasi oleh iterator melalui utas. Bagaimanapun, itu lebih umum untuk menggunakannya.
std::ostream& operator << (std::ostream& out, const man& p){ out << p.firstname << " " << p.secondname << " " << p.age; return out; } std::istream& operator >> (std::istream& in, man& p){ in >> p.firstname >> p.secondname >> p.age; return in; }
- Tetapkan aturan untuk memesan objek - Ini sudah merupakan perluasan besar: Anda dapat mengganti operator <, Anda dapat menggambarkan fungsi, functor atau ekspresi lambda. Dalam hal ini, gunakan fungsinya.
bool comparator(const man& p1, const man& p2){ return p1.age < p2.age; }
- Tetapkan aturan untuk memilih objek - Sekali lagi, pilihan implementasi yang cukup besar. Kali ini, biarkan ada functor (objek kelas di mana operator kurung [ functor ] didefinisikan) di mana Anda dapat melewati rentang usia:
struct predicate{ size_t begin, end; predicate(int p1, int p2): begin(p1), end(p2) {} bool operator ()(const man& p){ return (p.age > begin) && (p.age < end); } };
Perhatikan konstruktor functor - dengan cara ini kita dapat menyesuaikan perilakunya.
Sebenarnya, titik masuk ke program:
int main(){ std::ifstream fin("input.txt"); std::ofstream fout("output.txt"); std::vector<man> v; std::copy(std::istream_iterator<man>(fin), std::istream_iterator<man>(), std::inserter(v, v.end())); std::sort(v.begin(), v.end(), comparator); std::copy_if(v.begin(), v.end(), std::ostream_iterator<man>(std::cout, "\n"), predicate(20, 25)); std::copy(v.begin(), v.end(), std::ostream_iterator<man>(fout, "\n")); return 0; }
Seperti yang Anda lihat, perubahan pada fungsi utama minimal, hanya memengaruhi jenis elemen vektor. Plus menambahkan panggilan ke algoritma copy_if. Algoritma yang bermanfaat ini muncul dengan standar C ++ 11, yang menyalin elemen dari satu wadah ke hanya elemen yang memenuhi syarat.
Kesimpulan apa yang bisa ditarik dari ini?- Mengetahui dan secara aktif menggunakan algoritma perpustakaan standar secara signifikan mempercepat pengembangan (lebih tepatnya, itu mengarah pada automatisme).
- Mendeklarasikan berbagai konstruktor dan menyalin operator untuk struktur data berguna. Mereka digunakan dalam berbagai situasi, khususnya saat memasukkan elemen ke dalam wadah.
- Untuk kenyamanan, Anda dapat membebani operator input dan output, serta operator perbandingan dan operator pemesanan.
- Functors - alat yang ampuh yang memungkinkan Anda untuk mengimplementasikan fungsi dengan "memori" atau perilaku tambahan
- ... mungkin lebih ...
Terima kasih telah bertahan!
Semua kode program:an_example.cpp #include <string> #include <vector> #include <fstream> #include <algorithm> #include <iostream> #include <iterator> struct man{ std::string firstname, secondname; size_t age; }; std::ostream& operator << (std::ostream& out, const man& p){ out << p.firstname << " " << p.secondname << " " << p.age; return out; } std::istream& operator >> (std::istream& in, man& p){ in >> p.firstname >> p.secondname >> p.age; return in; } bool comparator(const man& p1, const man& p2){ return p1.age < p2.age; } struct predicate{ size_t begin, end; predicate(int p1, int p2): begin(p1), end(p2) {} bool operator ()(const man& p){ return (p.age > begin) && (p.age < end); } }; int main(){ std::ifstream fin("input.txt"); std::ofstream fout("output.txt"); std::vector<man> v; std::vector<man>::iterator i; std::copy(std::istream_iterator<man>(fin), std::istream_iterator<man>(), std::inserter(v, v.end())); std::sort(v.begin(), v.end(), comparator); std::copy_if(v.begin(), v.end(), std::ostream_iterator<man>(std::cout, "\n"), predicate(20, 25)); std::copy(v.begin(), v.end(), std::ostream_iterator<man>(fout, "\n")); return 0; }
Daftar Pustaka:- Stepanov Al. Lee Meng, Perpustakaan Template Standar, 1995
- Referensi CPP, salin
- Referensi CPP, inserter
- Referensi CPP, istream_iterator
- Referensi CPP, ostream_iterator
- Wiki functor