5 - шифрование, обработка символьных строк

Лабораторная работа 5 для студентов курса “Основы программирования” 1 курса кафедры ИУ5 МГТУ им Н.Э. Баумана.

Содержание

Цель работы

Научиться работать с файлами и c-style строками, используя файловые потоки ввода/вывода и строковые функции. Освоить базовые навыки работы с CMake. Более подробно познакомиться со структурами. Понять, как использовать аргументы командной строки.

Начало работы

Зайдите в свою локальную директорию с репозиторием для выполнения лабораторных работ. Заберите ветку с соответствующей лабораторной работой из общего репозитория (в лабораторной работе 0 был отмечен меткой upstream):

git pull upstream

или

git pull upstream lab_5

Переключитесь на ветку с текущей лабораторной работой:

git checkout lab_5

Свяжите ветку локального репозитория с вашим удаленным репозиторием:

git push --set-upstream origin lab_5

Указания по выполнению лабораторной работы

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

Внимание!

В данной лабораторной работе требуется самостоятельно тщательно продумать набор интерфейсных функций, которые пойдут в заголовочный файл.

Начиная с этой лабораторной работы, требуется использовать CMake для сборки проекта. Пока достаточно (и необходимо) использовать ту информацию, что указана в лабораторной работе 0.4.

Обратите внимание: пайплайн автоматической проверки на GitHub изменен с учетом новых требований. Для корректной работы в CMakeLists.txt должна быть указана кастомная цель с названием clang-format (пример приведен в методических указаниях для лабораторной работы 0.4).

Общие советы

Шифр Цезаря

Подробнее можно прочитать тут.

Работа с файлами

// в реальности стоит сделать размер буфера побольше, в районе 1024
while (f.getline(buf, 50) || !f.eof()) {
    ...
    f.clear();
}

Работа со строками

Пример

TBD

Задание

Провести кодирование и декодирование текста с помощью шифра Цезаря, используя в качестве алфавита стандартную таблицу ASCII. Величина сдвига для каждой позиции в исходном тексте - сумма (по модулю 128) кодов символов слова кодового блокнота, стоящего в блокноте на той же позиции. Если кодовый блокнот имеет количество слов меньше, чем количество символов в исходном тексте, то по исчерпании слов в нем перейти к первому слову и продолжить.

Слово определяется как непрерывная последовательность букв и/или цифр, разделяемых знаком пунктуации/пробелом/признаком концом строки. Знаком пунктуации считается любой символ, для которого функция std::ispunct возвращает не 0.

σ(si)=[γ(si)+j=0λi1γ(lj)]mod  128,lλi \sigma(s_i) = [\gamma(s_i) + \sum_{j = 0}^{|\lambda_i| - 1} \gamma(l_j)] \mod 128, l \in \lambda_i

где:

Приложение должно работать с четырьмя файлами:

Названия всех четырех файлов подаются пользователем при запуске приложения через аргументы командной строки. Приложение должно убедиться, что первые два файла существуют. Последние два приложение должно либо создать самостоятельно (если они отсутствуют), либо полностью удалить их текущее содержимое перед записью.

Допустимо подавать аргументы в заданном порядке. В идеале (но не обязательно), должна быть предусмотрена дополнительная возможность подать файлы в случайном порядке, используя именованные аргументы (например, ./app --some-arg-name=filename.txt --second-arg-name=filename2.txt). Парсинг аргументов осуществляется вручную.

В репозитории этих файлов быть не должно.

Составить и вывести в виде таблицы статистику в следующем виде:

Таблица не должна сразу выводиться целиком. Предусмотреть последовательный вывод таблицы (например, по 5 строк за раз) с возможностью переключаться вперед и назад (предыдущие и следующие строки). Неиспользуемые символы в таблицу попасть не должны.

Опционально: обеспечить возможность вывода отдельной строки таблицы для конкретного символа (как по самому символу, так и по его коду). Продумать поведение приложение при чередовании режимов последовательного вывода и поиска по символу.

Дать возможность нативно прервать приложение (т.е. не только подавая соответствующий сигнал через Ctrl+C).

Перед демонстрацией работы убедиться, что исходный (кодируемый) и расшифрованный файлы не отличаются друг от друга. Сделать это можно утилитой diff:

diff file1.txt file2.txt

Если они одинаковые, то команда не выведет ничего, а “echo $?” выведет 0. Подробнее можно узнать в справке (для этого надо запустить утилиту с соответствующим флагом).

Для адекватной работы для кодируемого файла и кодового блокнота необходимо использовать текстовые файлы, состоящие только из символов, принадлежащих стандартной таблице ASCII (символы английского алфавита и знаки препинания, различные служебные символы). Кодировка таких файлов должна быть UTF-8.

Кодировка текста - довольно сложная тема, которую нецелесообразно полноценно поднимать в рамках данного курса. Особенно, когда это касается C++. Подробнее про UTF-8 можно прочитать тут.

Отдельно также стоит упомянуть проблему признака переноса строки (\n, \n\r, \r\n, \r\r). В Linux для переноса строки используется \n. Обычно, ввод и вывод корректно обрабатываются в зависимости от операционной системы, даже если использовать только \n, но при работе с файлами в бинарном режиме это может повлиять на результат. Поэтому стоит убедиться, что все переносы строк состоят только из \n (например, вручную скопировать текст в файл).

Размеры исходных файлов с текстом должны быть не меньше нескольких килобайт (желательно как минимум несколько десятков килобайт).