Лабораторная работа №6 «Создание приложений Windows Forms для работы с потоковыми файлами» Цель выполнения данной лабораторной работы состоит в овладении практическими навыками программирования вычислительного процесса, связанного с созданием, чтением и записью текстовых потоковых файлов, обработкой содержащейся в них информации, а также получении дальнейших навыков по отладке и тестированию программ. 1. Вопросы, подлежащие изучению 1) 2) 3) 4) 5) 6) 7) Понятие файла. Способы доступа к данным файла. Понятие потока. Виды потоков. Буферизация данных. Виды действий с потоками. Ошибки времени выполнения. Класс OpenFileDialog, его свойства и методы. Класс SaveFileDialog, его свойства и методы. Классы StreamReader и StreamWriter, их свойства и методы для работы с текстовыми файлами. 2. Общее задание 1) Изучите вопросы программирования алгоритмов обработки текстовых потоковых файлов. 2) Выберите вариант задания из таблицы 1. 3) Проведите формализацию поставленной задачи. 4) Разработайте проект графического интерфейса пользователя. 5) Разработайте схемы алгоритмов процедур и программные коды функций пользователя в соответствии с индивидуальным заданием. Используйте алгоритмы и программные коды функций обработки строки из предыдущей лабораторной работы. 6) Разработайте программные коды событийных процедур. 7) Разработайте проект приложения Windows Form, содержащий: графический интерфейс; файл (файлы) с раздельно откомпилированными программными кодами функций, необходимых для решения задачи; событийные процедуры, которые должны содержать только операторы вызова пользовательских функций и контроля корректности исходных данных. 8) Создайте в приложении Блокнот текстовый файл со строками, подходящими для тестирования приложения данного варианта индивидуального задания. При сохранении файла выберите кодировку UTF-8. 9) Выполните приложение и получите результаты. 10) Докажите правильность полученных результатов. 3. Варианты индивидуальных заданий Таблица 1 1) 2) 3) 4) 5) 6) 7) 8) 9) 10) 11) 12) 13) 14) 15) 16) В текстовом файле найти строку, содержащую наибольшее количество цифр, идущих подряд. Зашифровать каждую строку текстового файла, содержащего русские буквы, пробелы и знаки препинания, заменив каждую букву на непосредственно следующую за ней по алфавиту ("а" на "б", "б" на "в", …."я" на "а"). В текстовом файле найти строку, содержащую наибольшее количество слов, начинающихся и заканчивающихся на одну и ту же букву В текстовом файле найти строки, в которых не было ни одной замены каждого третьего слова «мама» на слово «мамочка». Из каждой строки текстового файла удалить все символы, входящие в нее более одного раза и найти самую короткую строку. Преобразовать каждую строку текстового файла, повторив в ней каждый символ, совпадающий с заданным, и найти самую длинную строку. Записать в новый файл те строки исходного текстового файла, из символов которых можно составить вашу фамилию. В каждой строке текстового файла определить максимальную длину подстроки, состоящей из заданного символа, и найти сумму этих длин. Исключить из каждой строки текстового файла группы символов, расположенных между круглыми скобками, включая сами скобки. Предполагается, что внутри каждой пары скобок нет других скобок. Найти самую длинную строку. В текстовом файле найти строку, содержащую наименьшее количество слов четной длины, в которых нет буквы «а». Записать в новый файл те строки исходного текстового файла, в которых нет ни одного слова, содержащего ровно три буквы «а». В каждой строке текстового файла определить самое длинное слово нечетной длины и записать эти слова в новый файл. В текстовом файле найти строку, содержащую самое короткое слово четной длины. Каждая строка текстового файла содержит дату в формате "mm-dd-yyyy", где mm - месяц, dd - день, yyyy - год. Записать в новый файл только те строки исходного текстового файла, которые содержат корректно заданные даты, изменив их формат на "dd.mm.yy", где yy - две последние цифры года. Из каждой строки текстового файла, не содержащего цифр, получить "сжатую" строку, заменив самую длинную подстроку вида "XXX…XX" на подстроку вида "nX", где X - повторяющийся символ, n - число его повторений и записать в новый файл только измененные строки. Записать в новый файл те строки исходного текстового файла, которые нельзя преобразовать в число. 17) 18) 19) 20) 21) 22) 23) 24) 25) 26) 27) 28) 29 30) Из каждой строки текстового файла получить новую строку, записывая каждый повторяющийся подряд символ исходной строки только один раз, и записать эти строки в новый файл. В каждой строке текстового файла, содержащего натуральные числа, подсчитать сумму цифр и найти строку с наименьшей суммой. В текстовом файле, не содержащем букв русского алфавита, найти строку с максимальным процентом гласных букв (a, e, i, o, u, y). Записать в новый файл те строки исходного текстового файла, в которых самое длинное слово встречается раньше, чем самое короткое слово. Преобразовать каждую строку текстового файла, удалив из каждого слова нечетной длины средний символ, и найти строку с минимальным количеством удалений. В текстовом файле найти строку, содержащую наибольшее количество симметричных слов, т.е. читающихся одинаково слева направо и справа налево. Записать в новый файл те строки исходного текстового файла, которые являются записью вещественного числа с нулевой дробной частью. Преобразовать каждую строку текстового файла, заменив в ней слова, состоящие только из прописных букв, на слова, состоящие только из строчных букв, и найти строку с максимальным количеством замен. Записать в новый файл те строки исходного текстового файла, латинские буквы которых расположены в алфавитном порядке. Записать в новый файл те строки исходного текстового файла, которые являются записью целого числа. Записать в новый файл те строки исходного текстового файла, в которых нет nого с конца вхождения заданного символа. Преобразовать каждую строку текстового файла, состоящую из слов длиной менее 10 символов и разделенных запятыми, заменив запятые группами пробелов так, чтобы каждое слово начиналось с позиции 10*(k - 1) + 1, где k номер слова. Преобразовать каждую строку текстового файла, вставив в середину каждого слова четной длины букву «К», и найти строку с максимальным количеством вставок. Преобразовать каждую строку текстового файла, заменив в ней слова, состоящие только из строчных букв, на слова, состоящие только из соответствующих прописных букв, и найти строку с минимальным количеством замен. 4. Содержание отчёта 1) Титульный лист с указанием номера и названия работы, варианта индивидуального задания, группы и Ф.И.О. студента, Ф.И.О. преподавателя. 2) Общее и индивидуальное задание. 3) Формализация и уточнение задания. 4) Рисунки, таблицы и скриншоты, отражающие этапы разработки приложения: 4.1) графический интерфейс пользователя; 4.2) таблица используемых объектов и их свойств; 4.3) схемы алгоритмов решения поставленной задачи; 4.4) программный код разработанных функций, событийных процедур и заголовочных файлов; 4.5) результаты выполнения приложения; 4.6) доказательство правильности результатов. 5. Пример выполнения задания 1) Индивидуальное задание на разработку проекта Создать проект решения следующей задачи: В каждой строке текстового файла, состоящей из слов на русском языке, разделенных одним или несколькими пробелами, точками, запятыми и тире, найдите первое слово с равным количеством гласных и согласных букв и выведите его в новый файл. Если такое слово не найдено, выведите в новый файл пустую строку. 2) Формализация задачи Из условия задания следует, что его выполнение распадается на следующие этапы: открытие входного файла для чтения строк; открытие выходного файла для записи строк; чтение из входного файла очередной строки; вывод очередной строки в соответствующий объект формы; обработка очередной строки с использованием функций, разработанных в предыдущей лабораторной работе; вывод результата обработки в выходной файл; вывод результата обработки в соответствующий объект формы. 3) Разработка графического интерфейса пользователя приложения Графический интерфейс проекта изображен на рис. 1. Форма содержит 12 объектов: текстовое поле txtInpPath для отображения полного пути к входному файлу; текстовое поле txtOutPath для отображения полного пути к входному файлу; список lstInpFile для отображения строк входного файла; список lstOutFile для отображения строк выходного файла кнопку cmdOpenInpFile для перехода в окно диалога выбора входного файла; кнопку cmdOpenOutFile для перехода в окно диалога выбора выходного файла; кнопку cmdExec для запуска процедуры чтения и обработки входного файла; кнопку cmdExit для выхода из приложения; четыре надписи, комментирующие назначение текстовых полей и списков. Имена объектов (кроме надписей использованием правил венгерской нотации. Label) сформированы с Рисунок 1 – Форма проекта В таблице 2 приведены установленные при конструировании свойства основных объектов формы. Таблица 2 Тип объекта Текстовое поле Класс объекта TextBox Текстовое поле TextBox Список ListBox Свойство Name Font TabStop Enabled Name Font TabStop Enabled Name Значение свойства txtInpPath Microsoft Sans Serif; 11,25pt False False txtOutPath Microsoft Sans Serif; 11,25pt False False lstInpFile Список ListBox Кнопка Button Кнопка Button Кнопка Button Кнопка Button Font TabStop ScrollAlwaysVisible Name Font TabStop ScrollAlwaysVisible Name Font Text TabIndex Name Font Text TabIndex Name Font Text TabIndex Name Font Text TabIndex Microsoft Sans Serif; 11,25pt False True lstOutFile Microsoft Sans Serif; 11,25pt False True cmdOpenInpFile Microsoft Sans Serif; 9,75pt; Bold Открытие входного файла… 1 cmdOpenOutFile Microsoft Sans Serif; 9,75pt; Bold Открытие выходного файла… 2 cmdExec Microsoft Sans Serif; 9,75pt; Bold Обработка файлов 3 cmdExit Microsoft Sans Serif; 9,75pt; Bold Завершение работы 4 4) Разработка схем алгоритмов функций Схемы алгоритмов функций, предназначенных для обработки отдельной строки, копируются из предыдущей лабораторной работы и здесь повторно не рассматриваются. На рис. 2 приведена схема алгоритма единственной новой функции – FileProc. Функция получает в качестве входных параметров входной и выходной потоки sr и sw, а также списки для отображения строк входного и выходного файлов lstInFile и lstOutFile. В итеративном цикле с предусловием (пока не достигнут конец входного потока) выполняется чтение строк из входного потока; вывод прочитанной строки в соответствующий список формы; вызов функции Find, возвращающей первое слово с одинаковым количеством гласных и согласных букв; вывод найденного слова в выходной поток, вывод найденного слова в соответствующий список формы. Вх. параметры: вх. поток строк sr; вых. поток слов sw; список отображения строк вх. файла lstInFile; список отображения слов вых. файла lstOutFile. FileProc Инициализация cтроки: InBuffer = "" Инициализация слова: OutBuffer = "" Конец потока? Да Нет Чтение очередной строки из sr в InBuffer Длина строки InBuffer == 0 Да Нет Запись строки InBuffer в список lstInFile OutBuffer=Find(InBuffer) Функция Find находит в строке InBuffer первое слово с равным количеством гласных и согласных букв Запись слова OutBuffer в sw Запись слова OutBuffer в список lstOutFile конец Рисунок 2 – Схема алгоритма функции FileProc 5) Разработка программного кода приложения 5.1) Файл с функциями пользователя Функции пользователя, служащие для обработки файлов, находятся в файле files.cpp. Функции, предназначенные для обработки отдельной строки, копируются из предыдущей лабораторной работы и здесь повторно не рассматриваются. На рис. 3 приведен программный код функции FileProc, вызываемой из событийной процедуры. Функция получает в качестве входных параметров указатели на входной и выходной потоки sr и sw, а также указатели на списки для отображения строк входного и выходного файлов lstInFile и lstOutFile. Вначале объявляются и инициализируются пустыми строками строковые переменные InBuffer и OutBuffer – буферы для чтения и записи строк в файлы. Затем организуется цикл while, в котором выполняется вся обработка файлов. В заголовке цикла производится чтение очередной строки входного файла в буфер InBuffer с помощью метода ReadLine. При достижении конца потока этот метод возвращает значение null, обеспечивая выход из цикла. Рисунок 3 – Программный код функции FileProc Пока цикл повторяется, выполняются следующие действия: 1) проверка прочитанной строки на непустое значение, в случае пустой строки пропуск ее и переход к следующей итерации с помощью оператора continue; 2) добавление прочитанной строки в список lstInFile формы; 3) вызов функции Find для получения слова – результата обработки входной строки и запись результата в буфер OutBuffer; 4) вывод содержимого буфера в выходной файл с помощью метода WriteLine; 5) добавление полученного слова в список lstOutFile формы. В процессе повторения цикла возможны ошибки времени выполнения, для обработки которых использована конструкция try – catch. 5.2) Программный код заголовочного файла files.h Функция обработки файлов FileProc и вызываемые ею функции находятся в отдельном созданном файле files.cpp. Прототипы всех этих функций находятся в заголовочном файле files.h (рис. 4). Файл tchar.h необходим по причине использования типа данных TCHAR в коде функции Find. Доступ к пространству имен System::IO необходим для работы с файлами. Рисунок 4 – Текст заголовочного файла files.h 5.3) Событийные процедуры Событийные процедуры проекта приведены на рис 5, 6, 7, 9, 11. Рисунок 5 – Событийная процедура загрузки формы В процедуре Form1_Load события загрузка формы очищаются списки формы и текстовые поля, а также делается недоступной кнопка Обработка файлов (она станет доступной только после открытия входного и выходного файлов). Рисунок 6 – Событийная процедура кнопки Завершение работы В процедуре cmdExit_Click события нажатие кнопки Завершение работы выполняется выход из приложения. Выход можно выполнить также закрытием окна с формой. В событийной процедуре кнопки Открытие входного файла производится выбор текстового файла, созданного заранее в приложении Блокнот. Выбор производится с помощью стандартного диалога, создаваемого с использованием класса OpenFileDialog. Рисунок 7 – Событийная процедура кнопки Открытие входного файла Вначале создается объект openFileDialog указанного класса. Затем определяются его свойства, и вызывается метод ShowDialog, выводящий на экран окно выбора файла (рис. 8). Основные свойства и методы класса OpenFileDialog приведены в Приложении 1. После выбора файла и нажатия кнопки Открыть (DialogResult::OK) полный путь к файлу (свойство FileName) отображается в текстовом поле формы txtInPath. При нажатии кнопки Отмена это поле инициализируется пустой строкой. В завершение устанавливается доступность кнопки Обработка файлов: она станет доступной только после выбора обоих файлов, входного и выходного. Рисунок 8 – Окно выбора входного файла Рисунок 9 – Событийная процедура кнопки Открытие выходного файла В событийной процедуре кнопки Открытие выходного файла выполняется установка полного пути к текстовому файлу, в который будут выводиться результаты обработки строк входного файла. Установка производится с помощью стандартного диалога, создаваемого с использованием класса SaveFileDialog. Основные свойства и методы класса SaveFileDialog приведены в Приложении 1. Метод ShowDialog класса SaveFileDialog выводит на экран окно, изображенное на рис. 10. Следует выбрать папку для файла, в поле Имя файла ввести его имя (на данном рисунке – Слова) и нажать кнопку Сохранить. Установленный полный путь к файлу отображается в текстовом поле формы txtOutPath. Затем снова устанавливается доступность кнопки Обработка файлов: она станет доступной только после выбора обоих файлов, входного и выходного. Рисунок 10 – Окно установки пути к выходному файлу Событийная процедура кнопки Обработка файлов подготавливает и запускает процесс обработки. Вначале очищаются списки формы, предназначенные для отображения содержимого обоих файлов: входного и выходного. Пути к файлам копируются из текстовых полей в строковые переменные InFile и OutFile. Затем объявляются и инициализируются объекты sr и sw классов потокового ввода–вывода StreamReader и StreamWriter, соответственно. Основные свойства и методы этих классов приведены в Приложении 2. Операторы создания потоков помещены в блок try, чтобы обработать возможные исключения при создании. При возникновении исключений выполняется блок catch, в котором выводится сообщение об ошибке, закрываются созданные потоки и производится выход из событийной процедуры. При отсутствии ошибок вызывается пользовательская функция FileProc обработки файлов. В функцию передаются в качестве параметров созданные потоки и списки формы для вывода содержимого файлов. После завершения выполнения функции оба потока закрываются. Рисунок 11 – Событийная процедура кнопки Обработка файлов 6) Результаты выполнения приложения На рис. 12 приведены результаты выполнения приложения. Рисунок 12 – Результаты работы приложения 7) Доказательство правильности результата Правильность работы приложения подтверждается приведенными выше результатами его выполнения. Приложение 1 Таблица П.1.1. Основные свойства классов OpenFileDialog и SaveFileDialog Свойства класса Свойства класса Описание OpenFileDialog CheckFileExists – SaveFileDialog CheckFileExists CreatePrompt DefaultExt DefaultExt FileName FileName Filter Filter При установленном значении True проверяет существование файла с указанным именем и в случае его отсутствия выдает предупреждение. При установленном значении True в случае указания несуществующего файла выдается запрос на разрешение создать новый файл. Определяет расширение файла, добавляемое по умолчанию в случае, когда пользователь вводит имя файла без расширения. Определяет полное имя файла, выбранного в диалоговом окне. Задает значения списка Тип файла, определяющего фильтр отображаемых в окне файлов. Например, для отображения только текстовых файлов нужно этому свойству задать значение "Text files (*.txt)|*.txt" (т.е. описание типа файлов и шаблон). Для задания нескольких фильтров, в качестве их разделителя применяется символ "|", напри-мер: "Text files (*.txt)|*.txt|All files (*.*)|*.*". FilterIndex FilterIndex InitialDirectory InitialDirectory Multiselect – – OverwritePrompt ReadOnlyChecked RestoreDirectory – RestoreDirectory ShowReadOnly Title – Title Задает отображаемый по умолчанию фильтр при использовании нескольких фильтров. Задает каталог, отображаемый при первом вызове диалогового окна. По умолчанию используются активные устройство и папка, т.е. те, которые просматривались при последнем вызове этого диалогового окна. При установленном значении True позволяет выбирать несколько файлов в диалоговом окне. При установленном значении True (рекомендуется) в случае выбора существующего файла выдается сообщение, что данный файл уже существует и будет перезаписан. Определяет, установлен ли флажок доступности только для чтения. При установленном значении True задает отображение при очередном вызове того каталога, который открывался при последнем вызове диалогового окна. Определяет, отображается ли в диалоговом окне флажок доступности только для чтения. Определяет текст заголовка диалогового окна. По умолчанию окну присваивается стандартный для Windows заголовок. Приложение 2 Имя BaseStream CurrentEncoding EndOfStream Таблица П.2.1. Основные свойства и методы класса StreamReader Описание Свойства Возвращает основной поток. Получает текущую кодировку символов, используемую текущим объектом StreamReader. Получает значение, определяющее, находится ли текущая позиция потока в его конце. Методы Close(); Read(); Read(arrCh,i,n); ReadBlock(arrCh,i,n); ReadLine(); ReadToEnd(); Имя Encoding Close(); Закрывает объект StreamReader и основной поток и освобож-дает все системные ресурсы, связанные с устройством чтения. Выполняет чтение следующего символа из входного потока и перемещает положение символа на одну позицию вперед. Считывает в буфер (arrCh) заданное максимальное количество (n) символов из текущего потока, начиная с заданного индекса (i). Считывает заданное максимальное количество (n) символов из текущего потока, начиная с заданного индекса (i), и записывает данные в буфер (arrCh). Выполняет чтение строки символов из текущего потока и возвращает данные в виде строки или null (если достигнут конец входного потока). Считывает поток, начиная с текущей позиции ввода и до его конца. Таблица П.2.2. Основные свойства и методы класса StreamWriter Описание Свойства Получает кодировку Encoding, в которой осуществляется запись выходных данных. Методы Закрывает текущий объект StreamWriter (файл) и базовый поток. Записывает в текстовый файл 1, 2 или 3 объекта (v – числового, строкового, символьного или логического типа) в соответствии с заданным форматом (sf). Write(v); Write(sf,v1); Write(sf,v1,v2); Write(sf,v1,v2,v3); WriteLine(v); WriteLine(sf,v1); WriteLine(sf,v1,v2); WriteLine(sf,v1,v2,v3); Записывает в текстовый файл 1, 2 или 3 объекта (v – числового, строкового, символьного или логического типа) в соответствии с заданным форматом (sf). В завершении выводится признак конца строки.