Конвертер файлов
Рисунок 2.1 — Конечный автомат возможных переходов На основе построенного автомата можно построить нисходящий распознаватель с возвратом (с подбором альтернатив). Нисходящий распознаватель с возвратом служит для определения принадлежности цепочки к грамматике. Он анализирует текущее состояние, ищет правило перехода из текущего состояния в следующее, если следующее состояние совпадает… Читать ещё >
Конвертер файлов (реферат, курсовая, диплом, контрольная)
За все время существования компьютеров было разработано немало операционных систем. Сейчас их количество измеряется в десятках и в различных семействах существуют форматы файлов, используемых только в определенной линейке операционных систем. Если, например, для изображений существуют универсальные программы-редакторы, открывающие любой формат файлов, содержащих изображения, поддерживаемых операционных систем, то, например, для баз данных таких редакторов нет.
Для работы с каждым из форматов баз данных существует индивидуальная система управления базами данных. Существует огромное количество разновидностей баз данных, отличающихся по различным критериям:
1) Классификация по модели данных:
а) иерархическая;
б) сетевая;
в) реляционная;
г) объектная и объектно-ориентированная;
д) объектно-реляционная, функциональная.
2) Классификация по среде постоянного хранения:
а) во вторичной памяти, или традиционная;
б) в оперативной памяти;
в) в третичной памяти.
3) Классификация по степени распределённости:
а) централизованная, или сосредоточенная;
б) распределённая.
4) Другие виды БД а) пространственная;
б) временная;
в) пространственно-временная;
г) циклическая.
Большое обилие различных баз данных не позволяет напрямую перевести содержимое базы из одного типа в другой. Для решения данной проблемы существуют программы-конвертеры, преобразующие один формат баз данных в другой. Как правило, конвертеры существуют только для самых распространенных форматов баз данных, что не позволяет напрямую перевести какой-то устаревший формат в современный. Использовать два конвертера не рационально, поэтому оптимальное решение это — в качестве промежуточного этапа хранить базы данных в XML файлах.
XML-файлы и файлы других расширений, основанные на языке XML, получили очень широкое распространение, практически любая современная операционная система поддерживает этот формат файлов. В XML-файлах хранятся самые различные данные — от настроек приложений до баз данных. Файлы на основе XML используются для обмена информацией в Интернете и между программами (для этого данный язык разметки и был изначально задуман). Так как файлы формата XML содержат текстовые данные, их можно легко отредактировать в любом текстовом редакторе, а так же задать любую, удобную для пользователя, кодировку данных. Кроме этого существует большое количество генераторов XML документов.
1. ИССЛЕДОВАНИЕ И АНАЛИЗ ПРЕДМЕТНОЙ ОБЛАСТИ
1.1 Описание поставленной задачи
В выпускной квалификационной работе требуется реализовать программу-конвертер, создающую на основе содержимого, передаваемых dbf файлов, файл формата XML по заданному пользователем шаблону. Количество и структура dbf файлов могут быть любыми, выходной XML файл должен быть всегда один. Для каждого dbf файла существует свой шаблон, на основе которого программа записывает информацию в XML файл. Необходимо реализовать возможность создания шаблонов двумя способами: при помощи кода и при помощи конструктора. В шаблонах, созданных при помощи кода должен осуществляться выбор, какие именно данные необходимо записывать в выходной файл. Эта возможность осуществляется с помощью специальных кодовых команд, разработанных специально для этой программы. В шаблонах, созданных при помощи конструктора, требуется реализовать простой и удобный интерфейс, который позволит создавать настраиваемые шаблоны, на основе которых программа записывает информацию в XML файл.
1.2 Обоснование актуальности исследуемой задачи
программа конвертер файл шаблон
XML — рекомендованный Консорциумом Всемирной паутины язык разметки, фактически представляющий собой свод общих синтаксических правил. XML — текстовый формат, предназначенный для хранения структурированных данных (взамен существующих файлов баз данных), для обмена информацией между программами, а также для создания на его основе более специализированных языков разметки (например, XHTML).
XML-документ является базой данных лишь в самом общем смысле этого слова, то есть, он является коллекцией данных. Этим он не отличается от многих других файлов — в конечном итоге, все файлы состоят из данных определенного вида. Как формат «базы данных» XML имеет некоторые преимущества, например, он самоописывающий (разметка описывает данные). Легко обеспечить его обработку различным программным обеспечением, поскольку данные хранятся в Unicode, он хранит данные в виде древовидной или графоподобной структуры. Но у него есть и некоторые недостатки, например, он, слишком многословен и относительно медленно получает доступ к данным из-за необходимости парсирования и конвертирования текста.
К положительным сторонам можно отнести то, что XML позволяет реализовать многое из того, что можно обнаружить в обычных базах данных: хранение (XML-документы), схемы (DTD, язык XML-схем), языки запросов (XQuery, XPath, XQL, XML-QL, QUILT, и т. д.), программные интерфейсы (SAX, DOM, JDOM), и т. д. К недостаткам же можно отнести отсутствие многих возможностей, имеющихся в современных базах данных: экономичность хранения, индексы, безопасность, транзакции и интегрированность данных, многопользовательский доступ, триггеры, запросы по многим документам и т. д.
Таким образом, хотя и можно использовать XML-документы в качестве базы данных в средах с небольшим количеством данных, небольшим количеством пользователей и невысокими требованиями к производительности, этого нельзя сделать в большинстве бизнес-сред, в которых действует множество пользователей, действуют строгие требования к интегрированности данных и высокие требования к производительности.
Примером «базы данных», для которой подходит XML-документ, является .ini-файл — то есть, файл, в котором содержится информация о конфигурации приложения. Гораздо легче придумать язык программирования с небольшим набором функций на основе XML и написать SAX-приложение для его интерпретации, чем создать парсер для файлов, в которых данные разделены запятыми. Кроме того, XML позволяет вкладывать друг в друга элементы данных — это довольно трудно сделать при разделении данных запятыми. Однако такие файлы трудно назвать базами данных в полном смысле этого слова, поскольку они читаются и записываются линейно и только при открытии или закрытии приложения.
Наиболее интересными примерами наборов данных, в которых удобно использовать XML-документ как базу данных, является личный список контактов (имен, номеров телефонов, адресов и т. д). Однако, в связи с низкой стоимостью и удобством пользования такими базами данных, как dBASE и Access, даже в этих случаях нет особых причин использовать в качестве базы данных XML-документ. Единственное реальное преимущество XML состоит в легкой переносимости данных из одного приложения в другое, но это преимущество не так важно, поскольку уже сейчас широко распространены инструменты для сериализации баз данных в XML-формат.
Разработка программного обеспечения актуальна по следующим причинам:
— формат баз данных dbf устарел и не отвечает современным требованиям;
— у формата XML нет жестких требований к содержимому, пользователь может хранить данные в произвольном порядке и создавать теги с любым названием;
— ни одна программа-конвертер не позволяет создавать собственную структуру XML файла и записывать данные из нескольких файлов dbf формата.
1.3 Обзор методов решения подобных задач
«White Town» дает возможность конвертировать dbf файлы в XML формат. Программа может конвертировать dbf файлы форматов dBase III, dBase IV, FoxPro, VFP и dBase Level 7. Программа поддерживает интерфейс командной строки. Таким образом, ее можно запускать из .BAT или .LNK файла предварительно указав нужные параметры или по расписанию из планировщика Windows. Недостатком данного программного продукта является отсутствие возможности настраивать формат выходного файла.
«DBF Converter» — это многосторонняя и в то же время простая в использовании программа преобразования. Данная программа имеет интерфейс по типу Мастера, но также может быть использована в качестве утилиты командной строки для обработки группы файлов. «DBF Converter» поддерживает все современные форматы обмена данными, такие как XML, CSV, TXT, HTML, RTF, PRG и другие. Реализована возможность преобразовать DBF таблицы в SQL сценарий, который может быть импортирован в любую SQL базу данных.
В дополнение к простым преобразованиям, «DBF Converter» позволяет манипулировать данными, выбирая только определенные столбцы и применяя фильтры. В отличие от упрощенных фильтрационных правил, которые обычно имеются в других DBF приложениях, «DBF Converter» динамично составляет простые формы записи баз данных. Возможность установки улучшенной маски и правил в любое поле простой записи — это одна из самых ценных из имеющихся функций в «DBF Converter». Основным недостатком данного программного обеспечения является его стоимость в 29.95 у.е.
«DBF View» — бесплатная, компактная и удобная програма для работы с DBF файлами. Не требует инсталляции, работает без дополнительных драйверов и библиотек.
Главное преимущество это универсальность, быстрый и гибкий линейный поиск, который по скорости превосходит многие SQL.
Дополнительные возможности:
— поиск по маске (шаблон);
— редактирование, замена, удаление, создание, добавление данных;
— сортирование полей;
— мультиязычность и создание новых словарей;
— импорт и экспорт DBF, TXT, CSV, SQL, XML;
— перекодировки в DOS, Windows, транслит и другие;
— автозагрузка баз данных из определенной директории;
— пароль на запуск;
— запись истории.
Основным недостатком данного программного обеспечения является невозможность создания шаблонов при конвертации.
1.4 Постановка задачи, системные требования, требования к выходным данным и выходным формам
Изучив поставленную задачу, исследовав ее актуальность и проанализировав существующие программы-конвертеры, был составлен список необходимых требований для разрабатываемого программного обеспечения.
В программном продукте необходимо реализовать следующие функции:
— чтение содержимого dbf файлов;
— создание шаблонов в одном из двух редакторов;
— редактирование шаблонов;
— выбор порядка конвертации dbf файлов;
— исполнение шаблонов;
— ведение журнала ошибок;
— сохрание результатов работы программы в XML файл.
Программное обеспечение написанно на Microsoft Visual Studio 2008 и требует для своего запуска:
— Операционная система семейства Windows одной из версий: Windows Vista, Windows 7 или Windows 8;
— Microsoft .NET Framework 4;
— Visual FoxPro ODBC Drivers.
Минимальные системные требования к программному продукту соответсвуют минимальным требованиям к операционной системе.
В качестве входных данных могут быть файлы формата dbf версии dBase II, dBase III или dBase IV.
В качестве выходных файлов должен быть файл формата XML с версией языка 1.x и поддержкой любого браузера.
Путь к входным и выходным файлам может быть произвольный.
1.5 Выводы
В первой главе выпускной квалификационной работы была исследованна поставленная задача и составлен определен перечень функций, которые необходимо реализовать в программном продукте, а так же список системных требований и требований к входным и выходным файлам.
Основными пунктами рассмотрения в первой главе стали:
— описание поставленной задачи;
— обоснование актуальности;
— обзор методов решения подобных задач;
— постановка задачи, системные требования, требования к выходным данным и входным формам.
2. ПРОЕКТИРОВАНИЕ СТРУКТУРЫ И АРХИТЕКТУРЫ ПРОГРАММНОГО ПРОДУКТА
2.1 Выбор методов и средств для реализации, его обоснование
Для разработки программного продукта была выбрана интегрированная среда разработки Microsoft Visual Studio 2008.
Visual Studio 2008 — выпущена 19 ноября 2007, одновременно с .NET Framework 3.5. Нацелена на создание приложений для операционной системы Windows Vista (но поддерживает и XP), Office 2007 и веб-приложений. Включает в себя LINQ, новые версии языков C# и Visual Basic. В студию не вошёл Visual J#. Одним из его плюсов является полностью русский интерфейс.
Visual Studio включает в себя редактор исходного кода с поддержкой технологии IntelliSense и возможностью простейшего рефакторинга кода. Встроенный отладчик может работать как отладчик уровня исходного кода, так и как отладчик машинного уровня. Остальные встраиваемые инструменты включают в себя редактор форм для упрощения создания графического интерфейса приложения, веб-редактор, дизайнер классов и дизайнер схемы базы данных. Visual Studio позволяет создавать и подключать сторонние дополнения (плагины) для расширения функциональности практически на каждом уровне, включая добавление поддержки систем контроля версий исходного кода (как например, Subversion и Visual SourceSafe), добавление новых наборов инструментов (например, для редактирования и визуального проектирования кода на предметно-ориентированных языках программирования или инструментов для прочих аспектов процесса разработки программного обеспечения (например, клиент Team Explorer для работы с Team Foundation Server).
Все инструментальные среды Visual Studio 2008 на основе языка C# отличаются такими особенностями, как:
— возможностью формулировать задачи на языке взаимодействия объектов;
— высокой модульностью программного кода;
— адаптируемостью к желанием пользователей;
— высокой степенью повторной используемости программ;
— большое число подключаемых библиотек.
2.2 Описание применяемых алгоритмов
В разработке данного программного обеспечения можно выделить две основные трудности: построение распознавателя для программируемых шаблонов и создание программной модели, которая бы использовалась в шаблонах, создаваемых при помощи конструктора.
1. Программируемые шаблоны. Так как код, используемый в шаблонах, чем-то схож с кодом, используемым в языках программирования, необходимо, чтобы данный распознаватель перенял некоторые функции компилятора кода, а точнее его анализирующие функции. В структуре компилятора анализирующая часть состоит из лексического, синтаксического и семантического анализа. Лексический анализатор читает литеры программы на исходном языке и строит из них лексемы исходного языка. Результатом его работы становится таблица идентификаторов. Синтаксический анализатор выполняет выделение синтаксических конструкций в тексте исходной программы, обработанным лексическим анализатором. Приводит синтаксические правила программы в соответствие с грамматикой языка. Синтаксический анализатор является распознавателем текста входного языка. Семантический анализатор проверяет правильность текста исходной программы с точки зрения смысла входного языка.
С помощью кода должны реализоваться следующие возможности: создание цикла, получение и вывод данных о количестве строк и столбцов, получение типа данных и названия столбцов, а так же получение содержимого ячеек базы данных. Для этого в первую очередь необходимо составить список всех возможных состояний автомата. Возможные состояния распознавателя представлены в таблице 2.1.
Таблица 2.1 — Список возможных состояний распознавателя
Индекс состояния | Состояние | Описание | |
S1 | Переменная | Счетчик цикла | |
S2 | Для | Служебное слово, обозначающее начало цикла | |
S3 | До | Служебное слово, обозначающее условие выхода цикла | |
S4 | Столбец | Служебное слово, обозначающее, что дальнейшее обращение будет к столбцам базы | |
S5 | Строка | Служебное слово, обозначающее, что дальнейшее обращение будет к строкам базы | |
S6 | Количество | Служебное слово, обозначающее количество строк или столбцов, в зависимости к чему было предыдущее обращение | |
S7 | Тип | Служебное слово, обозначающее вывод типа данных столбца к которому следует обращение | |
S8 | Название | Служебное слово, обозначающее вывод названия столбца к которому следует обращение | |
S9 | . (точка) | Специальный символ, разделяющий служебные слова | |
S10 | = (знак равенства) | Специальный символ, обозначающий, какое значение будет присвоено переменной при начале работы цикла | |
S11 | [ (открывающаяся прямоугольная скобка) | Специальный символ, обозначающий, что далее последует обращение к какому-то конкретному столбцу или строке | |
S12 | ] (закрывающаяся прямоугольная скобка) | Специальный символ, обозначающий, что было обращение к какому-то конкретному столбцу или строке | |
S13 | Число | Любое целое число | |
На основании составленной таблицы можно построить конечный автомат возможных переходов состояний. На рисунке 2.1 изображен конечный автомат.
Рисунок 2.1 — Конечный автомат возможных переходов На основе построенного автомата можно построить нисходящий распознаватель с возвратом (с подбором альтернатив). Нисходящий распознаватель с возвратом служит для определения принадлежности цепочки к грамматике. Он анализирует текущее состояние, ищет правило перехода из текущего состояния в следующее, если следующее состояние совпадает, то процедура повторяется для следующего. Если распознаватель не может найти правило перехода из текущего состояния в следующее, значит, эта цепочка не принадлежит данной грамматике, то есть строка кода написана с логической ошибкой. Если вариантов перехода несколько, то распознаватель запоминает состояние, в котором возникла альтернатива и возвращается к нему, если цепочка не принадлежит грамматике.
Во время анализа шаблонов ведется журнал ошибок, содержащий в себе информацию о том, в каком шаблоне ошибка, в какой конкретно строке кода и тип ошибки. Ошибки могут быть следующих типов: неопознанный идентификатор (попытка использовать служебные слова или специальные символы, непредусмотренные данным кодом), нарушение логического смысла (строка кода не прошла проверку распознавателем), попытка обратиться к несуществующей переменной (обращение переменной к не созданной переменной или обращение к переменной вне цикла), не указано начало цикла (начало и конец цикла должны быть обязательно указаны в виде открывающейся и закрывающейся фигурных скобок).
2. Шаблоны, создаваемые при помощи конструктора. Одним из вариантов решения является структура, используемая в логических языках программирования: применять фильтры условий к общей входной информации, которой в данном случае является содержимое таблицы базы данных. На рисунке 2.3 изображена общая структура таблицы баз данных.
название | название | название | название | название | |
значение | значение | значение | значение | значение | |
значение | значение | значение | значение | значение | |
значение | значение | значение | значение | значение | |
значение | значение | значение | значение | значение | |
значение | значение | значение | значение | значение | |
значение | значение | значение | значение | значение | |
значение | значение | значение | значение | значение | |
значение | значение | значение | значение | значение | |
Рисунок 2.3 — Общая структура таблицы БД
3.
4. В качестве реализации было выбрано решение с использованием «Таблицы истинности». Эта таблица представляет собой таблицу, с n+1 столбцов и m+1 строк, где n и m — число столбцов и строк во входной таблице. Каждая ячейка таблицы хранит значение true или false. На рисунке 2.4 изображена «Таблица истинности».
название | название | название | название | название | ||
true | true | true | true | true | true | |
true | true | true | true | true | true | |
true | true | true | true | true | true | |
true | true | true | true | true | true | |
true | true | true | true | true | true | |
true | true | true | true | true | true | |
true | true | true | true | true | true | |
true | true | true | true | true | true | |
true | true | true | true | true | ||
Рисунок 2.4 — «Таблица истинности»
В случае применения фильтра значения true заменяются на false в зависимости от того к чему применялся фильтр. Если фильтр применялся к содержимому ячеек, то значения будут меняться для каждой ячейке конкретно, а если к строкам или столбцам, то только в дополнительных строке или столбце.
При работе с базой данных можно выделить следующие сущности: индекс строки, индекс столбца, количество строк, количество столбцов, тип столбца, название столбца, содержимое ячейки.
Так же были выделены условия: «<�», «>», «=», «содержит», «совпадает».
5. Выделенных сущностей и условий достаточно, чтобы выводить все возможные данные или накладывать всевозможные условия. На рисунке 2.5 изображена «Таблица истинности» с применением фильтров.
Рисунок 2.5 — «Таблица истинности» с применением фильтров
название | название | название | название | название | ||
true | true | true | true | true | false | |
true | true | true | true | true | true | |
true | true | true | true | true | true | |
true | true | true | true | true | true | |
true | false | true | false | true | true | |
true | false | true | false | true | false | |
true | true | true | false | true | false | |
true | true | true | false | true | false | |
false | true | true | true | true | ||
При выводе информации в XML файл, программа определяет, что необходимо вывести, а затем, используя «Таблицу истинности», выводит только те значения, которые соответствуют значению true.
Для создания макета шаблона были созданы следующие типы тегов: главный, простой, глобальный, блочный.
Главный — тег, этого типа может быть всего один в документе и он обязателен, он содержит информацию о XML документе.
Простой — теги этого типа являются единственным способом выводить данные и накладывать условия на «Таблицу истинности». Они состоят из следующих частей: название, источник и условие. В качестве источника и условия используются ранее выделенные сущности. В случае если у тега будет пустое имя, его содержимое выводиться не будет, но условие к «Таблице истинности» будет применяться.
Глобальный — теги этого типа не несут логической нагрузки, они необходимы просто для вывода.
Блочный — теги этого типа необходимы для объединения логики простых тегов, а так же все что записано в блочном теге будет выводиться для каждой ячейки удовлетворяющей «Таблице истинности». Сам блочный тег в XML документ не выводится.
2.3 Структура, архитектура программного продукта
Центральное место в объектно-ориентированном программировании занимает разработка логической модели системы в виде диаграммы классов. Диаграмма классов (class diagram) служит для представления статической структуры модели системы в терминологии классов объектно-ориентированного программирования. Диаграмма классов может отражать, в частности, различные взаимосвязи между отдельными сущностями предметной области, такими как объекты и подсистемы, а также описывать их внутреннюю структуру и типы отношений.
Класс (class) в данной диаграмме служит для обозначения множества объектов, которые обладают одинаковой структурой, поведением и отношениями с объектами других классов. Графически класс изображается в виде прямоугольника, который дополнительно может быть разделен горизонтальными линиями на разделы или секции. В этих разделах могут указываться имя класса, атрибуты (переменные) и операции (методы).
Кроме внутреннего устройства или структуры классов на соответствующей диаграмме указываются отношения между классами:
Для данного приложения были выделены классы, описанные в таблице 2.2.
Таблица 2.2 — Описание классов, используемых в программном продукте
Класс | Краткое описание | Методы класса | |
Read_dbf | Класс, осуществляющий чтение из файлов формата dbf | public DataTable ReadDb (string path) | |
Template | Класс, осуществляющий работу с шаблонами созданными пользователем | public void Connect (string path) public void Search () public void Analize () public void Check (int a, int s, int indc) public void ExecuteCode (int NCode, bool cikcle, StreamReader sr, StreamWriter sw, int tempF) | |
MyCode | Класс, содержащий информацию о строках кода записанных в шаблонах | public void GetValue () | |
Tag | Класс, содержащий информацию о тегах | ||
Диаграмма классов приложения-конвертера показана на рисунке 2.6. Из диаграммы видно, что класс MyCode является переменной класса Template. Класс Template содержит следующие поля: dt, lv, thisTemplate, mycode, fs, sr, sw, correct, masCode, masPerem, masPeremCount, masSost, masCodeLength. dt — переменная типа DataTable, содержащая информацию, хранящуюся в базе данных; lv — переменная типа ListView, объект интерфейса, в который записываются сообщения об ошибках в шаблонах; thisTemplate — переменная типа string, означающая название шаблона, который обрабатывается в данный момент; mycode — массив класса MyCode, хранящий информацию о всех фрагментах кода обнаруженных в данном шаблоне; fs — переменная типа FileStream, определяющая с каким файлом будет работать программа; sr — переменная типа StreamReader, определяющая из какого файла будет считана информация; sw — переменная типа StreamWriter, определяющая в какой файл будет записываться информация; correct — переменная типа bool, указывающая на то корректно ли обработан текущий фрагмент кода; masCode — массив типа string, содержащий все найденные строки кода в шаблоне; masCodeLength — переменная типа int, указывающая сколько строк кода найдено в шаблоне; masPerem — двумерный массив типа string, содержащий название и значение созданных переменных; masPeremCount — переменная типа int, указывающая сколько переменных создано в данный момент; masSost — массив типа int, содержащий список состояний автомата для текущей строки кода.
Так же класс содержит следующие методы: Connect, Search, Analize, Check, ExecuteCode. Метод Connect осуществляет подключение к шаблону по заданному пути. Метод Search находит фрагменты кода в шаблоне. Метод Analize определяет состояния для строки кода. Метод Check является рекурсивным, он определяет логическую правильность строки. Метод ExecuteCode исполняет текущий шаблон. Для описанных классов можно составить диаграмму классов[3].
2.4 Функциональная схема, функциональное назначение программного продукта
В программном продукте разработаны два возможных варианта обработки информации с уникальными алгоритмами.
Если пользователь использует кодовые шаблоны ему сначала необходимо указать входные файлы, затем либо создать новый шаблон, либо выбрать уже существующий. Далее пользователь указывает директорию и имя выходного файла и запускает процесс конвертации. Во время этого процесса изначально происходит выделение участков кода в шаблоне, затем в каждом из участков выделяются лексемы, после этого определяется их логический смысл и исполняется шаблон. Если на каком-то из этих этапов возникли ошибки, то информация о них заносится в журнал ошибок. После исполнения всех шаблонов пользователь может использовать выходной файл.
Если использовать шаблоны, созданные при помощи конструктора, то пользователю необходимо указать базу данных, которую требуется конвертировать, затем указать директорию выходного файла, создать шаблон и запустить процесс конвертации. Сама конвертация состоит из двух частей: создание таблицы истинности на основе шаблона и исполнение конвертации согласно таблице истинности. Затем выходной файл может использоваться пользователем по назначению.
2.5 Выводы
Во второй главе выпускной квалификационной работы были выбраны средства разработки, а именно Microsoft Visual Studio 2008, были описаны основные методы реализации программного продукта, а так же описана его структура. Так же была описана функциональная схема программного продукта.
Основными пунктами рассмотрения во второй главе стали:
— выбор методов и средств для реализации, его обоснование;
— описание применяемых алгоритмов;
— структура, архитектура программного продукта;
— функциональная схема, функциональное назначение программного продукта.
3. РЕАЛИЗАЦИЯ И ТЕСТИРОВАНИЕ ПРОГРАММНОГО ПРОДУКТА
3.1 Описание реализации
Одной из сложностей реализации данного программного продукта является написание алгоритма распознавателя. Весь алгоритм описывается методами: Search, Analize, Check, ExecuteCode.
Метод Search считывает шаблон и находит фрагменты кода, выделенные символами «*» с обеих сторон, и записывает их в массив.
public void Search ()
{ char c;
string s = «» ;
bool sign = false;
while (!sr.EndOfStream)
{
c = Convert. ToChar (sr.Read ());
if ((c ≠ '*') && (sign == true))
{ s += c. ToString (); }
if ((c == '*') && (sign == false))
{ sign = true;
s = «» ; }
else
if ((c == '*') && (sign == true))
{ if (s ≠ «»)
{ sign = false;
masCode[masCodeLength] = s;
masCodeLength++; }
else
s += c. ToString (); }}
mycode = new MyCode[masCodeLength]; }
Метод Analize разбивает строку кода на отдельные лексемы и определяет состояние для каждой из них, в случае если используются символы или слова, не предусмотренные языком, или некорректные названия переменных — в журнал ошибок добавляется соответствующее сообщение об ошибке. Полный список используемых лексем представлен в таблице 2.1.
public void Analize()
{ string[] masIdent = new string[1024];
int masIdentLength = 0;
string s = «» ;
char c;
bool sign = true;
for (int a = 0; a < masCodeLength; a++)
{ correct = false;
masIdentLength = 0;
masCode[a] = masCode[a]. Trim ();
masCode[a] = masCode[a]. ToLower ();
s = «» ;
for (int b = 0; b < masCode[a]. Length; b++)
{ c = masCode[a][b];
if (c ≠ ' ')
if (c == '.')
{ if (s ≠ «»)
{ masIdent[masIdentLength] = s;
masIdentLength++; }
masIdent[masIdentLength] = «.» ;
masIdentLength++;
s = «» ; }
…
if ((c == ' ') && (s ≠ «»))
{ masIdent[masIdentLength] = s;
masIdentLength++;
s = «» ; } }
if (s ≠ «»)
{ masIdent[masIdentLength] = s;
masIdentLength++; }
mycode[a] = new MyCode (««, null);
for (int z = 0; z < masIdentLength; z++)
mycode[a]. code += masIdent[z] + ««;
masSost = new int[masIdentLength];
В предыдущей части метода все найденные лексемы были записаны в массив masIdent, далее инициализируется цикл, в котором для всех найденных лексем определяется состояние и записывается в массив masSost.
for (int b = 0; b < masIdentLength; b++)
{ int Value;
if (masIdent[b] == «для»)
masSost[b] = 2;
else if (masIdent[b] == «до»)
masSost[b] = 3;
else if (masIdent[b] == «столбец»)
masSost[b] = 4;
else if (masIdent[b] == «строка»)
masSost[b] = 5;
else
…
else
if (Char.IsLetter (masIdent[b][0]))
{ bool f = true;
for (int d = 1; d < masIdent[b]. Length; d++)
if (!Char.IsLetterOrDigit (masIdent[b][d]))
f = false;
if (f == true) masSost[b] = 1; else
Добавление записи об ошибке в журнал ошибок, в случае, если, найденного идентификатора, не существует.
{ lv.Items.Add (thisTemplate, thisTemplate);
lv.Items[lv.Items.Count — 1]. SubItems. Add (mycode[a].code);
lv.Items[lv.Items.Count — 1]. SubItems. Add («Неопознанный идентификатор » + masIdent[b]); }} else
{ lv.Items.Add (thisTemplate, thisTemplate);
lv.Items[lv.Items.Count — 1]. SubItems. Add (mycode[a].code);
lv.Items[lv.Items.Count — 1]. SubItems. Add («Неопознанный идентификатор » + masIdent[b]);}}
mycode[a] = new MyCode(mycode[a]. code, masSost);
Check(0, masSost[0], a); }
Метод Check основан на работе нисходящего распознавателя с возвратом: определяется текущее состояние, если оно возможно, то осуществляется переход в следующее. Если невозможно, то состояние переключается в альтернативное, если такого нет, то в журнал ошибок добавляется сообщение об ошибке.
public void Check (int a, int s, int indc)
{ if (masSost[a] == s)
{ if ((s == 1) && (a == 0))
{ if (a == masSost. Length — 1)
correct = true; } else
if ((s == 2) && (a == 0)) s = 1; else
if (((s == 4) || (s == 5)) && (a == 0)) s = 8; else
if ((s == 1) && (a == 1)) s = 9; else
if ((s == 8) && (a == 1)) s = 6; else
if ((s == 10) && (a == 1)) s = 1; else
if ((s == 9) && (a == 2)) s = 12; else
if ((s == 6) && (a == 2))
{ if (a == masSost. Length — 1)
correct = true; } else
if (((s == 1) || (s == 12)) && (a == 2)) s = 11; else
if ((s == 12) && (a == 3)) s = 3; else
if ((s == 11) && (a == 3)) s = 8; else
if ((s == 3) && (a == 4)) s = 12; else
if ((s == 8) && (a == 4))
{ if (masSost[0] == 4)
s = 7;
…
if ((s == 6) && (a == 7))
{ if (a == masSost. Length — 1)
correct = true; }
else
if (((s == 12) || (s == 1)) && (a == 7))
s = 11;
else
if ((s == 11) && (a == 8))
{ if (a == masSost. Length — 1)
correct = true; }
В случае если массив входных состояний прошел проверку распознавателем и все состояния совпали, переменной correct присваивается значение true, а в случае, если где-нибудь нашлось несовпадение, то осуществляется возврат и проверяется для альтернативного состояния.
if (correct == false)
{ a++;
Check (a, s, indc); } }
else
if ((s == 8) && (a == 1))
{ s = 10;
Check (a, s, indc); }
else
if ((s == 1) && (a == 2))
{ s = 12;
Check (a, s, indc);}
else
…
else
if ((s == 1) && (a == 7))
{ s = 12;
Check (a, s, indc); }
Else
Если осуществляемый переход не был распознан, то, обрабатываемая строка кода, считается логически неверной и добавляется соответствующая запись об ошибке в журнал ошибок.
if (correct == false)
{
lv.Items.Add (thisTemplate, thisTemplate);
lv.Items[lv.Items.Count — 1]. SubItems. Add (masCode[indc]);
lv.Items[lv.Items.Count — 1]. SubItems. Add («Нарушен логический смысл строки»);
mycode[indc]. correct = false;
} }
Метод ExecuteCode записывает содержимое шаблона в выходной файл, исполняя программные строки. Если встречается цикл, то создается временный файл, в который записывается содержимое цикла и пока цикл не завершится, исполняется содержимое этого файла. Это необходимо для выполнения вложенных циклов.
public void ExecuteCode(int NCode, bool cikcle, StreamReader sr, StreamWriter sw, int tempF)
{
char c;
while (!sr.EndOfStream)
{
c = Convert.ToChar(sr.Read());
Алгоритм считывает по символу входной файл, в случае если встречается закрывающаяся фигурная скобка, означающая конец цикла, и переменная cikcle равна true, то это означает, что метод был вложенным и завершает его.
if ((c == '}') && (cikcle == true))
{
break;
}
Если, считанный символ, не был «*», то это означает, что символ не относится к кодовым командам и его необходимо просто вывести.
if (c ≠ '*')
{
sw.Write (c);
}
Если, считанный символ, был «*», алгоритм считывает следующий символ, если и он «*», то это означает что пользователь, хотел вывести этот символ в выходной файл.
if (c == '*')
{ c = Convert. ToChar (sr.Read ());
if (c == '*')
sw.Write (c);
else
Если, следующий символ не был «*», то это означает, что все последующие символы до «*» относятся к кодовым командам.
if (mycode[NCode]. correct == true)
if (mycode[NCode]. masSost[0] == 1)
{ bool creat = false;
for (int a = 0; a < masPeremCount; a++)
{ if (masPerem[a, 0] == mycode[NCode]. code)
{ creat = true;
sw.Write (masPerem[a, 1]);
NCode++;
while (sr.Read () ≠ '*')
{ }break; } }
Если, в коде, пользователь пытается вывести переменную, которая до этого не была объявлена, то запись об ошибке заносится в журнал ошибок и дальний код уже не исполняется.
if (creat == false)
{ if (mycode[NCode]. code ≠ «»)
{ lv.Items.Add (thisTemplate, thisTemplate);
lv.Items[lv.Items.Count — 1]. SubItems. Add (mycode[NCode].code);
lv.Items[lv.Items.Count — 1]. SubItems. Add («Попытка вывести несуществующую переменную»);
mycode[NCode]. code = «» ; }
NCode++;
while (sr.Read () ≠ '*')
{ } } }
else
if (mycode[NCode]. masSost[0] == 4)
{ if (mycode[NCode]. masSost[2] == 6)
{ NCode++;
sw.Write (dt.Columns.Count.ToString ());
while (sr.Read () ≠ '*')
{ } }
else
if (mycode[NCode]. masSost[2] == 12)
{
if (Convert.ToInt32(mycode[NCode]. masValue[2]) < dt.Columns.Count)
{ if (mycode[NCode]. masSost[5] == 7)
sw.Write (dt.Columns[Convert.ToInt32(mycode[NCode]. masValue[2])].DataType.Name);
else
sw.Write (dt.Columns[Convert.ToInt32(mycode[NCode].masValue[2])].ColumnName);}
Если, пользователь пытается обратиться к столбцу или строке, которых не существует, то соответствующая запись об ошибке добавляется в журнал ошибок.
else
{
lv.Items.Add (thisTemplate, thisTemplate);
lv.Items[lv.Items.Count — 1]. SubItems. Add (mycode[NCode].code);
lv.Items[lv.Items.Count — 1]. SubItems. Add («Индекс выходит за рамки массива»);
mycode[NCode]. code = «» ; }
NCode++;
while (sr.Read () ≠ '*')
{ }}
else
{ bool creat = false;
for (int a = 0; a < masPeremCount; a++)
if (masPerem[a, 0] == mycode[NCode]. masValue[2])
{ creat = true;
if (Convert.ToInt32(masPerem[a, 1]) < dt.Columns.Count)
{ if (mycode[NCode]. masSost[5] == 13)
sw.Write (dt.Columns[Convert.ToInt32(masPerem[a, 1])]. ColumnName);
else
sw.Write (dt.Columns[Convert.ToInt32(masPerem[a, 1])]. DataType.Name);
} else {
lv.Items.Add (thisTemplate, thisTemplate);
lv.Items[lv.Items.Count — 1]. SubItems. Add (mycode[NCode].code);
lv.Items[lv.Items.Count — 1]. SubItems. Add («Индекс выходит за рамки массива»);
mycode[NCode]. code = «» ; }
NCode++;
while (sr.Read () ≠ '*')
{ } }
if (creat == false) {
В случае если пользователь указывает несуществующую переменную в качестве индекса столбца или строки, запись о соответствующей ошибке добавляется в журнал ошибок.
lv.Items.Add (thisTemplate, thisTemplate);
lv.Items[lv.Items.Count — 1]. SubItems. Add (mycode[NCode].code);
lv.Items[lv.Items.Count — 1]. SubItems. Add («Попытка обратиться к несуществующей переменной»);
NCode++;
while (sr.Read () ≠ '*')
{ } } }}
else
if (mycode[NCode]. masSost[0] == 5)
{ int n1 = 0, n2 = 0, nn = 0;
if (mycode[NCode]. masSost[2] == 6)
{ sw.Write (dt.Rows.Count.ToString ());
NCode++;
while (sr.Read () ≠ '*')
{ } }
else
{ if (mycode[NCode]. masSost[2] == 12)
{ { n1 = Convert. ToInt32(mycode[NCode]. masValue[2]);
nn++; }
if (mycode[NCode]. masSost[7] == 12)
{ n2 = Convert. ToInt32(mycode[NCode]. masValue[7]);
nn++; }
else
{ bool creat = false;
for (int a = 0; a < masPeremCount; a++)
if (masPerem[a, 0] == mycode[NCode]. masValue[7])
{ creat = true;
n2 = Convert. ToInt32(masPerem[a, 1]);
nn++; }
…
В случае если переменная использовалась в качестве индекса столбца или строки и ее значение превышает число столбцов или строк таблицы соответственно, то запись об этой ошибке добавляется в журнал ошибок.
Else { if (n1 >= dt.Rows.Count)
{ if (mycode[NCode]. code ≠ «»)
{lv.Items.Add (thisTemplate, thisTemplate);
lv.Items[lv.Items.Count — 1]. SubItems. Add (mycode[NCode].code);
lv.Items[lv.Items.Count — 1]. SubItems. Add («Индекс » + n1 + « выходит за рамки массива»);}}
if (n2 >= dt.Columns.Count)
{ if (mycode[NCode]. code ≠ «»)
{ lv.Items.Add (thisTemplate, thisTemplate);
lv.Items[lv.Items.Count — 1]. SubItems. Add (mycode[NCode].code);
lv.Items[lv.Items.Count — 1]. SubItems. Add («Индекс » + n2 + « выходит за рамки массива»); }}
mycode[NCode]. code = «» ; }
NCode++;
while ((sr.Read () ≠ '*') && (!sr.EndOfStream))
{ } } } } else
if (mycode[NCode]. masSost[0] == 2)
{ int k, nk;
masPerem[masPeremCount, 0] = mycode[NCode]. masValue[1];
masPerem[masPeremCount, 1] = mycode[NCode]. masValue[3];
nk = masPeremCount;
masPeremCount++;
if (mycode[NCode]. masSost[5] == 12)
k = Convert. ToInt32(mycode[NCode]. masValue[5]); else
if (mycode[NCode]. masSost[5] == 4) k = dt.Columns.Count;
else k = dt.Rows.Count;
while (sr.Read () ≠ '*') { }
В случае если пользователь объявил цикл и после этого не указал его начало, не поставив «{», это расценивается как ошибка и запись об этом добавляется в журнал ошибок.
c = Convert. ToChar (sr.Read ());
if (c == 'r')
c = Convert. ToChar (sr.Read ());
if (c == 'n')
c = Convert. ToChar (sr.Read ());
if (c ≠ '{')
{ lv.Items.Add (thisTemplate, thisTemplate);
lv.Items[lv.Items.Count — 1]. SubItems. Add (mycode[NCode].code);
lv.Items[lv.Items.Count — 1]. SubItems. Add («Не указано начало цикла»);
mycode[NCode]. correct = false;
NCode++; } else {
Если начало цикла указано корректно, то переменная, отвечающая за глубину вложенности циклов, увеличивается на единицу, содержимое цикла, до знака «}», записывается во временный файл, создается дубликат массивов содержащих значения переменных и данный рекурсивный метод запускается уже для этого временного файла.
tempF++;
Directory.CreateDirectory («Temp»);
StreamWriter sw1=new StreamWriter («Temp\Temp» +tempF.ToString ()+" .txt", false, Encoding. UTF8);
c = Convert. ToChar (sr.Read ());
if (c == 'r')
{ sr.Read ();
c = Convert. ToChar (sr.Read ()); }
int cickleCount = 0;
while (c ≠ '}')
{ if (c == '{')
cickleCount++;
sw1.Write (c);
if (sr.EndOfStream)
break;
c = Convert. ToChar (sr.Read ());
if ((c == '}') && (cickleCount ≠ 0))
{ cickleCount—;
sw1.Write (c);
c = Convert. ToChar (sr.Read ()); } }
sw1.Close ();
StreamReader sr1 = new StreamReader («Temp\Temp» + tempF. ToString () + «.txt», Encoding. UTF8);
int CickleCode = 0;
string s1 = «» ;
bool sign2 = false;
while (!sr1.EndOfStream)
{ c = Convert. ToChar (sr1.Read ());
if ((c ≠ '*') && (sign2 == true))
{ s1 += c. ToString (); }
if ((c == '*') && (sign2 == false))
{ sign2 = true;
s1 = «»; }
else
if ((c == '*') && (sign2 == true))
{ if (s1 ≠ «»)
{ sign2 = false;
CickleCode++; }
else s1 += c. ToString (); } }
sr1.Close ();
for (int a = Convert. ToInt32(mycode[NCode]. masValue[3]); a < k; a++)
{ masPerem[nk, 1] = a. ToString ();
ExecuteCode (NCode + 1, true, new StreamReader («Temp\Temp» + tempF. ToString () + «.txt», Encoding. UTF8), sw, tempF);}