2013-03-21 52 views
1

我目前正在編寫一個命令行「解析器」,可以這麼說,到目前爲止它一直在工作,直到我嘗試了一些方法來添加選項/參數。字符數組的奇數輸出

void parser::nextCom() { 

    cout << parser::prompt; // parser::prompt = "> " 
    string com; 
    getline(cin, com); 

    char the_command[5]; // i want this to store the command e.g. "go" given that go is a command 
    for (int i = 0; i < com.size(); i++) { 
     if (com[i] == ' ') break; 
     else the_command[i] = com[i]; 
    } 

    cout << the_command << endl; 
} 

命令被複制,但一些非常不想要的字符顯示當在打印the_command到控制檯。

這是我所得到的,如果我通過「北上」的命令:

goÌÌÌÌÌÌÌÌÌÌÌÌÌÌØNi

我也不太清楚關於C++字符數組,但我不知道我怎麼得到這個輸出。任何幫助都將不勝感激。有關代碼的任何問題,或者如果您需要更多的代碼,只需評論,預先感謝

回答

4
cout << the_command << endl; 

在開始將com中的字符複製到the_command之前,該數組完全未初始化。我會代表這些未知字符問號(當然,他們很可能沒有真正問號):

? ? ? ? ? 

這意味着你不知道的char S的數組中的值是什麼。然後,您只將字符從the_command複製gocom,所以你的數組現在包含:

g o ? ? ? 

所以,當你試圖輸出這個數組,輸出流不知道什麼時候停止。您需要確保在o之後插入\0。這樣做將是一個辦法:

for (int i = 0; i < com.size(); i++) { 
    if (com[i] == ' ') { 
     the_command[i] = '\0'; 
     break; 
    } 
    else the_command[i] = com[i]; 
} 

這將使陣列像這樣:

g o \0 ? ? 

但是,你會好得多隻是堅持std::string。我不想考慮你可以避免使用這個數組的麻煩。這是我會怎麼寫你的函數:

void parser::nextCom() { 
    std::cout << parser::prompt; 

    std::string command_line, command; 
    std::getline(cin, command_line); 

    std::stringstream command_line_stream(command_line); 
    command_line_stream >> command; 

    if (command == "go") { 
     std::string direction; 
     command_line_stream >> direction; 
     go(direction); 
    } 
} 
+0

我想讓命令和使用if語句或switch語句來確定要運行哪個函數 – PurityLake 2013-03-21 20:22:50

+0

@PurityLake什麼阻止你?看我的編輯。 – 2013-03-21 20:24:57

+0

好吧,你有一個點,我會遇到與字符數組的麻煩,只是不知道如何使用字符串分離命令,是不是字符串流爲我做? – PurityLake 2013-03-21 20:27:13

1

這是因爲您的代碼中有緩衝區溢出。您將不確定長度的字符串複製到char [5]緩衝區中......基本上,您的循環正在將由輸入字符串確定的多個字節複製到char [5]數組的末尾,該數組不再以null結尾,所以「cout」只是讀取,直到它找到空字節。

+0

我看它的方式是,第一個命令是不大於5個字符 – PurityLake 2013-03-21 20:16:56

+1

好了,從理論上說,'如果(COM [I] =='「) break;'應該防止輸入buf溢出''go north'''。 (當然,代碼本身並不安全,因爲您無法保證所有輸入的條件都可以得到。) – us2012 2013-03-21 20:17:02

+2

好的catch,無論哪種方式,緩衝區都不是空終止的,導致cout讀得太遠。 – Ryan 2013-03-21 20:18:39

3

在讀取最後一個字符後,您不是null-terminating the_command。或者做任何邊界檢查。

請使用std::string代替。

3

更改代碼:

if (com[i] == ' ') 
{ 
    com[i] = '\0'; 
    break; 
} 

這將確保有你的字符數組的最後一個空終止。你看到垃圾的原因是因爲std::cout將愉快地打印字符,直到它看到一個空終止符。

1

基本上the_command[5]包含垃圾,因爲沒有被初始化並且不包含字符終止符。你可以先清除它,當您打印char陣列這樣,字符繼續插入,直到空字符\0在字符串中發現你會被罰款

for (i = 0; i < 5; i++) { 
    the_command[i] = 0; 
}