
- •Содержание Введение
- •Задача 1: Обнаружить учетку памяти
- •Задача 2. Составить тесты к программе
- •Задача 3: Напечатать все содержимое файла на экран.
- •Задача 3: Напечатать все содержимое файла на экран (оптимизация).
- •Задача 4. Удалить все нечетные элементы из массива
- •Задача4.Удалить все нечетные элементы из массива (оптимизация)
- •Задача 4. Удалить все нечетные элементы из массива (последующая оптимизация)
- •Задача 4. Удалить все нечетные элементы из массива (основа тестов)
- •Задача 5. В файле удалить все слова, которые начинаются и заканчиваются одной буквой
- •Задача 5. В файле удалить все слова, которые начинаются и заканчиваются одной буквой (без использования потоков и std::string)
- •Задача 6. Удалить строки, в которых есть два одинаковых элемента (без использования std::vector)
- •Задача 6. Удалить строки, в которых есть два одинаковых элемента (c использованием std::vector)
- •Задача 7. Отсортировать содержимое словаря
- •Задача 8. Реализовать сохранение и загрузку пользовательских структур данных с использованием fstream
- •Заключение Глоссарий
- •Список рекомендуемой литературы
Задача 6. Удалить строки, в которых есть два одинаковых элемента (c использованием std::vector)
Теперь решим эту задачу с использованием STL.
Логика программы «глобально» при оптимизации не изменится. В отличие от массива, у std::vector есть функция size(), которая возвращает размер вектора. Поэтому переменная size в классе MatrixString больше не нужна. С учетом этого содержимое файла MatrixString.h станет следующим:
#include <vector>
class MatrixString {
private:
std::vector<int> data;
int getRandValue(int max, int min);
int getCount(int element);
public:
MatrixString(int size_);
~MatrixString();
void print();
bool needDelete();
};
Следует отметить, что в конструкторе мы знаем размер вектора, который в конечном счете сформируется. Поэтому желательно зарезервировать необходимое количество элементов в векторе, что бы избежать лишних перевыделений памяти во время заполнения вектора. И это необходимо сделать в конструкторе.
MatrixString::MatrixString(int size) {
data.reserve(size);
for (int i = 0; i < size; i++) {
data.push_back(getRandValue(-10, 10));
}
}
Все остальные функции в MatrixString так же почти не изменятся, за исключением того, что везде size заменится на data.size().
Теперь рассмотрим изменение класса Matrix. По полной аналогии заменим MatrixString ** на std::vector<MatrixString *> и избавимся от переменной size. Теперь обратим внимание на то, что в MatrixString не осталось операторов new и new []. Поэтому у нас не будет проблем с динамической памятью. И теперь не надо контролировать вызов создания строки матрицы и можно заменить std::vector<MatrixString *> на std::vector<MatrixString> и таким образом избавится от операторов new, new[], delete, delete[]. С учетом этого содержимое файлов Matrix.h и Matrix.cpp станет следующим:
Содержимое файла Matrix.h:
Содержимое
#include <vector>
#include "MatrixString.h"
class Matrix {
private:
std::vector<MatrixString>strings;
void delByIndex(int index);
public:
Matrix(int sizeX, int sizeY);
void print();
void process();
};
СодержимоефайлаMatrix.cpp
#include "MatrixString.h"
#include "Matrix.h"
#include <stdio.h>
void Matrix::delByIndex(int index) {
strings.erase(strings.begin() + index, strings.begin() + index + 1);
}
Matrix::Matrix(int sizeX, int sizeY) {
strings.reserve(sizeY);
for (int i = 0; i < sizeY; i++) {
strings.push_back(MatrixString(sizeX));
}
}
void Matrix::print() {
for (int i = 0; i < strings.size(); i++) {
strings[i].print();
}
printf("\n");
}
void Matrix::process() {
for (int i = strings.size() - 1; i >= 0; i--) {
if (strings[i].needDelete()) {
delByIndex(i);
}
}
}
Содержимое lab2_1.cpp не изменится
Задача 7. Отсортировать содержимое словаря
Задача: в файле «in.txt» находится словарь. Каждая строка словаря содержит только одно слово. Необходимо в файл «out.txt» записать слова, отсортированные по алфавиту.
Логично предположить, что данная задача представима в виде последовательности трех действий:
Считывание строк из файла in.txt
Сортировка строк
Сохранение результатов в файл out.txt.
Первая подзадача уже разбиралась в 3й задаче, поэтому подробно на ней останавливаться не будем. Приведем код функции, которая отвечает за чтение всех строк из файла (обратите внимание на подключение fstream для работы с ifstream – input file stream):
#include <conio.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
int readFromFile(std::string dictionary_name, std::vector<string> &words) {
ifstream ifs(dictionary_name);
if (!ifs.is_open()) {
cout << "Could not open file: " << dictionary_name << endl;
return 1;
}
//пока не дошли до конца файла
while (ifs.eof() == false) {
string curLine;
getline(ifs, curLine);
words.push_back(curLine);
}
ifs.close();
return 0;
}
Теперь необходимо отсортировать список. Следует отметить, что данную задачу можно реализовать с помощью стандартных алгоритмов STL.
sort(words.begin(), words.end());
Естественно возникает вопрос о том, какие еще стандартные алгоритмы доступны в модуле alogorithm. Их можно разделить на четыре категории:
Неизменяющие алгоритмы над последовательностями
for_each – приминяет фунцию к каждому элементу
find – выполняет линейный поиск
find_first_of – выполняет линейный поиск любого из множества значений
adjacent_find – выполняет линейный поиск смежных равных элементов
count – подсчитывает количество элементов с данным значением
mismatch – сканирует две последовательности в поисках первой позиции, где они различны
equal - сканирует две последовательности для проверки их поэлементной эквивалентности
search – сканирует последовательность в поисках друго подпоследовательности
search_n – сканирует последовательность в поисках ряда идентичных элементов с данным значением
find_end – сканирует последовательность в поисках последнего совпадения с другой последовательностью
Изменяющие алгоритмы над последовательностями
copy – копирует элементы в другоую последовательность
swap – обменивает элементы одной последовательности с элементами другой
transform – замещает каждый элемент значением, возвращаемым после применения переденной в качестве параметра функции к элементу
replace – замещает каждый эдемент, равный некоторому значению копией другого заданного значения
fill – замещает каждый элемент копией другого заданного значения
generate – замещает каждый элемент значением, возвращаемым вызовом функции
remove – удаляет элементы, равные заданному значению
unique – удаляет последовательные равные элементы
reverse – обращает относительный порядок элементов
rotate – выполняет циклический сдвиг элементов
random_shuffle – псевдослучайно переупорядочивает элементы
partition – переупорядочивает элементы таким образом, что элементы, удовлетворяющие указанному предикату, предшествуют элементам, не удовлетворяющим ему.
Алгоритмы, связанные с сортировкой
sort, stable_sort, partial_sort – переставляют элементы последоватьльности в порядке возрастания
nth_element – находит N-й наименьший элемент последовательности
binary_search, lower_bound, upper_bound, equal_range – выполняют поиск в отсортировнной последовальности методом деления пополам
megre – сливает дву отсортировнные последовательности в одну
includes, set_union, set_intersection, set_difference, set_symmetric_difference –выполняют теоретико-множественные операции над отсортированными структурами
push_heap, pop_heap, make_heap, sort_heap -выполняют операции по упорядочиванию последоватьности, лрганизованной в виде пирамиды
min, max, min_element, max_element находят минимальный или максимальный элемент пары или последовательности
lexicographical_compare – лексикографически сравнивает две последовательности
next_permutation, prev_permutation – генерируют перестановки последовательности, основываясь на лексикографическом упорядочении множества всех перестановок
Обобщенные числовые алгоритмы
accumulate – вычисляет сумму элементов последовательности
inner_product – вычисляет сумму произведение соответствующих элементов последовательностей
partial_sum – вычисляет частичные суммы элементов последовательности и сохраняет их в другой (или той же) последовательности
adjacent_difference – вычисляет разности смежных элементов и сохраняет их в другой (или той же) последовательности.
Запись в выходной файл так же не представляет из себя сложностей:
int writeToFile(std::string fileName, std::vector<string> &words){
ofstream ofs(fileName);
if (!ofs.is_open()) {
cout << "Could not open file: " << fileName << endl;
return 1;
}
for (vector<string>::iterator i = words.begin(); i != words.end(); ++i) {
ofs << *i << "\n";
}
ofs.close();
return 0;
}
Приведем полный код программы:
#include <conio.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
int readFromFile(string dictionaryName, vector<string> &words) {
ifstream ifs(dictionaryName);
if (!ifs.is_open()) {
cout << "Could not open file: " << dictionaryName << endl;
return 1;
}
while (ifs.eof() == false) {
string curLine;
getline(ifs, curLine);
words.push_back(curLine);
}
ifs.close();
return 0;
}
int writeToFile(string fileName, vector<string> &words) {
ofstream ofs(fileName);
if (!ofs.is_open()) {
cout << "Could not open file: " << fileName << endl;
return 1;
}
for (vector<string>::iterator i = words.begin(); i != words.end(); ++i) {
ofs << *i << "\n";
}
ofs.close();
return 0;
}
int main(int argc, char* argv[]) {
vector<string> words;
readFromFile("in.txt", words);
sort(words.begin(), words.end(), less<string>());
writeToFile("out.txt", words);
//_getch();
return 0;
}