2010-04-12 96 views
1

我已經編寫了一個程序,以從用戶獲取字符串輸入並將其解析爲令牌並根據輸入移動機器人。我的問題是試圖發佈多個命令。代碼如下所示:爲什麼我的while循環需要新的輸入(C++)

void Navigator::manualDrive() 
{ 

    const int bufSize = 42; 
    char uinput[bufSize]; 
    char delim[] = " "; 
    char *token; 
    while(true) 
    { 

     Navigator::parseInstruction(uinput); 
    } 
} 
/* parseInstruction(char *c) -- parses cstring instructions received 
* and moves robot accordingly 
*/ 


void Navigator::parseInstruction(char * c) 
{ 

    const int bufSize = 42; 
    char uinput[bufSize]; 
    char delim[] = " "; 
    char *token; 


    cout << "Enter your directions below: \n"; 
    cin.ignore(); 
    cin.getline (uinput, bufSize); 


    token=strtok(uinput, delim); 
    if(strcmp("forward", token) == 0) 
    { 
     int inches; 
     token = strtok(NULL, delim); 
     inches = atoi (token); 
     Navigator::travel(inches); 
    } 
    if(strcmp("back",token) == 0) 
    { 
     int inches; 
     token = strtok(NULL, delim); 
     inches = atoi (token); 
     double value = fabs(0.0735 * fabs(inches) - 0.0550); 
     myRobot.backward(1/*speed*/, value/*time*/); 
    } 
    if(strcmp("turn",token) == 0) 
    { 
     int degrees; 
     token = strtok(NULL, delim); 
     if(strcmp("left",token) == 0) 
     { 
      token = strtok(uinput, delim); 
      degrees = atoi (token); 
      double value = fabs(0.0041 * degrees - 0.0523); 
      myRobot.turnLeft(1/*speed*/, value/*time*/); 
     } 
    } 
    if(strcmp("turn",token) == 0) 
    { 
     int degrees; 
     token = strtok(NULL, delim); 
     if(strcmp("right",token) == 0) 
     { 
      token = strtok(uinput, delim); 
      degrees = atoi (token); 
      double value = fabs(0.0041 * degrees - 0.0523); 
      myRobot.turnRight(1/*speed*/, value/*time*/); 
     } 
    } 
    if(strcmp("stop",token) == 0) 
    { 
     myRobot.motors(0,0); 
    } 
} 

在函數manualDrive中,我有一個while循環無限地調用函數parseInstruction。程序輸出「在下面輸入您的指示:」當我給出程序指令時,它會執行它們,然後再次輸出「在下面輸入您的指示:」,當我再次輸入我的指示時,它不會執行它們並輸出「輸入您的指示下面:「代替。我相信這是一個非常簡單的修復,我只是對C++很陌生。所以,如果你可以請幫助我,並告訴我爲什麼該計劃只採取第一組方向。謝謝

+0

從問題格式的角度來看,我認爲你有一些格式問題。確保在所有代碼行之前加上四個空格。 – 2010-04-12 22:39:52

+0

對不起,我試圖修復它。 – Van 2010-04-12 22:49:15

+0

感謝您解決我的縮進問題 – Van 2010-04-12 23:02:51

回答

1

這聽起來像是當你的cin命令讀入上一個輸入的新行字符時發生的常見問題。我看到你有cin.ignore(),這通常是解決這個問題的方法,但它仍然在發生。

嘗試移動你的忽視,則對getline()命令

+0

我在getline()之後移動了ignore(),並且機器人沒有移動,並且出現了分段錯誤。 – Van 2010-04-12 22:58:53

1

後,你不應該在這裏需要cin.ignore()線。 cin.getline應已經提取並丟棄分隔符。我懷疑它扔掉了你的命令的第一個字符。你可以通過改變你的if語句到別的假設分析,並在結尾處加一個else塊檢查:

if(strcmp("forward", token) == 0) 
else if(strcmp("back",token) == 0) 
else if(strcmp("turn",token) == 0) 
else if(strcmp("turn",token) == 0) 
else if(strcmp("stop",token) == 0) 
else 
{ 
    std::cerr << "Unknown command '" << token << "'\n"; 
} 
+0

