Множества и мультимножества




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

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-08-07 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: