3. Алгоритм compress постоянно вызывает функцию occurrences. Таким образом, мы переходим от одной группы символов к другой. Строка r<
string
string compress(const string &s)
{
const auto end_it (end(s));
stringstream r;
for (auto it (begin(s)); it != end_it;) {
const auto [next_diff, c, n] (occurrences(it, end_it));
r << c << n;
it = next_diff;
}
return r.str();
}
4. Метод decompress
string decompress(const string &s)
{
stringstream ss{s};
stringstream r;
char c;
size_t n;
while (ss >> c >> n) { r << string(n, c); }
return r.str();
}
5. В нашей функции main
int main()
{
string s {"aaaaaaaaabbbbbbbbbccccccccccc"};
cout << compress(s) << '\n';
cout << decompress(compress(s)) << '\n';
}
6. Компиляция и запуск программы дадут следующий результат:
$ ./compress
a9b9c11
aaaaaaaaabbbbbbbbbccccccccccc
Как это работает
Эта программа, по сути, состоит из двух функций: compress
decompress
.Функция decompress
return
. Строка кода, выполняющего некие действия, выглядит так:while (ss >> c >> n) { r << string(n, c); }
Она постоянно считывает символ c
n
из строкового потока ss
. Класс stringstream
скрывает от нас возможности, связанные с анализом строки. Отработав успешно, функция возвращает развернутую строку в строковый поток, из которого итоговую строку можно вернуть вызывающей стороне. Если c = 'a'
и n = 5
, то выражение string(n, c)
вернет строку "aaaaa"
.Функция compress
Функция occurences
find_if
мы находим первый символ, отличный от символа, на который изначально указывал итератор. На рис. 6.12 данный итератор называется diff
. Разность между этой новой позицией и старой позицией итератора равна количеству одинаковых элементов (на рис. 6.12 diff-it
равно 6
). После выполнения подсчетов итератор diff
можно использовать повторно для выполнения нового поиска. Так что мы помещаем diff
, символ поддиапазона и длину поддиапазона в кортеж и возвращаем его.Имея подобную информацию, можно переходить от поддиапазона к поддиапазону и помещать промежуточные результаты в сжатую целевую строку:
for (auto it (begin(s)); it != end_it;) {
const auto [next_diff, c, n] (occurrences(it, end_it));
r << c << n;
it = next_diff;
}
Дополнительная информация
В шаге 4 мы упоминали, что функция decompress небезопасна. Более того, ее легко использовать