Set (множество) — это ассоциативный контейнер STL, хранящий отсортированный набор уникальных объектов. Сортировка осуществляется с использованием функции сравнения Compare (по умолчанию, в качестве функции сравнения, используется std::less<Key>). [4]
Контейнеры multiset похожи на множества в том, что являются ассоциативными контейнерами, содержащими отсортированный набор объектов, но в контейнерах multiset объекты могут дублироваться. [5]
Ниже представлен код программы, которая выводит все уникальные года, содержащиеся в файле, и выводит количество повторений вводимого года с помощью функции count.
#include <set>
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
ifstream in ("input.txt");
set<int> st;
multiset<int> mst;
/*Считывание данных*/
while (!in.eof()){
int x;
in>>x;
st.insert (x);
mst.insert (x);
}
in.close();
ofstream out ("output.txt");
/* уникальные года */
out<<"set:\n";
for (set<int>::iterator iter=st.begin (); iter!= st.end (); ++iter){
out<<*iter<<" ";
}
out.close();
/*по заданному году вывести количество*/
int year;
cout<<"enter year: ";
cin>>year;
cout<<"count of "<<year<<": "<<mst.count(year)<<endl;
return 0;
}
Содержимое входного файла:
2000 2001 2000 2004 2005 2006 2007 2000 2009
Результат работы программы:
enter year: 2000
count of 2000: 3
Отображения и мультиотображения
Ассоциативные массивы (Maps, отображения) — это сортированные ассоциативные контейнеры которые содержат уникальные пары ключ/значение.[6]
Отображения и мультиотображения отличаются только тем, что последние могут содержать дубликаты, а первые — нет. [1]
Ниже представлен листинг программы, которая выводит год по заданному имени, используя отображение, и список годов, используя мультиотображение.
|
#include <iostream>
#include <fstream>
#include <map>
#include <string>
using namespace std;
int main ()
{
fstream in ("input_task1.txt");
map<string,int> mp;
multimap<string,int> mmp;
/*заполнение map и multimap*/
while (!in.eof()){
string name;
in>>name;
int year;
in>>year;
mp.insert(map<string,int>::value_type(name,year));
mmp.insert(multimap<string,int>::value_type(name,year));
}
in.close();
/*вывести по заданному имени год (map)*/
string find_name_mp;
cout<<"enter name (for map): ";
cin>>find_name_mp;
cout<<mp[find_name_mp]<<endl;
/*список годов (multimap)*/
string find_name_mmp;
cout<<"enter name (for multimap): ";
cin>>find_name_mmp;
for (multimap<string,int>::iterator iter = mmp.find (find_name_mmp); iter!= mmp.end() && iter->first == find_name_mmp; ++iter){
cout<<iter->second <<endl;
}
return 0;
}
Содержимое входного файла:
Name1 2000
Name2 2001
Name3 2000
Name4 2004
Name2 2011
Name5 2005
Name6 2006
Name7 2007
Name2 2012
Name8 2000
Name9 2009
Результат работы программы:
enter name (for map): Name2
enter name (for multimap): Name2
Строки
Строковые классы стандартной библиотеки C++ позволяют работать со строками как с обычными типами, не создающими проблем для пользователей.
Это означает, что строки можно копировать, присваивать и сравнивать как базовые типы, не беспокоясь о возможной нехватке памяти или размерах внутреннего блока, предназначенного для хранения символов. Тип string представляет последовательности символов способом, совместимым с алгоритмами и соглашениями STL. [1], [2]
Ниже представлен код программы, демонстрирующей работу класса string и применение к нему алгоритмов STL.
#include <string>
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
int main()
{
ifstream in ("input_task3.txt");
string s;
getline(in,s);
in.close();
ofstream out ("output.txt");
|
out<<"input file: \n"<<s<<"\n\n";
/*substr. Выделение подстроки между первым и последним пробелами*/
string::size_type left_space = s.find (" ");
string::size_type right_space = s.rfind (" ");
string s_sub = s.substr (left_space, right_space - left_space);
out<<"substr (between first space and last
space):\n"<<s_sub<<"\n\n";
/*insert. Вставка подстроки в начало основной строки*/
string s_ins = s;
s_ins.insert (0, s_sub + " ");
out<<"insert of a substr in pos 0:\n"<<s_ins<<"\n\n";
/*append. Сложение строки и подстроки*/
string s_app = s;
s_app.append (s_sub);
out<<"append() (input string and substr)\n"<<s_app<<"\n\n";
/*copy. Копирование символов строки класса string в строку типа
char* */
char buf[500];
memset (buf, '\0', 500);
s.copy (buf, s.length(), 0);
out<<"copy() (input string to char)\n"<<buf<<"\n\n";
/*erase. Удаение подстроки из основной строки*/
string s_er=s;
s_er.erase(left_space, right_space - left_space);
out<<"erase substr between first space and last
space:\n"<<s_er<<"\n\n";
/*compare.Сравнивание строки и подстроки*/
int res=s.compare(s_sub);
out<<"compare (input string and substr):\n"<<res<<"\n\n";
/*swap.Меняет строки местами*/
string first("This is first string");
string second ("This is second string");
out<<"before swap():\n"<<first<<endl<<second<<endl;
first.swap (second);
out<<"after swap():\n"<<first<<endl<<second<<"\n\n";
/*find. Поиск первого вхожения слова 'Iterator', начиная слева*/
string::size_type pos_find = s.find("Iterator", 0);
out<<"first 'Iterator' at "<<pos_find;
/*rfind. Поиск первого вхожения слова 'Iterator', начиная справа*/
string::size_type pos_rfind = s.rfind("Iterator", s.length());
out<<"\nlast 'Iterator' at "<<pos_rfind<<"\n\n";
out.close();
return 0;
}
Содержимое входного файла:
There are five kinds of iterators: Input Iterator, Output Iterator, Forward Iterator, Bidirectional Iterator, and Random Access Iterator.
|
Результат работы программы:
input file:
There are five kinds of iterators: Input Iterator, Output Iterator, Forward Iterator, Bidirectional Iterator, and Random Access Iterator.
substr (between first space and last space):
are five kinds of iterators: Input Iterator, Output Iterator, Forward Iterator, Bidirectional Iterator, and Random Access
insert of a substr in pos 0:
are five kinds of iterators: Input Iterator, Output Iterator, Forward Iterator, Bidirectional Iterator, and Random Access There are five kinds of iterators: Input Iterator, Output Iterator, Forward Iterator, Bidirectional Iterator, and Random Access Iterator.
append() (input string and substr)
There are five kinds of iterators: Input Iterator, Output Iterator, Forward Iterator, Bidirectional Iterator, and Random Access Iterator. are five kinds of iterators: Input Iterator, Output Iterator, Forward Iterator, Bidirectional Iterator, and Random Access
copy() (input string to char)
There are five kinds of iterators: Input Iterator, Output Iterator, Forward Iterator, Bidirectional Iterator, and Random Access Iterator.
erase substr between first space and last space:
There Iterator.
compare (input string and substr):
before swap():
This is first string
This is second string
after swap():
This is second string
This is first string
first 'Iterator' at 41
last 'Iterator' at 128
Потоки ввода-вывода
В C++ операции ввода-вывода выполняются при помощи потоков данных. Согласно принципам объектно-ориентированного программирования, поток данных представляет собой объект, свойства которого определяется классом. Вывод интерпретируется как запись данных в поток, а ввод — как чтение данных из потока. Для стандартных каналов ввода-вывода существуют стандартные глобальные объекты. [1]
Ниже приведён листинг программы, демонстрирующий использование потоков ввода-вывода.
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
/*функция, считывающая целые числа из потока ввода и копирующая их в вектор*/
void readVector(vector<int> &v, istream &in) {
v.clear();
int a;
while (in>>a){
v.push_back (a);
}
}
/*функция, записывающая целые числа из вектора в поток вывода*/
void printVector(vector<int> &v, ostream &out) {
for (vector<int>::iterator iter=v.begin(); iter!= v.end(); ++iter){
out<<*iter << " ";
}
out << endl;
}
int main ()
{
vector<int> vec;
/*заполнение вектора, в качестве аргумента передаётся cin*/
cout<<"enter vector: ";
readVector(vec, cin);
/*вывод элементов вектора в поток cout*/
printVector(vec, cout);
/*заполнение вектора, в качестве аргумента передаётся файловый
поток fin*/
ifstream fin("input_task2.txt");
readVector(vec, fin);
fin.close();
/*вывод элементов вектора в файловый поток fout*/
ofstream fout("output.txt");
printVector(vec, fout);
fout.close();
/*передача строки в строковый поток ввода*/
istringstream sstr_in("23 56 56 45 64 23 34");
readVector(vec, sstr_in);
/*вывод элементов вектора в строковый поток и вывод строки в поток
cout*/
ostringstream sstr_out;
printVector(vec, sstr_out);
cout << "string: " << sstr_out.str();
if (true) return 0;
}
Содержимое входного файла:
1990 2000 2010 2020 2030 2040 2050
Содержимое файла output.txt:
1990 2000 2010 2020 2030 2040 2050
Результат работы программы:
enter vector: 1 2 3^D
1 2 3
string: 23 56 56 45 64 23 34
Итераторы
Итераторы призваны предоставлять доступ к членам контейнеров, они могут быть использованы способом, похожим на манипуляции указателями. Например, можно использовать итератор для прохода по всем элементам вектора. Есть несколько разных типов итераторов:
· input_iterator (для чтения). Читают значения с движением вперед. Могут быть инкрементированы, сравнены и разыменованы.
· output_iterator (для записи). Пишут значения с движением вперед. Могут быть инкрементированы и разыменованы.
· forward_iterator (однонаправленные). Читают или пишут значения с движением вперед. Комбинируют функциональность предыдущих двух типов с возможностью сохранять значение итератора.
· bidirectional_iterator (двунаправленные). Читают и пишут значения с движением вперед или назад. Похожи на однонаправленные, но их также можно инкрементировать и декрементировать.
· random_iterator (с произвольным доступом). Читают и пишут значения с произвольным доступом. Самые мощные итераторы, сочетающие функциональность двунаправленных итераторов и возможность выполнения арифметики указателей и сравнений указателей.
· reverse_iterator (обратные). Или итераторы с произвольным доступом, или двунаправленные, движущиеся в обратном направлении.
Каждый класс контейнеров связан с типом итератора, и каждый из алгоритмов STL использует определенный тип итератора.
Например, векторы связаны с итераторами с произвольным доступом, значит, они могут использовать алгоритмы, требующие произвольного доступа. Так как итераторы с произвольным доступом включают в себя все свойства других итераторов, то векторы также могут использовать алгоритмы, написанные для других итераторов. [7]
Ниже представлен листинг программы, которая содержит алгоритмы, использующие разные типы итераторов.
#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
#include <fstream>
using namespace std;
int main ()
{
vector <int> vec;
ifstream in("input_task2.txt");
while (!in.eof()){
int x;
in>>x;
vec.push_back (x);
}
in.close();
/*copy() использует InputIterator и OutputIterator для считывания
из потока и зпаиси в поток*/
copy (istream_iterator<int>(cin), istream_iterator<int>(),
ostream_iterator <int>(cout, " "));
ofstream out("output.txt");
out<<"vector:\n";
for (vector <int>::iterator iter = vec.begin (); iter!= vec.end();
++iter){
out<<*iter<<" ";
}
/*max_element использует input iterator*/
vector<int>::iterator max_it = max_element(vec.begin (),
vec.end());
out<<"\n\ninput iterator\nmax: "<<*max_it<<"\n\n";
/*generate_n использует output iterator*/
vector <int> vec_temp(vec);
generate_n(vec_temp.begin (), vec_temp.size(), rand);
out<<"output iterator\ngenerate rand():\n";
for (vector <int>::iterator iter = vec_temp.begin (); iter!=
vec_temp.end(); ++iter){
out<<*iter<<" ";
}
/*fill использует forward iterator*/
out<<"\n\nforward iterator:\nfill():\n";
fill (vec_temp.begin (), vec_temp.end(), 1);
for (vector <int>::iterator iter = vec_temp.begin (); iter!=
vec_temp.end(); ++iter){
out<<*iter<<" ";
}
/*reverse использует bidirectional iterator*/
out<<"\n\nbidirectional iterator:\n"<<"reverse():\n";
vector <int> vec_temp1(vec);
reverse (vec_temp1.begin(), vec_temp1.end());
for (vector <int>::iterator iter = vec_temp1.begin (); iter!=
vec_temp1.end(); ++iter){
out<<*iter<<" ";
}
/*random_shuffle использует random access iterator*/
out<<"\n\nrandom access iterator:\n";
random_shuffle (vec.begin(), vec.end ());
for (vector <int>::iterator iter = vec.begin (); iter!= vec.end();
++iter){
out<<*iter<<" ";
}
out.close();
return 0;
}
Содержимое входного файла:
1990 2000 2010 2020 2030 2040 2050
Результат работы программы:
vector:
1990 2000 2010 2020 2030 2040 2050
input iterator
max: 2050
output iterator
generate rand():
41 18467 6334 26500 19169 15724 11478
forward iterator:
fill():
1 1 1 1 1 1 1
bidirectional iterator:
reverse():
2050 2040 2030 2020 2010 2000 1990
random access iterator:
2030 2010 1990 2000 2020 2040 2050