2014-03-07 44 views
1

我最終試圖編寫一個shell,所以我需要能夠解析命令。我試圖將每個單詞和特殊符號轉換爲令牌,而忽略空格。它適用於分隔令牌的字符是|但是隻要我使用單個空白字符,程序就會崩潰。這是爲什麼?閱讀空格解決Parser問題。爲什麼?

我是一名學生,我意識到我分離令牌的方式相當粗糙。我很抱歉。

#include <iostream> 
#include <stdio.h> 
#include <string> 
#include <cctype> 

using namespace std; 

#define MAX_TOKENS 10 

int main() 
{ 
    //input command for shell 
    string str; 

    string tokens[MAX_TOKENS] = { "0", "0", "0", "0", "0", "0", "0", "0", "0", "0" }; 
    int token_index = 0; 
    int start_token = 0; 

    cout << "Welcome to the Shell: Please enter valid command: " << endl << endl; 
    cin >> str; 


    for (unsigned int index = 0; index < str.length(); index++) 
    { 
     //if were at end of the string, store the last token 
     if (index == (str.length() - 1)) tokens[token_index++] = str.substr(start_token, index - start_token + 1); 

     //if char is a whitespace store the token 
     else if (isspace(str.at(index)) && (index - start_token > 0)) 
     { 
      tokens[token_index++] = str.substr(start_token, index - start_token); 
      start_token = index + 1; 
     } 

     //if next char is a special char - store the existing token, and save the special char 
     else if (str[index] == '|' || str[index] == '<' || str[index] == '>' || str[index] == '&') 
     { 
      //stores the token before our special character 
      if ((index - start_token != 0)) //this if stops special character from storing twice 
      { 
       //stores word before Special character 
       tokens[token_index++] = str.substr(start_token, index - start_token); 
      } 

      //stores the current special character 
      tokens[token_index++] = str[index]; 

      if (isspace(str.at(index + 1))) start_token = index + 2; 
      else start_token = index + 1; 
     } 
    } 

    cout << endl << "Your tokens are: " << endl; 

    for (int i = 0; i < token_index; i++) 
    { 
     cout << i << " = " << tokens[i] << endl; 
    } 



    return 0; 
} 
+0

你想看看那個:http://ericlippert.com/2014/03/05/how-to-debug-small-programs/ – Samuel

+0

我認爲問題是'cin'輸入空格。你可能不得不使用'cin.getline()'。看看http://stackoverflow.com/questions/5838711/c-cin-input-with-spaces –

+0

我的道歉,我會去找個橡皮鴨 – Nik

回答

1

有幾件事情:

  • 檢查token_index小於MAX_TOKENS每個增量後,再次使用它之前,否則,你有一個緩衝區溢出。如果將tokens更改爲std::vector,則可以使用at()語法作爲其安全網。
  • 表達式index - start_token的類型爲unsigned int,因此它永遠不會小於0。相反,你應該做index > start_token作爲你的測試。
  • str.at(index)如果index超出範圍,則會引發異常。然而,你從來沒有發現異常。取決於你的編譯器,這可能看起來像程序崩潰。將main()的代碼包裝在try...catch(std::exception &)區塊中。

最後,這是一個長鏡頭,但我會提到它的完整性。最初在C89中,isspace和其他is函數必須採取非負面的論點。它們的設計使得編譯器可以通過數組查找來實現它們,因此傳入負值的signed char會導致未定義的行爲。我不完全確定這是否在C和C++的各種後期版本中「固定」,但即使標準要求它,也有可能你有一個編譯器仍然不喜歡接收負面字符。要從代碼中消除這種可能性,請使用isspace((unsigned char)str.at(index)),或者甚至更好,使用C++語言環境界面。

+0

根據Sakthi Kumar的評論,我忽略了你甚至沒有在一行中閱讀,以:)開頭:)操作符格式化I/O;當讀入一個字符串時,它只讀取第一個空格。但是,在這種情況下,你的代碼仍然不應該受到影響。 –