C++ iteratorlar
C++ iteratorlar
Iteratorlar ma’lumotlar tuzilmalari (vektorlar, set’lar va h.k.) elementlarini "ko‘rsatish" orqali ularga murojaat qilish va ular bo‘ylab iteratsiya qilish (aylanib chiqish) uchun ishlatiladi.
U "iterator" deb ataladi, chunki "iteratsiya" — sikl yordamida aylanib chiqish uchun ishlatiladigan texnik atama.
Vektor bo‘ylab iteratsiya qilish uchun quyidagi misolga qarang:
Misol
// Create a vector called cars that will store strings
vector<string> cars = {"Volvo", "BMW", "Ford", "Mazda"};
// Create a vector iterator called it
vector<string>::iterator it;
// Loop through the vector with the iterator
for (it = cars.begin(); it != cars.end(); ++it) {
cout << *it << "\n";
}
O‘zingiz sinab ko‘ring »
Misol izohi
- Avval turli avtomobil ishlab chiqaruvchilarining nomlarini saqlash uchun stringlardan iborat vektor yaratamiz.
- So‘ng vektor bo‘ylab aylanib chiqishda foydalanadigan
itnomli "vektor iteratori"ni yaratamiz. - Keyin iterator yordamida vektor bo‘ylab aylanib chiqish uchun
forsiklidan foydalanamiz. Iterator (it) vektordagi birinchi elementni (cars.begin()) ko‘rsatadi va siklitqiymaticars.end()ga teng bo‘lmaguncha davom etadi. - Inkrement operatori (
++it) iteratorni vektordagi keyingi elementga suradi. - Dereference operatori (
*it) iterator ko‘rsatib turgan elementga murojaat qiladi.
Eslatma: Iteratorning tipi u aylanib chiqadigan ma’lumotlar tuzilmasining tipiga mos kelishi kerak (bizning misolimizda string)
begin() va end() nima?
begin() va end() — vektorlar va list’lar kabi ma’lumotlar tuzilmalariga tegishli funksiyalardir. Ular iteratorning o‘ziga tegishli emas. Aksincha, ular ushbu ma’lumotlar tuzilmalarining elementlariga murojaat qilish va ular bo‘ylab iteratsiya qilish uchun iteratorlar bilan birga ishlatiladi.
begin()ma’lumotlar tuzilmasining birinchi elementini ko‘rsatuvchi iteratorni qaytaradi.end()oxirgi elementdan keyingi bitta pozitsiyani ko‘rsatuvchi iteratorni qaytaradi.
Ular qanday ishlashini tushunish uchun misol sifatida vektorlardan foydalanishda davom etamiz:
vector<string> cars = {"Volvo", "BMW", "Ford", "Mazda"};
vector<string>::iterator it;
begin() misollari
begin() vektordagi birinchi elementni (0-indeks, ya’ni "Volvo") ko‘rsatadi:
Ikkinchi elementni (BMW) ko‘rsatish uchun
cars.begin() + 1 deb yozishingiz mumkin:
Va, albatta, bu uchinchi elementni
cars.begin() + 2 bilan ko‘rsatish mumkinligini ham anglatadi:
end() misoli
end() vektordagi oxirgi elementdan keyingi bitta pozitsiyani ko‘rsatadi (ya’ni u haqiqiy elementni ko‘rsatmaydi, balki vektorning oxiri shu yerda ekanini bildiradi).
Demak, end() yordamida cars vektoridagi oxirgi elementni (Mazda) ko‘rsatish uchun cars.end() - 1 dan foydalanishingiz mumkin:
Nega "ko‘rsatadi" deymiz?
Iteratorlar "ko‘rsatkichlar (pointers)"ga o‘xshaydi: ular ma’lumotlar tuzilmasidagi elementlardan qiymat qaytarmaydi, balki ularni "ko‘rsatadi". Ular muayyan pozitsiyaga ishora qiladi va kerak bo‘lganda qiymatning nusxasini olmasdan unga murojaat qilish hamda uni o‘zgartirish imkonini beradi. Masalan:
Misol
// Point to the first element in the vector
it = cars.begin();
// Modify the value of the first element
*it = "Tesla";
// Volvo is now Tesla
O‘zingiz sinab ko‘ring »
auto kalit so‘zi
C++ 11 va undan keyingi versiyalarda iteratorning tipini aniq e’lon qilib ko‘rsatish o‘rniga auto kalit so‘zidan foydalanishingiz mumkin.
auto kalit so‘zi kompilyatorga to‘g‘ri ma’lumot tipini avtomatik aniqlash imkonini beradi, bu esa kodni soddalashtiradi va uni o‘qishni osonlashtiradi:
Buning o‘rniga:
vector<string>::iterator it = cars.begin();
Yuqoridagi misolda kompilyator it ning tipini cars.begin() qaytaradigan tipga, ya’ni vector<string>::iterator ga qarab aniqlaydi.
auto kalit so‘zi for sikllarida ham ishlaydi:
for (auto it = cars.begin(); it != cars.end(); ++it) {
cout << *it << "\n";
}
O‘zingiz sinab ko‘ring »
for-each sikli va iteratorlar
Ma’lumotlar tuzilmasining elementlarini shunchaki aylanib chiqish uchun for-each siklidan quyidagicha foydalanishingiz mumkin:
Misol
// Create a vector called cars that will store strings
vector<string> cars = {"Volvo", "BMW", "Ford", "Mazda"};
// Print vector elements
for (string car : cars) {
cout << car << "\n";
}
O‘zingiz sinab ko‘ring »
Agar elementlarni faqat o‘qiyotgan bo‘lsangiz va ularni o‘zgartirish kerak bo‘lmasa, for-each sikli iteratorlarga qaraganda ancha sodda va tushunarli.
Biroq iteratsiya davomida elementlarni qo‘shish, o‘zgartirish yoki o‘chirish, teskari tartibda aylanib chiqish yoki ayrim elementlarni o‘tkazib yuborish kerak bo‘lsa, iteratorlardan foydalanishingiz kerak:
Misol
// Create a vector called cars that will store strings
vector<string> cars = {"Volvo", "BMW", "Ford", "Mazda"};
// Loop through vector elements
for (auto it = cars.begin(); it != cars.end(); ) {
if (*it == "BMW") {
it = cars.erase(it); // Remove the BMW element
} else {
++it;
}
}
// Print vector elements
for (const string& car : cars) {
cout << car << "\n";
}
O‘zingiz sinab ko‘ring »
Teskari tartibda aylanib chiqish
Teskari tartibda aylanib chiqish uchun begin() va end() o‘rniga rbegin() va rend() dan foydalanishingiz mumkin:
Misol
// Iterate in reverse order
for (auto it = cars.rbegin(); it != cars.rend(); ++it) {
cout << *it << "\n";
}
O‘zingiz sinab ko‘ring »
Boshqa ma’lumotlar tuzilmalarini aylanib chiqish
Iteratorlar kodni qayta ishlatish uchun juda qulay, chunki vektorlar, list’lar, deque’lar, set’lar va map’larni aylanib chiqishda bir xil sintaksisdan foydalanishingiz mumkin:
list misoli
// Create a list called cars that will store strings
list<string> cars = {"Volvo", "BMW", "Ford", "Mazda"};
// Loop through the list with an iterator
for (auto it = cars.begin(); it != cars.end(); ++it) {
cout << *it << "\n";
}
O‘zingiz sinab ko‘ring »
deque misoli
// Create a deque called cars that will store strings
deque<string> cars = {"Volvo", "BMW", "Ford", "Mazda"};
// Loop through the deque with an iterator
for (auto it = cars.begin(); it != cars.end(); ++it) {
cout << *it << "\n";
}
O‘zingiz sinab ko‘ring »
set misoli
// Create a set called cars that will store strings
set<string> cars = {"Volvo", "BMW", "Ford", "Mazda"};
// Loop through the set with an iterator
for (auto it = cars.begin(); it != cars.end(); ++it) {
cout << *it << "\n";
}
O‘zingiz sinab ko‘ring »
map misoli
// Create a map that will store strings and integers
map<string, int> people = { {"John", 32}, {"Adele", 45}, {"Bo", 29} };
// Loop through the map with an iterator
for (auto it = people.begin(); it != people.end(); ++it) {
cout << it->first << " is: " << it->second << "\n";
}
O‘zingiz sinab ko‘ring »
Iteratorlarni qo‘llab-quvvatlash
Yuqoridagi misollar iteratorlarni qo‘llab-quvvatlaydigan turli ma’lumotlar tuzilmalarini qanday aylanib chiqishni ko‘rsatadi (vector, list, deque, map va set iteratorlarni qo‘llab-quvvatlaydi, steklar va navbatlar esa qo‘llab-quvvatlamaydi).
Algoritmlar
Iteratorlarning yana bir muhim xususiyati shundaki, ular ma’lumotlar tuzilmasidagi elementlarni saralash va qidirish uchun sort() va find() kabi turli algoritm funksiyalari (<algorithm> kutubxonasida joylashgan) bilan birga ishlatiladi.
Masalan, sort() funksiyasi ma’lumotlar tuzilmasidagi elementlarni boshidan oxirigacha saralash uchun parametr sifatida iteratorlarni (odatda begin() va end() qaytaradigan) qabul qiladi.
Ushbu misolda elementlar string bo‘lgani uchun alifbo tartibida saralanadi:
Misol
#include <iostream>
#include <vector>
#include <algorithm> // Include the <algorithm> library
using namespace std;
int main() {
// Create a vector called cars that will store strings
vector<string> cars = {"Volvo", "BMW", "Ford", "Mazda"};
// Sort cars in alphabetical order
sort(cars.begin(), cars.end());
// Print cars in alphabetical order
for (string car : cars) {
cout << car << "\n";
}
return 0;
}
O‘zingiz sinab ko‘ring »
Bu misolda esa elementlar butun son bo‘lgani uchun son qiymati bo‘yicha saralanadi:
Misol
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
// Create a vector called numbers that will store integers
vector<int> numbers = {1, 7, 3, 5, 9, 2};
// Sort numbers numerically
sort(numbers.begin(), numbers.end());
for (int num : numbers) {
cout << num << "\n";
}
return 0;
}
O‘zingiz sinab ko‘ring »
Tartibni teskarisiga o‘zgartirish uchun begin() va end() o‘rniga rbegin() va rend() dan foydalanishingiz mumkin:
Misol
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
// Create a vector called numbers that will store integers
vector<int> numbers = {1, 7, 3, 5, 9, 2};
// Sort numbers numerically in reverse order
sort(numbers.rbegin(), numbers.rend());
for (int num : numbers) {
cout << num << "\n";
}
return 0;
}
O‘zingiz sinab ko‘ring »
W3Schools Pathfinder
Yutuqlaringizni kuzating – bu bepul!
