Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lecture9a_FSM.doc
Скачиваний:
3
Добавлен:
19.11.2019
Размер:
5.49 Mб
Скачать

Example (пример)

Consider we need a program in C that reads a text from standard input stream, line by line, and prints the first word of each line. It is clear we need first to read and skip the leading spaces, if any, then read characters of the first word and print them until the word ends, and then read and skip all the remaining characters until the end-of-line character is encountered. Upon the end of line character (regardless of the stage) we restart the algorithm from the beginning, and in case the end of file condition (regardless of the stage) we terminate the program.

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

Traditional (imperative) program (обычная императивная программа).

The program which solves the example task in traditional (imperative) style can look something like this (программа, которая выполняет описанную задачу в традиционном (императивном) стиле выглядит следующим образом):

#include <stdio.h>

int main()

{

int c;

do {

c = getchar();

while(c == ' ')

c = getchar();

while(c != EOF && c != ' ' && c != '\n') {

putchar(c);

c = getchar();

}

putchar('\n');

while(c != EOF && c != '\n')

c = getchar();

} while(c != EOF);

return 0;

}

Расшифровка операторов программы на языке с:

#include <stdio.h> //включение информации о стандартной библиотеке ввода/вывода;

main() //определение функции с именем main(), не получающей никаких аргументов;

{ - //функция main()заключается в фигурные скобки;

int c; // значения численных переменных целые;

while(c == ' ')//-оператор цикла;

c = getchar(); //- переменная c считывает очередной символ ввода;

putchar(c); //- печать содержимого целой переменной c;

while(c != EOF && c != ' ' && c != '\n') { //- пока С не равно «конец файла» «И» С не равно пробелу «И» С не равно «символу новой строки»

do while // - цикл;

!= // - не равно;

&& // - логический оператор «И»;

putchar('\n'); // - печать «символа новой строки»;

EOF // - целая константа – конец файла;

' ' // - пробел;

'\n' // - код символа новой строки, который в ASCII равен 10;

== // - оператор «равно»;

\n / / - символ новой строки;

return 0; // - инструкция реализует механизм возврата результата от вызываемой функции к вызывающей;

Automata-based style program (программа на основе модели конечного автомата)

The same task can be solved thinking in terms of finite state machines. Please note that line parsing has three stages: skipping the leading spaces, printing the word and skipping the trailing characters. Let's call them states before, inside and after. The program may now look like this:

Та же самая задача может быть решена за счет использования выражений, характерных для модели конечных автоматов. Обратите внимание на то, что строка анализа (разбора) имеет 3 этапа: пропуск ведущих отступов, печать слова и пропуск замыкающих символов. Назовем их как «состояния» before - до, inside – внутри и after – после. Программа теперь выглядит следующим образом:

#include <stdio.h>

int main()

{

enum states {

before, inside, after

} state;

int c;

state = before;

while((c = getchar()) != EOF) {

switch(state) {

case before:

if(c == '\n') {

putchar('\n');

} else

if(c != ' ') {

putchar(c);

state = inside;

}

break;

case inside:

switch(c) {

case ' ': state = after; break;

case '\n':

putchar('\n');

state = before;

break;

default: putchar(c);

}

break;

case after:

if(c == '\n') {

putchar('\n');

state = before;

}

}

}

return 0;

}

Расшифровка программы:

enum states \\ - спецификатор перечисления;

switch case default \\ - конструкция переключателя;

break \\ - инструкция, связанная с case;

if else \\ - конструкция разветвления;

Although the code now looks longer, it has at least one significant advantage: there's only one reading (that is, call to the getchar() function) instruction in the program. Besides that, there's only one while loop instead of the four the previous version had.

И хотя текст новой программы длиннее, она, по крайней мере, имеет одно важное преимущество: в ней только одна команда считывания информации (функция - getchar() function). Кроме того, имеется только один цикл while вместо 4 в предыдущей программе.

In this program, the body of the while loop is the automaton step, and the loop itself is the cycle of the automaton's work.

В этой программе, тело цикла while является этапом работы конечного автомата, и цикл сам по себе является циклом работы конечного автомата.

The program implements (models) the work of a finite state machine shown on the picture. The N denotes the end of line character, the S denotes spaces, and the A stands for all the other characters. The automaton follows exactly one arrow on each step depending on the current state and the encountered character. Some state switches are accompanied with printing the character; such arrows are marked with asterisks.

Эта программа вводит (модель) работы конечного автомата согласно приведенной схемы. N обозначает конец строки символов, S – объем пространства для отображения, и А – для всех других символов. Конечный автомат следует точно по стрелке на каждом этапе в зависимости от текущего состояния и встреченного символа. Некоторые переключатели состояний сопровождаются указаниями на печать символа; такие стрелки помечены с помощью «*».

It is not absolutely necessary to divide the code down to separate handlers for each unique state. Furthermore, in some cases the very notion of the state can be composed of several variables' values, so that it could be impossible to handle each possible state explicitly. In the discussed program it is possible to reduce the code length noticing that the actions taken in response to the end of line character are the same for all the possible states. The following program is equal to the previous one but is a bit shorter:

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

If you anticipate an event that causes signals, you can define a handler function and tell the operating system to run it when that particular type of signal arrives.

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

#include <stdio.h>

int main()

{

enum states {

before, inside, after

} state;

int c;

state = before;

while((c = getchar()) != EOF) {

if(c == '\n') {

putchar('\n');

state = before;

} else

switch(state) {

case before:

if(c != ' ') {

putchar(c);

state = inside;

}

break;

case inside:

if(c == ' ') {

state = after;

} else {

putchar(c);

}

break;

case after:

break;

}

}

return 0;

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]