跳轉

2013-10-20 78 views
1

我有下面的代碼來定義我的FSM狀態:跳轉

enum states 
{ 
    START,    // Send request to remote IP or wait for a request (WAIT_CONN_REQ) 
    WAIT_RESP,   // Chat request sent to remote IP. Waiting for a response from the target machine 
    SEND_CONN_RESP,  // Chat request received from remote IP. ACCEPT or REJECT 
    ACCEPTED   // Both parties agreed to exchange datagrams. Begin application data (MESSAGES) exchange 
}; 
typedef enum states states; 
states state; 

我的思維過程是這樣的:我的聊天程序將具有上述四種狀態。整潔地做這件事的最好方法是什麼?當然使用switch語句。那我該怎麼做呢?像這樣的:(代碼簡化&與printf功能」

int main(int argc, char *argv[]) 
{ 
    state = START; 
    switch (state) 
    { 
     case START: 
      printf("Simple Chat Client - START state\n"); 
      if (argv[1] != NULL) 
      { 
       SEND_CONN_REQ(); 
       } else { 
       WAIT_CONN_REQ(); 
      } 
      break; 
     case WAIT_RESP: 
      printf("WAIT_RESP STATE!"); 
      break; 
     case SEND_CONN_RESP: 
      printf("SEND_CONN_RESP state!"); 
      break; 
     case ACCEPTED: 
      printf("ACCEPTED state!"); 
      break; 
    } 
} 

但這並不做我想我需要在條件滿足就跳轉到另一種情況下,像這樣什麼代替:。

if (argv[1] != NULL) 
        { 
         SEND_CONN_REQ(); 
         goto case WAIT_RESP;   
         } else { 
         WAIT_CONN_REQ(); 
        } 
        break; 
       case WAIT_RESP: 
        printf("WAIT_RESP STATE!"); 
        break; 

我的邏輯告訴我,要做到這一點的辦法是改變state變量,假定整個switch將與新的變量再次執行。但是,什麼情況是,我必須要麼使用break和退出switch,或者不使用它並讓程序執行下一個case

所以我看了其他選項,如do報表和continue。但在我看來,使用case似乎是與FSM一起使用的方式。

我將不勝感激關於如何正確執行此操作的任何幫助。是一個switch聲明甚至是最好的方式?

+0

您的switch語句是靜音的。任何請不要使用goto –

+0

@EdHeal嘿! - 我知道'goto'不好,永遠不要使用,我只把它放在那裏,以便傳達我的意思。但是,謝謝你的建議!你能解釋一下「靜音」的含義嗎? – user2899235

+0

您設置了'state',然後在'switch'語句中使用它。即如果對於它將去的路線是否是一個放棄的結論。它也在'main'功能 –

回答

2

正常的方式來編寫一個狀態機一樣,使用循環和開關:

state = START; 
while (state != STOP) 
{ 
    switch (state) 
    { 
     case START: 
      printf("Simple Chat Client - START state\n"); 
      if (argv[1] != NULL) 
      { 
       SEND_CONN_REQ(); 
      } else { 
       WAIT_CONN_REQ(); 
      } 
      break; 
     case WAIT_RESP: 
      printf("WAIT_RESP STATE!"); 
      break; 
     case SEND_CONN_RESP: 
      printf("SEND_CONN_RESP state!"); 
      break; 
     case ACCEPTED: 
      printf("ACCEPTED state!"); 
      break; 
    } 
} 

每個動作可以選擇設置新的狀態,以便下一次迭代將做適當的行動。如果您想及時查看輸出,請不要忘記在printf()語句的末尾輸出換行符。在Windows上可能無關緊要;它在其他平臺上運行。

+0

@JonathanLeffer - 你好 - 它在主函數中,也就是在開關被設置之前 –

+1

'main()'中的'state'被設置爲'START'這個問題,但之後從未改變。我沒有在我的大綱代碼中寫入正確的修改;我不知道他們是什麼。但是任何時候代碼繞過循環,都應該將'state'設置爲正確的下一個值,以便在下一次迭代中正確的活動繼續進行。代碼完成後,它將'state'設置爲(假設)STOP狀態,以便循環終止。 –

+0

@JonathanLeffler你好 - 謝謝你!這看起來非常整齊。我知道你說過這是編碼狀態機的正常方式,但是你能解釋爲什麼這個代碼比發佈的意外情況更好嗎? – user2899235

0

如果您總是隻想執行正確的狀態,您可以刪除break聲明。我會在/* fall through */這樣的地方發表評論,這樣很明顯,它是故意遺漏的人跟隨,以及你的未來,忘記自我。我個人不喜歡這種方法。

爲什麼不改變state變量,然後在switch語句正上方執行goto?像這樣也許:

switchStart: 
    switch (state) 
    { 
     case START: 
      printf("Simple Chat Client - START state\n"); 
      if (argv[1] != NULL) 
      { 
       SEND_CONN_REQ(); 
       state = STATE_HERE; // change your state 
       goto switchStart; // jump to the top of the switch 
       } else { 
       WAIT_CONN_REQ(); 
      } 
      break; 
     case WAIT_RESP: 
      printf("WAIT_RESP STATE!"); 
      break; 
     case SEND_CONN_RESP: 
      printf("SEND_CONN_RESP state!"); 
      break; 
     case ACCEPTED: 
      printf("ACCEPTED state!"); 
      break; 
    } 
+0

嘿!這完美的作品!謝謝!什麼是「陷阱」?或者有一個呢?這看起來很簡單,完全符合我的需要。 – user2899235

+0

「疑難雜症」是人們通常喜歡遠離「goto」語句,因爲它有時會使讀代碼和調試變得困難。我也不特別喜歡它們,但是既然你提出了一個轉向,我認爲你並不反對這個想法。 :-D。感謝您接受答案。如果你認爲寫得很好,請儘快寫好。 –

+0

那麼,當你這樣說...對於初學者,我不認爲使用「goto」是一個好習慣。我把它放在那裏,這樣人們就能理解我想達到的目標 - 或者說我可以更好地解釋它。我不認爲我會使用這個解決方案,即使它看起來是最簡單的方法。但謝謝你的回答,非常感謝! (我還無法登錄帖子) – user2899235