Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 01.03.2020, 17:45   #1
CyberNoble
Новичок
Джуниор
 
Регистрация: 01.03.2020
Сообщений: 2
По умолчанию Как сжать строку в c++

В двух словах:
Имеется строка
Код:
string word = "aaabbcaa"
на выходе нужно получить 3a2bc2a либо {3,a},{2,b},c,{2,a}

Если не в двух,то :
Массив может состоять не только из этих 3 букв,пользователь вводит все сам

Пробовал так:
Код:
string wordZIP = word;
        int result = 0;
        int j = 1;
        int z = 0;
        for (int k = 0; k < wordLength; k++)
        {
            if (wordZIP[j] != wordZIP[z])
            {
                j++;
                z++;
                if (j - z > 1)
                {
                    result = j - z;
                }
            }
            j++;
        }
Но что-то потерял мысль,планировал записывать результат разницы индексов,чтобы получать кол-во повторяющихся символов,но,кажется не в ту сторону пошел.
Можете подсказать как довести до ума,а лучше пример кода,желательно с комментариями.
Заранее спасибо

P.S.
wordZIP уже имеет в себе рандомное слово.
P.S.S.
Длина последовательности повторяющихся может быть любой.
CyberNoble вне форума Ответить с цитированием
Старый 01.03.2020, 18:15   #2
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 968
По умолчанию

формат такой:
<количество_повторов> <двоеточие> <символ>
Код:
#include <algorithm>
#include <string>
#include <iostream>

std::string Compress(const std::string& src)
{
	std::string result;

	auto beg=src.begin();
	while(beg!=src.end())
	{
		auto curr_end=std::find_if(beg,src.end(),[&beg](const auto& c){return c!=*beg;});
		const auto count=curr_end-beg;
		result+=std::to_string(count);
		result+=':';
		result+=*beg;
		beg=curr_end;
	}

	return result;
}

int main()
{
	const std::string src="aaabbcaallllllrrrrrrgttttthhhhhhh";
	auto result=Compress(src);
	std::cout<<src<<'\n';
	std::cout<<result<<'\n';
}
Код:
aaabbcaallllllrrrrrrgttttthhhhhhh                                                                                        
3:a2:b1:c2:a6:l6:r1:g5:t7:h
зачем двоеточие - если в исходной строке будут символы '0'...'9', то восстановить строку не получится

очевидно, что для выгоды использования такого сжатия необходимо, чтобы было много повторов по 4+ символов. Иначе результат будет такой же или длиннее

P.S. к ZIP это всё отношения не имеет

Последний раз редактировалось Алексей1153; 01.03.2020 в 18:20.
Алексей1153 вне форума Ответить с цитированием
Старый 01.03.2020, 19:03   #3
CyberNoble
Новичок
Джуниор
 
Регистрация: 01.03.2020
Сообщений: 2
По умолчанию

Алексей1153, Понял,спасибо,но не совсем понимаю смысл строчки
Код:
auto curr_end=find_if(beg,src.end(),[&beg](const auto& c){return c!=*beg;});
Выходит ,что переменная curr_end принимает значение первого элемента между
Код:
beg
и
Код:
src.end()
для которого из условия
Код:
[&beg](const auto& c){return c!=*beg;}
возвращается true?
Собственно не очень хорошо понимаю,если с
Код:
beg
и
Код:
 src.end()
еще понятно,что переменная beg получает значение начала массива string ,а
Код:
src.end()
- это конец строки,то с условием
Код:
[&beg](const auto& c){return c!=*beg;}
уже тяжко. Можете,пожалуйста его подробно расписать,зачем тут ссылка на адрес первого элемента,в чем смысл объявления адреса
Код:
(const auto& c)
,а конец
Код:
{return c!=*beg;}
,так понимаю - это обычная конструкция для этой функции или как?Впервые сталкиваюсь с find_if и алгоритмами.
P.S.Про zip понял
P.S. А в чем плюс использовать auto,тоже впервые столкнулся,почитал,что это позволяет не указывать тип переменной явно,но стоит ли ее постоянно использовать или это только ухудшает понимание кода человеком?
CyberNoble вне форума Ответить с цитированием
Старый 01.03.2020, 20:26   #4
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 968
По умолчанию

std::find_if - стандартная функция STL. На вход принимает два итератора - начало и конец контейнера, где производится поиск. Третий параметр - предикат, возвращающий тип bool

в качестве предиката у меня использована лямбда

[ &beg ] //захват переменной beg по ссылке (этот итератор указывает на первый символ в цепочек)
( const auto& c ) //список аргументов аргументов - ссылка на текущий проверяемый элемент контейнера
{ return c!=*beg; } //тело лямбды - возвращается результат сравнения (элемент не равен первому символу в цепочке)

в итоге, в итераторе curr_end оказывается конец диапазона с одинаковыми символами

Цитата:
Сообщение от CyberNoble Посмотреть сообщение
А в чем плюс использовать auto
это не плюс и не минус, это возможность языка. Хотя, иногда auto реально улучшает читабельность (да и скорость набора кода). Для сравнения:

Код:
auto curr_end=std::find_if(beg,src.end(),[&beg](auto& c){return c!=*beg;});
//то же самое
std::string::const_iterator curr_end=std::find_if(beg,src.end(),[&beg](const char& c){return c!=*beg;});
про лямбды и auto можно почитать, например, тут
Алексей1153 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Что значит сжать? PadavanPanda C# (си шарп) 4 19.05.2018 17:21
Сжать exe файл Legeardo Общие вопросы Delphi 11 22.10.2016 12:33
Сжать массив tanyuxxxa Помощь студентам 4 12.02.2013 19:12
Двунаправленный линейный список строк. Вставить строку, удалить строку и заменить строку tarasman11 Паскаль, Turbo Pascal, PascalABC.NET 4 05.07.2012 20:27
Как сжать bmp? MkG Общие вопросы C/C++ 2 23.05.2010 12:10