Функция исключения нулевого байта - C (СИ)

Узнай цену своей работы

Формулировка задачи:

Нужна функция которая обрабатывает данные побайтно и преобразует их таки образом что бы байт никогда не имел 0b00000000, т.е не был равен нулю, при этом изначальное значение которому был равен байт до кодирования должно быть возвращено относительно быстро и легко. Допускается использование дополнительных байт для кодирования информации. Самое простое решение это задействовать часть байт для записи некой метки не равной нулю, но тогда надо возиться со сдвигами и это вообще не элегантно)).

Решение задачи: «Функция исключения нулевого байта»

textual
Листинг программы
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define MEM_SIZE 16
 
typedef struct
{
  unsigned char byte;
  signed char isNormal;
} TEncodedMemoryBlock;
 
char* GetBin(const unsigned char byte)
{
  static char binStr[9];
 
  unsigned char i = 7;
  unsigned char temp = byte;
 
  memset(binStr, '0', sizeof(binStr));
  binStr[8] = '\0';
 
  do
  {
    if ((temp & 1) == 0)
    {
      binStr[i] = '0';
    }
    else
    {
      binStr[i] = '1';
    }
 
    i--;
    temp = temp >> 1;
  }
  while (temp != 0);
 
  return binStr;
}
 
TEncodedMemoryBlock* EncodeMemory(const unsigned char* const memoryBlock, const size_t blockLength)
{
  TEncodedMemoryBlock* memArray = NULL;
 
  const unsigned char encodingKey1 = 0x01;
  const unsigned char encodingKey2 = 0x10;
  const unsigned char nullBlock = 0x00;
 
  size_t i = 0;
 
  memArray = malloc(blockLength * sizeof(*memArray));
  if (memArray != NULL)
  {
    for(i = 0; i < blockLength; i++)
    {
      if (memoryBlock[i] == nullBlock)
      {
        memArray[i].byte = encodingKey1;
        memArray[i].isNormal = 0;
      }
      else if (memoryBlock[i] == encodingKey1)
      {
        memArray[i].byte = encodingKey2;
        memArray[i].isNormal = 0;
      }
      else
      {
        memArray[i].byte = memoryBlock[i] ^ encodingKey1;
        memArray[i].isNormal = 1;
      }      
    }
  }
 
  return memArray;
}
 
unsigned char* DecodeMemory(const TEncodedMemoryBlock* const encodedMemoryBlock, const size_t blockLength)
{
  unsigned char* decodedMem = NULL;
 
  size_t i = 0;
 
  const unsigned char encodingKey1 = 0x01;
  const unsigned char encodingKey2 = 0x10;
  const unsigned char nullBlock = 0x00;
 
  decodedMem = malloc(blockLength);
  if (decodedMem != NULL)
  {
    for(i = 0; i < blockLength; i++)
    {
      if (encodedMemoryBlock[i].isNormal)
      {
        decodedMem[i] = encodedMemoryBlock[i].byte ^ encodingKey1;
      }
      else
      {
        if (encodedMemoryBlock[i].byte == encodingKey1)
        {
          decodedMem[i] = nullBlock;
        }
        else
        {
          decodedMem[i] = encodingKey1;
        }
      }
    }
  }
 
  return decodedMem;
}
 
void PrintEncodedMemory(const TEncodedMemoryBlock* const encodedMemoryBlock, const size_t blockLength)
{
  size_t i = 0;
 
  printf("=== Encoded memory: ===\n");
  for(i = 0; i < blockLength; i++)
  {
    printf("[%2lu] : 0x%02hhX %s (%hhd)\n", i, encodedMemoryBlock[i].byte, GetBin(encodedMemoryBlock[i].byte), encodedMemoryBlock[i].isNormal);
  }
  printf("=======================\n");
}
 
void PrintMemory(const unsigned char* const memoryBlock, const size_t blockLength)
{
  size_t i = 0;
 
  printf("======= Memory: =======\n");
  for(i = 0; i < blockLength; i++)
  {
    printf("[%2lu] : 0x%02hhX %s\n", i, memoryBlock[i], GetBin(memoryBlock[i]));
  }
  printf("=======================\n");
}
 
int main(void)
{
  char str[MEM_SIZE];
 
  unsigned char origMemBlock[MEM_SIZE];
  unsigned char* decodedMemBlock;
 
  size_t N = sizeof(str);
 
  TEncodedMemoryBlock* encodedMem = NULL;
 
  memset(str, 0, N);
  memset(origMemBlock, 0, N);
  
 
  strcpy(str, "This is a test!");
 
  memcpy(origMemBlock, str, N);
 
  PrintMemory(origMemBlock, N);
 
  encodedMem = EncodeMemory(origMemBlock, N);
 
  PrintEncodedMemory(encodedMem, N);
 
  decodedMemBlock = DecodeMemory(encodedMem, N);
 
  PrintMemory(decodedMemBlock, N);
 
  printf("cmp of original and decoded: %d\n", memcmp(origMemBlock, decodedMemBlock, N));
 
  free(encodedMem);
  free(decodedMemBlock);
  return 0;
}

Объяснение кода листинга программы

  1. Функция GetBin принимает один аргумент - байт, и возвращает строку бинарного представления этого байта.
  2. В функции EncodeMemory создается массив указателей на структуры TEncodedMemoryBlock, которые будут хранить информацию о каждом байте входного массива. Если входной массив содержит нулевой байт, он заменяется на специальный код.
  3. Функция DecodeMemory принимает массив структур TEncodedMemoryBlock и возвращает декодированный массив байтов. Если в исходном массиве был нулевой байт, он заменяется на специальный код.
  4. В функции main создается массив символов, который затем преобразуется в массив байтов. Этот массив байтов кодируется с помощью EncodeMemory, затем декодируется с помощью DecodeMemory. Результат сравнивается с исходным массивом.

Оцени полезность:

13   голосов , оценка 3.692 из 5
Похожие ответы