Нотация Бекуса-Наура части do функции g
Случай |
Ch, FileIn |
FileOut |
Ch |
EOF |
1 |
<слово><пробелы><непробел> |
<слово> <пробел> |
<непробел> |
FALSE |
4 |
<слово> <пробелы> |
<слово> |
<пробел> |
TRUE |
6 |
<слово> <пробел> |
<слово> |
<пробел> |
TRUE |
7 |
<пробелы> <непробел> |
<пробел> |
<непробел> |
FALSE |
10 |
<пробелы> |
<пустая строка> |
<пробел> |
TRUE |
12 |
<пробел> |
<пустая строка> |
<пробел> |
TRUE |
Часть DO оператора WHILE в процедуре RemoveExtraBlanks содержит функцию g, описанную выше. BNF -таблица, описывающая g помогает в понимании итераций цикла. Оператор WHILE такой:
WHILE NOT EOF(FileIn)
DO
{Вычислить g}
Любой из шести образцов может возникнуть на входе и g произведет соответствующий образец на выходе, подготовившись к приему следующего образца, пока на входе не будет встречен конец файла.
Используя таблицу может бать записано BNF-описание файлов, обрабатываемых оператором WHILE. Как только встретится <непробел> в Ch и части FileIn, данный образец может повториться. Пусть <R> обозначает вовлеченную строку. Только случаи 1 и 4 вовлекаются, поскольку только они начинаются со <слова>, которое начинает <непробел>. (Случай 6 является менее общей версией случая 4). Таким образом, рекурсивное правило будет таким:
<R> ::= <слово> <пробелы> <R> (1)
| <слово> <пробелы> (4)
Случаи 7 и 10 могут быть применены только изначально, поскольку они требуют, чтобы в Ch находился пробел, и ни одного случая не приводит к этой ситуации – все они приводят к появлению пробела в Ch лишь в конце файла, при котором происходит прекращение оператора WHILE:
<Файл1> ::= <слово> <пробелы> <R> (1)
|<слово> <пробелы> (4)
|<пробелы> <R> (7)
|<пробелы> (10)
Случай 12 является менее общей версией случая 10.
Можно заметить что первые 2 альтернативы являются <R>, поэтому:
<Файл1> ::= <R> (1, 4)
|<пробелы> <R> (7)
|<пробелы> (10)
Выходной файл, создаваемый программой может быть описан в форме BNF для <Файл2> подобным образом. Случаи 4 и 6 являются дубликатами, как 10 и 12. Повторение может возникнуть в случаях 1 и 4, как и раньше, приводя нас к строкам <S>:
<S> ::= <слово> <пробел> <S> (1)
| <слово> (4)
Остальные случаи могут возникнуть только изначально:
<Файл2> ::= <слово> <пробел> <S> (1)
| <слово> (4)
| <пробел> S (7)
| <пустая строка> (10)
Путем замены первых двух альтернатив на S получаем:
<Файл2> ::= <S> (1, 4)
| <пробел> S (7)
| <пустая строка> (10)
Очевидно из таблицы для функции g, что <слова> из <Файла1> перемещаются в <Файл2> в том же порядке, в котором появляются. Таким образом, функция f цикла WHILE конвертирует <Файл1> в <Файл2>, приготовляя порядок <слов> в том случае, если EOF(FileIn) равен FALSE, и идентична в противном случае, т.е:
f = ((NOT(EOF(FileIn)) AND FIleIn.3=R AND FIleOuot.3=W)
FileIn, FileOut := <FileIn.1 & FileIn.2, ††. R>,
<FileOut.1 & convert(FileIn.2), ††, W>) |
(EOF(FileIn)) AND FileIn.3 = R )
где convert принимает в качестве аргумента строку в виде <Файл1> и производит строку в виде <Файл2>, причем слова и их порядок не изменяются.
Формальное доказательство того, что функция f является функцией выполняемой оператором WHILE, дано не будет, но три условия правила проверки WHILE будут обсуждены неформально.
domain(f) = domain( WHILE... )
(EOF(FileIn) f) = (EOF(FileIn) )
f = IF NOT EOF(FileIn) THEN {вычислить g} ◦ f
Задание 5. Покажите справедливость правил 1-3 самостоятельно
(30 баллов)
На этом анализ процедуры RemoveExtraBlanks закончен. Решение не было полностью формальным, однако мы использовали программное исчисление для достижения полного понимания каждой программной части и эффекта их комбинации. В программном анализе, анализ может быть строгим в большей или меньшей степени. Нашей целью является понять, с соответствующей уверенность эффект программы. Иногда анализ требует очень строгого подхода, но иногда неформальный анализ тоже является достаточным. Например, если часть программы трудна для понимания или является жизненно критической (например, программа управления пилотируемым космическим кораблем), тогда подробный анализ может потребоваться для того, чтобы быть уверенными в корректности программы. С другой стороны, если часть программы легка для понимания, то затраты на проведение строгого анализа могут себя не оправдать.
Программный анализ заставляет использовать множество различных формализмов. Этот пример использует строковую нотацию и нотацию Бекуса-Наура, а также условные присваивания и трассировочные таблицы. Формализмы были придуманы для того, чтобы сделать задачу сложного анализа проще. Новые формализмы могут быть придуманы для решения других задач.
Задание 6. Предположим, что на входе RemoveExtraBlanks дан файл, который состоит из более чем одной строки. Объясните подробно, что произойдет на границах строк.
(10 баллов)
Задание 7. Измените проект RemoveExtraBlanks таким образом, чтобы он сохранял линейную структуру текста, продолжая, тем не менее, удалять лишние пробелы на каждой строке. Начните с BNF-описания измененной проблемы, используя <маркер конца строки> в качестве маркера конца строки. Прикиньте, какая часть анализа потребует изменений, чтобы охватить измененную программу.
(15 баллов)
Задание 8. Модифицируйте проект RemoveExtraBlanks (для получения процедуры RemoveAllWords) так, чтобы действие программы было реверсированным: программа должна записывать только все пробелы и пропускать слова.
(15 баллов)
Задание 9. Обозначив входную строку буквой S, выходную строку программы RemoveExtraBlanks обозначив W, а выходную строку программы RemoveAllWords буквой B, объясните, почему:
Длина (S) ≠ длина(W) + длина (B)
(15 баллов)
Задание 10. Докажите, что реализацией для {вставить пробел, если это не последнее слово} также может являться:
IF Ch <> ‘ ‘
THEN
WRITE(FileOut, ‘ ‘)
(15 баллов)
Задание 11. Текстовый файл содержит трехзначные числа, разделенные пробелами (одним или несколькими). Числам могут предшествовать нулевые символы (несколько, либо ни одного). Цель: переформатировать файл в файл с разделителями в один пробел, с убиранием ведущих нулей (за исключением числа ноль, который должен выглядеть так: 0).
a) Опишите проблемы с использованием BNF
b) разделите множество входных строк на группы и создайте наборы тестовых данных для каждой группы.
c) Напишите проект программы, решающей данную задачу.
(50 баллов)
Задание 12. Даны 2 строки. Первая строка состоит из пробелов. Вторая – из слов и пробелов. Предположив, что длина первой строки определяет ее ширину, выведите каждое слово из второй строки в отцентрированном (относительно ширины первого слова) виде.
(20 баллов)