我們使用藍牙設備向機器人發送信號和從機器人發送信號(似乎存在滯後問題)。當機器人將信息發送回設備讓我們知道它已連接時,程序會將信息放入cin.getline()中並結束程序(現在不應該發生該函數處於while循環中)。我用cin.ignore()來否定這個動作。但是,您的建議當然似乎值得,而且我會在明天美國東部時間下午5點左右回到實驗室的時候嘗試一下。 – Van 2010-04-12 23:53:26

+0

雖然這是一個很好的建議;當你的程序似乎誤解了輸入時,首先要檢查的是程序是否按照你認爲的方式看到輸入! – 2010-04-13 00:10:54

+0

你是對的,cin.ignore()扔掉了輸入的第一個字母。如果沒有cin.ignore(),那麼程序將無法運行,所以我最終要做的就是在它連接到機器人並且在我的手動驅動函數被調用之前將它移動到我的驅動程序中。 – Van 2010-04-13 22:03:43

0

我相信你的多重if語句與誤讀的命令沿的部分原因。我也會使用endl而不是使用/ n char。這樣做意味着你不需要忽略。

void Navigator::manualDrive() 
{ 

    const int bufSize = 42; 
    char uinput[bufSize]; 
    char delim[] = " "; 
    char *token; 
    while(true) 
    { 

     Navigator::parseInstruction(uinput); 
    } 
} 
/* parseInstruction(char *c) -- parses cstring instructions received 
* and moves robot accordingly 
*/ 


void Navigator::parseInstruction(char * c) 
{ 

    const int bufSize = 42; 
    char uinput[bufSize]; 
    char delim[] = " "; 
    char *token; 


    cout << "Enter your directions below: " << endl; 
    cin.getline (uinput, bufSize); 


    token=strtok(uinput, delim); 
    switch(token[3])//the command's fourth letter 
    //needed letter because strings don't work with switch 
    { 
     case 'w': //forward 
      int inches; 
      token = strtok(NULL, delim); 
      inches = atoi (token); 
      Navigator::travel(inches); 
      break;//this signifies the end of the case 

     case 'k': //back 
      int inches; 
      token = strtok(NULL, delim); 
      inches = atoi (token); 
      double value = fabs(0.0735 * fabs(inches) - 0.0550); 
      myRobot.backward(1/*speed*/, value/*time*/); 
      break; 

     case 'n': //turn 
      int degrees; 
      token = strtok(NULL, delim); 
      if(strcmp("left",token) == 0) 
      { 
       token = strtok(uinput, delim); 
       degrees = atoi (token); 
       double value = fabs(0.0041 * degrees - 0.0523); 
       myRobot.turnLeft(1/*speed*/, value/*time*/); 
      } 
      else if(strcmp("right",token) == 0) 
      { 
       token = strtok(uinput, delim); 
       degrees = atoi (token); 
       double value = fabs(0.0041 * degrees - 0.0523); 
       myRobot.turnRight(1/*speed*/, value/*time*/); 
      } 
      break; 

     case 'p': //stop 
      myRobot.motors(0,0); 
      break; 

     default: //the default case 
      cout << "Command Unknown" << endl; 
      break; 
    } 
} 
+0

我喜歡使用開關盒,比出於某種原因的聲明好得多,所以我可能會給它一個鏡頭。我需要定義每個案件的信件嗎? EX:char w [] =「forward」; – Van 2010-04-13 00:38:09

+0

我想你誤解了開關盒的工作原理。開關參數與每種情況進行比較,因此您無需爲每種情況聲明任何變量。 – datdo 2010-04-13 03:29:28

+0

不要緊,我只是意識到什麼開關(令牌[3])出於某種原因正在做。它找到第四個字母,如果它的w(向前的第三個字母)則執行'w'。對不起,我是一個主要的n00b,這肯定會有一段時間,然後我才能幫助這個網站。 – Van 2010-04-13 04:35:32