Задание: "Первые 15 наиболее часто встречающихся символов кодируются 4-битными кодами от 0000 до 1110. Код 1111 обозначает, что следующие за ним 8 бит кодируют один из остальных символов. Разработать функции упаковки и распаковки строки с определением наиболее часто встречающихся символов и коэффициента уплотнения".
Есть следующий код. Почему-то при использовании функции распаковки, программа выводит в блокнот полную лабуду. Помогите найти ошибку.
Есть следующий код. Почему-то при использовании функции распаковки, программа выводит в блокнот полную лабуду. Помогите найти ошибку.
:
#define STRLEN 1000
#include <Windows.h>
#include <conio.h>
#include <cstdio>
#include <iostream>
using namespace std;
unsigned char CharNum[256], InStr[STRLEN], OutStr[STRLEN], M[15];
int len, pos;
int Comp();
int Decomp();
void PutChar(unsigned char code);
unsigned char GetChar();
int check(unsigned char ch);
int main()
{
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
FILE *Fin = fopen("input.txt", "rb");
FILE *Fout = fopen("output.txt", "wb");
unsigned char c;
if (!Fin)
{
printf("Error! Check input.txt\n");
return 0;
}
len = 0;
while (fscanf(Fin, "%c", &c) != EOF)
{
InStr[len] = c;
len++;
}
printf("(C)ompress or (D)ecompress?\n(C/D)");
do
{
c = getchar();
} while (c != 'C' && c != 'D');
int OutLen;
if (c == 'C')
OutLen = Comp();
else
OutLen = Decomp();
for (int i = 0; i < OutLen; i++)
fprintf(Fout, "%c", OutStr[i]);
_getch();
return 0;
}
int check(unsigned char ch)
{
for (int i = 0; i < 15; i++)
if (ch == M[i])
return i;
return 15;
}
int Comp()
{
InStr[len] = 0;
int i, j;
for (i = 0; i < len; i++)
CharNum[InStr[i]]++;
for (j = 0; j < 15; j++)
{
M[j] = CharNum[0];
for (i = 1; i < 256; i++)
if (CharNum[M[j]] < CharNum[i])
M[j] = i;
CharNum[M[j]] = 0;
OutStr[j] = M[j];
}
len++;
pos = 30;
for (i = 0; i < len; i++)
{
PutChar(InStr[i]);
}
double ratio = (double)((pos + 1) / 2) / len;
printf("Коэффициент уплотнения = %f\n", ratio);
return (pos + 1) / 2;
}
int Decomp()
{
int i;
for (i = 0; i < 15; i++)
M[i] = InStr[i];
pos = 30;
len = 0;
do
{
OutStr[len] = GetChar();
} while (OutStr[len++]);
return len - 1;
}
void PutChar(unsigned char code)
{
unsigned char z = check(code);
if (z == 15)
{
if ((pos & 1) == 0)
z <<= 4;
OutStr[pos / 2] = OutStr[pos / 2] | z;
pos++;
z = code << 4;
if (pos & 1)
z >>= 4;
OutStr[pos / 2] = OutStr[pos / 2] | z;
pos++;
z = code >> 4;
if ((pos & 1) == 0)
z <<= 4;
OutStr[pos / 2] = OutStr[pos / 2] | z;
pos++;
return;
}
if ((pos & 1) == 0)
z <<= 4;
OutStr[pos / 2] = OutStr[pos / 2] | z;
pos++;
}
unsigned char GetChar()
{
unsigned char z = InStr[pos / 2];
if ((pos & 1) == 0)
z >>= 4;
else
z %= 16;
pos++;
if (z < 15)
return M[z];
if (pos & 1)
z = (InStr[pos / 2] % 16) | (InStr[(pos + 1) / 2] >> 4 << 4);
else
z = (InStr[pos / 2] >> 4) | (InStr[(pos + 1) / 2] << 4);
pos += 2;
return z;
}