реализация конечного автомата с помощью ключевого слова “урожая”

Самый простой способ запомнить это посмотреть на std::numeric_limits< int >::max()

Например ( из MSDN ),

// numeric_limits_max.cpp

#include 
#include 

using namespace std;

int main() {
   cout << "The maximum value for type float is:  "
        << numeric_limits::max( )
        << endl;
   cout << "The maximum value for type double is:  "
        << numeric_limits::max( )
        << endl;
   cout << "The maximum value for type int is:  "
        << numeric_limits::max( )
        << endl;
   cout << "The maximum value for type short int is:  "
        << numeric_limits::max( )
        << endl;
}

25
задан Matt Warren 28 July 2009 в 15:19
поделиться

4 ответа

Это возможно, но это плохая идея. Блоки итераторов были созданы, чтобы помочь вам писать собственные итераторы для коллекций, а не для решения универсальной проблемы реализации конечных автоматов.

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

(И, кстати, я дважды ошибся, когда прочитал ваше имя. Одного из разработчиков C # также зовут Мэтт Уоррен!)

49
ответ дан 28 November 2019 в 18:19
поделиться

Да, это абсолютно возможно и легко сделать. Вы можете наслаждаться использованием конструкций потока управления ( для , foreach , while , ... goto (используя goto ] особенно подходит для этого сценария;))) вместе с yield s для его создания.

IEnumerator<State> StateMachine
             (Func<int> currentInput /* gets current input from IO port */, 
              Func<int> currentOutput) {
    for (;;)  {
       if ((currentInput() & 1) == 0) 
           yield return new State("Ready"); 
       else {
           if (...) {
               yield return new State("Expecting more data");
               SendOutput(currentOutput());
               while ((currentInput() & 2) != 0) // while device busy
                    yield return new State("Busy");
           else if (...) { ... } 
       }
    }
}

// consumer:
int data;
var fsm = StateMachine(ReadFromIOPort, () => data);
// ...
while (fsm.Current != "Expecting more data")
    fsm.MoveNext();
data = 100;
fsm.MoveNext();
7
ответ дан 28 November 2019 в 18:19
поделиться

Блоки итераторов действительно реализуют конечные автоматы, но хитрый бит получает следующий ввод. Как вы узнаете, куда двигаться дальше? Я предполагаю, что у вас могла бы быть какая-то общая переменная «текущего перехода», но это несколько неприятно.

Если вам не нужен какой-либо ввод (например, ваш конечный автомат просто циклически переключается между состояниями), тогда это просто, но это не интересный вид :)

Вы можете описать интересующий вас тип конечного автомата?

4
ответ дан 28 November 2019 в 18:19
поделиться

Хотя это не конечный автомат в классическом смысле, статья о Micro Threading на основе итераторов творчески использует yield для действий на основе состояний.

IEnumerable Patrol ()
{
    while (alive){
        if (CanSeeTarget ()) {
            yield return Attack ();
        } else if (InReloadStation){
            Signal signal = AnimateReload ();
            yield return signal;
        } else {
            MoveTowardsNextWayPoint ();
            yield return TimeSpan.FromSeconds (1);
        };
    }
    yield break;
}
4
ответ дан 28 November 2019 в 18:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: