Кодирование и декодирование текста в c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

FILE *inputFile;
FILE *outputFile;

int encodeBinary[4] = {0x00, 0x01, 0x02, 0x03};
char encodeChars[4] = {':', '@', '\n', ' '};

void encode(const char * inFile, const char * outFile)
{

    inputFile = fopen(inFile, "r");
    outputFile = fopen(outFile, "w");
    char lineBuffer[BUFSIZ];

    if(inputFile == NULL)
    {
        perror("Error while opening file.\n");
        exit(EXIT_FAILURE);
    }

    while(fgets(lineBuffer, sizeof(lineBuffer), inputFile))
    {
        for(int i = 0; lineBuffer[i] != 0; i++)
        {
            if(lineBuffer[i] == encodeChars[0])
            {
                fprintf(outputFile, "%d", encodeBinary[0]);
            }
            else if(lineBuffer[i] == encodeChars[1])
            {
                fprintf(outputFile, "%d", encodeBinary[1]);
            }
            else if(lineBuffer[i] == encodeChars[2])
            {
                fprintf(outputFile, "%d", encodeBinary[2]);
            }
            else if(lineBuffer[i] == encodeChars[3])
            {
                fprintf(outputFile, "%d", encodeBinary[3]);
            }
        }
    }

    fclose(inputFile);
    fclose(outputFile);

}

void decode(const char * inFile, const char * outFile)
{

    inputFile = fopen(inFile, "r");
    outputFile = fopen(outFile, "w");
    char lineBuffer[BUFSIZ];

    if(inputFile == NULL)
    {
        perror("Error while opening file.\n");
        exit(EXIT_FAILURE);
    }

    while(fgets(lineBuffer, sizeof(lineBuffer), inputFile))
    {
        for(int i = 0; lineBuffer[i] != 0; i++)
        {
            if(lineBuffer[i] == '0')
            {
                fprintf(outputFile, "%c", encodeChars[0]);
            }
            else if(lineBuffer[i] == '1')
            {
                fprintf(outputFile, "%c", encodeChars[1]);
            }
            else if(lineBuffer[i] == '2')
            {
                fprintf(outputFile, "%c", encodeChars[2]);
            }
            else if(lineBuffer[i] == '3')
            {
                fprintf(outputFile, "%c", encodeChars[3]);
            }
        }
    }

    fclose(inputFile);
    fclose(outputFile);

}


void commands(const char * command, const char * inputFile, const char * outputFile)
{
    if(strcmp(command, "encode") == 0)
    {
        encode(inputFile, outputFile);
    }
    else if(strcmp(command, "decode") == 0)
    {
        decode(inputFile, outputFile);
    }
}

void testValues(int argc, const char * argv[])
{
    if(argc == 4)
    {
        commands(argv[1], argv[2], argv[3]);
    }
    else
        printf("USAGE: ./encode [input_file] [output_file]\n");
}

//MAIN
int main(int argc, const char * argv[])
{

    testValues(argc, argv);

    return 0;
}

Всем привет. У меня есть этот кусок кода. Код должен получить текстовый файл, состоящий из символов: @ "новая строка" и "пробел". Затем эти символы должны быть преобразованы в двоичные числа, 0, 1, 10, 11. После этого мне также нужен способ декодирования обратно в исходные символы. Чего я никак не могу понять, так это как уметь читать разницу между числами, если там 001, то откуда мне знать, что речь идет о 0, 01, а не 00, 1. Я где-то читал, что вы можно использовать побитовые операции для этого? Любая помощь приветствуется!

Итак, я немного изменил свой код. Теперь проблема в том, что когда я сохраняю значения, закодированный файл имеет такой же размер, как и файл, который должен быть закодирован. Как я могу хранить значения в файле таким образом, чтобы он сохранял значения в шестнадцатеричном (или двоичном) формате, чтобы закодированный файл был меньше исходного файла?


