Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Результат_2012_02_09.docx
Скачиваний:
6
Добавлен:
20.04.2015
Размер:
593.36 Кб
Скачать

Задача 4. Удалить все нечетные элементы из массива (последующая оптимизация)

Теперь необходимо отметить, что STL имеет множество готовых функций. Для работы с этими функциями необходимо подключить #include <algorithm>. Одна из этих функций – remove_if, которая возвращает итератор на элементы, которые подходят под условие. В нашем случае (когда вектор чисел) этот итератор будет иметь тип vector<int>::iterator

  1. Для использования функции remove_if необходимо ввести функцию-предикат, которая будет указывать на необходимость удаления элемента

bool isOdd(int s) {

return s % 2 == 1;

}

  1. При вызове функции необходимо указать диапазон вектора, который надо проверять. В нашем случае это весь вектор – от начала (vector.begin()) до конца (vector.end()). Так же необходимо указать функцию, которая будет указывать на необходимость удаления эдемента – в нашем случае это функция isOdd

  2. Полученный итератор надо передать в функцию erase, указав окончание цепочки (оно совпадает с окончанием вектора, потому что проверяем весь вектор). Таким образом, главная функция обработки будет выглядить следующим образом:

void mainAction(vector<int> &data) {

vector<int>::iterator newEnd = remove_if(data.begin(),data.end(), isOdd);

data.erase(newEnd, data.end());

}

  1. Следует отметить, что данную функцию в Visual C++ можно сократить, используя ключевое слово auto (полный аналог var в C# - автоопределяемые типы) и анонимные функции (для замены функции isOdd). Тогда главная функция примет следующий вид:

void mainAction(vector<int> &data) {

auto newEnd = remove_if(data.begin(), data.end(),

[](int s) {return s % 2 == 1; });

data.erase(newEnd, data.end());

}

Еще раз отметим, что эти преобразования будут работать только в Visual C++, поскольку auto в других компиляторах С++ имеет другой смысл. Поэтому такими оптимизациями мы пользоваться не будем.

  1. Так же следует отметить, что с помощью итераторов можно сделать вывод вектора. Итератор указывает на элемент контейнера (вектора), поэтому для вывода значения элемента необходиом взять значение по адресу, на который указывает итератор. Поэтому операцию вывода можно так же реализовать следующим способом:

void printVector(char *caption, vector<int> &data) {

cout << caption << ": ";

for (vector<int>::iterator i = data.begin(); i != data.end(); ++i) {

cout << *i << " ";

}

cout << "\n";

}

  1. Приведем полный код решения задачи:

#include <vector>

#include <time.h>

#include <conio.h>

#include <iostream>

#include <algorithm>

using namespace std;

bool isOdd(int s) {

return s % 2 == 1;

}

void mainAction(vector<int> &data) {

vector<int>::iterator newEnd = remove_if(data.begin(),

data.end(), isOdd);

data.erase(newEnd, data.end());

}

int getCorrectValue() {

while (true) {

int size;

if (!(cin >> size)) {

cin.clear();

while(std::cin.get()!= '\n');

continue;

}

return size;

}

}

void printVector(char *caption, vector<int> &data) {

cout << caption << ": ";

for (int i = 0; i < data.size(); i++) {

cout << data[i] << " ";

}

cout << "\n";

}

int getRandValue(int max, int min) {

return (((double)rand())/RAND_MAX)*(max - min) + min;

}

void fillVector(vector<int> &data, int size) {

data.reserve(size);

for (int i = 0; i < size; i++) {

data.push_back(getRandValue(-5, 10));

}

}

int main(int argc, char* argv[]) {

srand(time(NULL));

cout << "enter array size: ";

int size = getCorrectValue();

if (size < 0) {

cout << "array size can not be negative number";

_getch();

return 1;

}

vector<int> data;

fillVector(data, size);

printVector("before process", data);

mainAction(data);

printVector("after process", data);

_getch();

return 0;

}