- PVSM.RU - https://www.pvsm.ru -
Стандартная библиотека С++ предлагает не только набор классов, но также определяет способ написания программ. В рамках данной статьи рассматриваются общие требования к реализации программ при помощи STL.
Рассмотрим следующую задачу:
Считать из файла input.txt массив целых чисел, разделенных пробельными символами. Отсортировать их и записать в файл output.txt
Можно написать следующее решение:
#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;
}
Несколько слов о «магии» в коде:
Этот пример, на самом деле, довольно прост. Однако он может нам помочь в решении следующей задачи:
В файле input.txt хранится список, содержащий информацию о людях: фамилия, имя, возраст (каждая строка это запись, данные разделены пробелом). Считать эти данные в массив, отсортировать их по возрасту и записать в файл output.txt. Вывести на экран информацию о человеке, чей возраст более 20, но менее 25 лет.
В принципе, решение будет практически таким же. Однако, для сохранения решения необходимо провести подготовительную работу, а именно:
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::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;
}
Как можно заметить, изменения функции main минимальные, касаются только типа элементов вектора. Плюс добавлен вызов алгоритма copy_if. Этот полезный алгоритм появился со стандартом С++11, он копирует элементы из одного контейнера в дргой только те элементы, которые удовлетворяют условию.
Какие можно сделать из этого выводы?
Спасибо, что дотерпели!
Весь код программы:
#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;
}
Библиография:
Автор: mcroitor
Источник [12]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/c-3/302243
Ссылки в тексте:
[1] copy: #cppref1
[2] inserter: #cppref2
[3] istream_iterator: #cppref3
[4] ostream_iterator: #cppref4
[5] функтор: #wiki1
[6] Stepanov Al. Lee Meng, The Standard Template Library, 1995: http://stepanovpapers.com/STL/DOC.PDF
[7] CPP Reference, copy: https://en.cppreference.com/w/cpp/algorithm/copy
[8] CPP Reference, inserter: https://en.cppreference.com/w/cpp/iterator/inserter
[9] CPP Reference, istream_iterator: https://en.cppreference.com/w/cpp/iterator/istream_iterator
[10] CPP Reference, ostream_iterator: https://en.cppreference.com/w/cpp/iterator/ostream_iterator
[11] Wiki, функтор: https://ru.wikipedia.org/wiki/Функциональный_объект
[12] Источник: https://habr.com/post/433218/?utm_campaign=433218
Нажмите здесь для печати.