person Arash Saidi    schedule 07.10.2013    source источник
comment
символы имеют 7 бит (не обязательно), а не 2 или 3 бита.   -  person haccks    schedule 07.10.2013
comment
Да, но я должен представлять эти символы как 2-битные каждый.   -  person Arash Saidi    schedule 07.10.2013
comment
Я, вероятно, должен был быть более ясным, но я должен взять один файл с символами, а затем закодировать их в другой файл в двоичном формате, чтобы сэкономить место. Как я могу это сделать?   -  person Arash Saidi    schedule 07.10.2013


Ответы (1)


{0, 1, 10, 11}; не являются двоичными числами, это десятичные числа, которые являются числовым форматом по умолчанию в исходном коде C. Другими возможными основаниями счисления являются шестнадцатеричная, записываемая с префиксом 0x, и восьмеричная, записываемая с префиксом 0. Невозможно записать двоичные числа в стандартном коде C (вероятно, потому, что они считаются трудными для чтения людьми).

Итак, что вам нужно сделать, это ввести числа в шестнадцатеричном формате:

{0x00, 0x01, 0x02, 0x03}

Алгоритм довольно прост:

  • Прочитать символ из файла.
  • Найдите совпадение этого символа среди encodeChars (которое должно быть объявлено как const char []).
  • Если найдено, замените его соответствующим индексом в «двоичном».
  • Декодирование выполняется наоборот, вместо этого просто используйте двоичный файл в качестве таблицы поиска.
  • Если важна производительность, рассмотрите возможность реализации этого с помощью двоичного поиска. Это идеальный пример того, где следует использовать бинарный поиск (отсортированные данные, без дубликатов).

ИЗМЕНИТЬ

Я говорил о представлении чисел для программиста внутри собственного исходного кода программиста. Здесь вы можете использовать только десятичные, шестнадцатеричные и восьмеричные числа.

Существует также представление чисел для пользователя, что, я полагаю, именно то, что вы искали. Это может быть все что угодно.

И, наконец, представление чисел для CPU. Он хочет только двоичный код и ничего, кроме двоичного.

Подумайте об этом: printf("%c", 0x41).

  • Программатор видит шестнадцатеричный код 41.
  • Пользователь видит букву А.
  • ЦП видит что-то вроде «Сохранить номер 01000001 в стеке. Перейти к подпрограмме».

Чтобы отобразить случайный байт в виде двоичного числа для пользователя, просто выполните что-то вроде:

#include <stdint.h>

uint8_t data = 0x41;

for(uint8_t i=0; i<8; i++)
{
  if( (data & (1<<i)) > 0)
  {
    printf("1");
  }
  else
  {
    printf("0");
  }

}
person Lundin    schedule 07.10.2013
comment
Спасибо за попытку. Но я должен представлять числа в двоичной форме, а не в восьмеричной или шестнадцатеричной. - person Arash Saidi; 07.10.2013
comment
@ХаториСансо; Компьютер обрабатывает их как двоичные, а не восьмеричные или шестнадцатеричные! - person haccks; 07.10.2013
comment
Вы можете использовать нестандартный префикс 0b, который работает в нескольких компиляторах (по крайней мере, GCC, TCC и Clang) - person Kninnug; 07.10.2013
comment
@HatoriSanso Вы путаете представление чисел между исходным кодом ‹-› программистом с представлением чисел между программой ‹-› пользователем. Это две совершенно разные вещи. Подождите, я отредактирую пример того, как печатать двоичные числа... - person Lundin; 07.10.2013
comment
Спасибо! Мне удалось изменить свой код так, что теперь каждый символ представлен шестнадцатеричным числом. Но закодированный файл такого же размера, как мой текстовый файл? Как я могу хранить шестнадцатеричные числа как биты вместо символов в текстовом файле (или любом другом файле)? - person Arash Saidi; 07.10.2013
comment
@HatoriSanso Для этого вам нужно открыть файл как двоичный, а не как текстовый файл. Проверьте функции fread и fwrite. И я обновил этот ответ некоторыми разъяснениями. - person Lundin; 07.10.2013