我有一个文本文件,其中包含我编码的字符串。
假设它是: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;
}
}
}
我知道我的Decompress函数似乎有点混乱,但是我对这个函数很迷失。 抱歉。
在stackoverflow上也许有人愿意帮助失落的初学者。
感谢您的帮助。
答案 0 :(得分:2)
假设输入字符串不能包含数字(编码不能覆盖数字,例如,字符串"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
(后者是a
的ASCII值),"aa"
将得到0x02 0x61
,依此类推。如果必须存储超过255个相等的字符,则可以存储两对:0xff 0x61, 0x07 0x61
用于包含字符a
的262倍的字符串...解码然后变得不重要:您成对读取字符,解释的第一个字节作为数字,第二个作为字符–琐碎。而且您也可以用这种方式很好地覆盖数字。
答案 1 :(得分:0)
#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;
}
答案 2 :(得分:0)
解压缩可能无法以明确的方式进行,因为您没有定义前哨字符;也就是说,在给定压缩流的情况下,无法确定数字是原始单个数字还是代表重复的RLE命令。我建议使用“ 0”作为前哨字符。编码时,如果看到“ 0”,则仅输出010
。其他任何char X都将转换为0NX
,其中N
是重复字节计数器。如果超过255,只需输出一个新的RLE重复命令