11.05 Оператор switch и разбор ДКА

<!> Это проект занятия, которого нет в планах <!>

Форма для сдачи

Switch

Когда в алгоритме требуется цепочка операторов вида «если целое число равно A — сделать то-то; если равно B — сделать то-то, …», лучше применять оператор switch:

Enum

Константы в switch() — целочисленные (в виде числе или char-литералов). Во избежание «магических чисел» можно использовать #define. Но если есть необходимость превратить последовательность числе в идентификаторы, надо пользоваться enum.

Детерминированные конечные автоматы

( https://madebyevan.com/fsm/ https://fsmd.moritzliedtke.com/ TODO захостить + доделать autocrop?) )

Построение простого парсера:

   1 #include <stdio.h>
   2 #include <stdlib.h>
   3 
   4 enum { BASE, Y, Ye, Yes, N, No };
   5 
   6 int ynparser(char *str) {
   7         int state = BASE;
   8         for(char *c=str; *c; c++)
   9                 switch(state) {
  10                         case BASE:
  11                                 switch(*c) {
  12                                         case 'Y': state=Y; break;
  13                                         case 'N': state=N; break;
  14                                         default : return -1;
  15                                 }
  16                                 break;
  17                         case Y:
  18                                 switch(*c) {
  19                                         case 'e': state=Ye; break;
  20                                         default : return -1;
  21                                 }
  22                                 break;
  23                         case Ye:
  24                                 switch(*c) {
  25                                         case 's': state=Yes; break;
  26                                         default : return -1;
  27                                 }
  28                                 break;
  29                         case Yes:
  30                                 return 1;
  31                         case N:
  32                                 switch(*c) {
  33                                         case 'o': state=No; break;
  34                                         default : return -1;
  35                                 }
  36                                 break;
  37                         case No:
  38                                 return 0;
  39                         default: /* Не должно случиться! */
  40                                 abort();
  41                 }
  42         return -1;
  43 }
  44 
  45 #define SZ 12
  46 int main(void) {
  47         char yn[SZ];
  48         fgets(yn, SZ, stdin);
  49         printf("%d: %s", ynparser(yn), yn);
  50         return 0;
  51 }

Транслятор

В момент разбора строки можно выполнять разнообразные действия.

Д/З

  1. <!> «Большая» задача <!> В цикле вводить строки, предположительно содержащие вещественное число в любом из двух форматов (экспоненциальном и с фиксированной точкой). Конец ввода — EOF. Написать функцию int checkfloat(char *str, float *num), распознающую число. Функция записывает введённое число в *num и возвращает 0 в случае, если строка распознана. В противном случае возвращается -1, а *num не меняется. Буква 'e' может быть как большой, так и маленькой; в начале числа и порядка может стоять '+', '-' и ничего. Программа выводит введённое число в формате "%f", если ввод корректен, и NaN, если нет. Переводы строки игнорируются, пробелы — нет.

LecturesCMC/AL/Prac/19_Parsing (последним исправлял пользователь hbd 2026-11-05 16:37:12)