Декомпрессия по длине прогона с использованием C ++ - PullRequest
1 голос
/ 19 февраля 2020

У меня есть текстовый файл со строкой, которую я закодировал.

Допустим, это: aaahhhhiii kkkjjhh ikl wwwwwweeeett

Вот код для кодирования, который прекрасно работает:

void Encode(std::string &inputstring, std::string &outputstring)
{
    for (int i = 0; i < inputstring.length(); i++) {
        int count = 1;
        while (inputstring[i] == inputstring[i+1]) {
            count++;
            i++;
        }
        if(count <= 1) {
            outputstring += inputstring[i];
        } else {
            outputstring += std::to_string(count);
            outputstring += inputstring[i];
        }
    }
}

Вывод соответствует ожидаемому: 3a4h3i 3k2j2h ikl 6w4e2t

Теперь я хотел бы распаковать вывод - обратно в исходное состояние.

И я борюсь с этим уже пару дней сейчас.

Моя идея на данный момент:

void Decompress(std::string &compressed, std::string &original)
{
    char currentChar = 0;
    auto n = compressed.length();
    for(int i = 0; i < n; i++) {

        currentChar = compressed[i++];

        if(compressed[i] <= 1) {
            original += compressed[i];
        } else if (isalpha(currentChar)) {
            //
        } else {
            //
            int number = isnumber(currentChar).....
            original += number;
        }
    }
}

Я знаю, что моя функция распаковки кажется немного грязной, но я довольно потерян с этой. Извините за это.

Возможно, есть кто-то в стеке потока, который хотел бы помочь потерянной и начинающей душе.

Спасибо за любую помощь, я ценю это.

Ответы [ 3 ]

2 голосов
/ 19 февраля 2020

Предполагая, что входные строки не могут содержать цифр (это не может быть охвачено вашей кодировкой, поскольку, например, обе строки "3a" и "aaa" приведут к закодированной строке "3a" - как бы вы захотели снова разложить?) Тогда Вы можете распаковать его следующим образом:

unsigned int num = 0;
for(auto c : compressed)
{
    if(std::isdigit(static_cast<unsigned char>(c)))
    {
        num = num * 10 + c - '0';
    }
    else
    {
        num += num == 0; // assume you haven't read a digit yet!
        while(num--)
        {
            original += c;
        }
    }
}

Не проверенный код, хотя ...

Символы в строке на самом деле являются только числовыми значениями. Вы также можете рассматривать char (или signed char, unsigned char) как обычные 8-битные целые числа. И вы можете хранить числовое значение в таком байте тоже. Обычно вы выполняете кодирование длины именно таким образом: считайте до 255 одинаковых символов, сохраняйте счет в одном байте, а символ - в другом байте. Один "a" будет затем закодирован как 0x01 0x61 (последний является значением ASCII a), "aa" получит 0x02 0x61 и так далее. Если вам нужно хранить более 255 одинаковых символов, вы сохраняете две пары: 0xff 0x61, 0x07 0x61 для строки, содержащей 262 символа a ... Декодирование становится тривиальным: вы читаете символы попарно, первый байт интерпретируется как число, второй один как персонаж - остальное тривиально. И вы так же хорошо освещаете цифры.

0 голосов
/ 19 февраля 2020

Декомпрессия не может работать однозначно, потому что вы не определили часовой символ; то есть, учитывая сжатый поток, невозможно определить, является ли число исходным одиночным числом или оно представляет команду повтора RLE. Я бы предложил использовать «0» в качестве сторожевого символа. Во время кодирования, если вы видите «0», вы просто выводите 010. Любой другой символ X преобразуется в 0NX, где N - счетчик повторных байтов. Если вы go превысили 255, просто выведите новую команду повторения RLE

0 голосов
/ 19 февраля 2020
#include "string"
#include "iostream"


void Encode(std::string& inputstring, std::string& outputstring)
{
    for (unsigned int i = 0; i < inputstring.length(); i++) {
        int count = 1;
        while (inputstring[i] == inputstring[i + 1]) {
            count++;
            i++;
        }
        if (count <= 1) {
            outputstring += inputstring[i];
        }
        else {
            outputstring += std::to_string(count);
            outputstring += inputstring[i];
        }
    }
}

bool alpha_or_space(const char c)
{
    return isalpha(c) || c == ' ';
}

void Decompress(std::string& compressed, std::string& original)
{
    size_t i = 0;
    size_t repeat;
    while (i < compressed.length())
    {
        // normal alpha charachers
        while (alpha_or_space(compressed[i]))
            original.push_back(compressed[i++]);

        // repeat number
        repeat = 0;
        while (isdigit(compressed[i]))
            repeat = 10 * repeat + (compressed[i++] - '0');

        // unroll releat charachters
        auto char_to_unroll = compressed[i++];
        while (repeat--)
            original.push_back(char_to_unroll);
    }
}

int main()
{
    std::string deco, outp, inp = "aaahhhhiii kkkjjhh ikl wwwwwweeeett";

    Encode(inp, outp);
    Decompress(outp, deco);

    std::cout << inp << std::endl << outp << std::endl<< deco;

    return 0;
}
...