2013-09-26 101 views
1

我正在練習C字符串/指針,並不能解決這個簡單的問題。 cin.getline()不會在第一次迭代時提示用戶輸入,但對於連續的字符串會這樣做。 (我任意選擇10作爲字符限制)。cin.getline()跳過第一次迭代

我可以忽略一些非常簡單的事情嗎?

void getStrings() {  
int num; 

cout << "How many strings? "; 
cin >> num; 

const int numStrings = num; 

char** stringSet = (char**) malloc(numStrings * sizeof(char*)); 

for (int i = 0; i < numStrings; i++) { 
    *(stringSet + i) = (char*) malloc(10); 
    cout << "String " << i << ": "; 
    cin.getline(stringSet[i], 10); 
    cout << endl; 
} 
+0

不要在C++ land中使用'malloc',不要忘記釋放它。使用'new' /'delete'。等等......爲什麼你需要裸指針呢? – deepmax

+1

如果你要去malloc,malloc足夠的空間。當你告訴getline接受包括NUL在內的11個字節時,你需要留出11個字節的空間,因爲getline將包含NUL。 – rici

+0

@MM。他的問題提到'c',他使用'malloc',所以'C'標籤是相關的,應該重新添加。 – jmstoker

回答

2

拋開這樣的事實:當標準庫的std::string等東西可用時,通常不宜使用C++中的裸指針,因此不應使用malloc。例如:代替(char*) malloc(10),您應該在程序結束時編寫new char[10]並記住delete[] *(stringSet+i)

這就是說,該行:

cin >> num 

...提取只有它後面的第一個數字。它會失敗(並且cin將設置它的fail位,並且如果在遇到任何非空白字符之前遇到一個數字,將需要與cin.reset()重置)。

但之後它會停止從輸入中提取。在你的輸入流中,輸入中仍然存在空格或其他字符。例如,如果你運行此程序,並輸入「2 foobar」,按Enter,它會立即打印:

String 1: foobar 
String 2: 

這是因爲流仍含有「foobar\n」。

爲了得到你正在尋找你可能會想你的循環前添加以下行爲:這將清除的東西流這有

cin.ignore(); 

1
cin >> num; 

這將提示一些用戶輸入。假設用戶完成了對他們的期望,他們將輸入一些數字,然後他們將會敲入回車鍵。這些數字將被存儲在輸入緩衝區中,但換行符也是如此,因爲它們敲入了回車鍵。 cin將解析數字以產生一個整數,它存儲在num變量中。它停在換行符上,換行符保留在輸入緩衝區中。稍後,您可以撥打getline,在輸入緩衝區中查找換行符。它立即找到一個,所以它不需要提示用戶輸入更多信息。所以看起來,第一次調用getline並沒有做任何事情,但實際上它確實如此。

+0

這是什麼叫的,我怎樣才能克服getline的這個輸入鍵的效果? –

0

你的意思是「不提示用戶輸入第一次迭代」?我的意思是「不打印提示輸入第一個字符串」,但根據您的代碼,我認爲這意味着「在輸入前打印輸入前兩個字符串的提示。」

cin >> num讀取一個數字,整個數字,而只是數字。它不會讀取數字後面的任何內容,如換行符。所以第一個getline讀取你已經輸入的換行符。

順便說一下,您應該使用cerr而不是cout作爲用戶提示。

cout應該保留用於實際輸出。這使得腳本編寫更容易,因爲您可以重定向cout而不依賴於cerr,並且因爲您不想在程序結果中捕獲提示。

+0

好我會記住這一點。對不清楚的解釋抱歉。打印出「字符串1:」,然後在沒有輸入第一個字符的情況下立即打印「字符串2:」。第二個字符串被接收,因爲它應該。至於「cin >> num」我知道它在流中保留了過多的輸入,但是問題仍然存在於單數字輸入如「2」中。 – geg

+0

@goldenchild:這不是輸入的長度問題。這是'cin >>'不會吞下換行符,所以下一個getline()只讀取一個換行符並立即返回。這就是爲什麼你的兩個提示是連續打印的原因。 – rici