我想,每個人一開始遇到這個問題,都會覺得挺簡單的。但真正實施的時候,可能就會覺得還是有點坑的。畢竟對於C/C++這樣成熟而使用廣泛的語言而言,對於這個簡單的問題竟然沒有一個簡潔有力甚至一行代碼的解決方案,依然是讓人覺得挺震驚的。
在 C/C++ 中,由於整數讀取通常是會忽略空格、制表符、換行符等等的,所以當一行整數位不定數目的讀取時,事情就變得有點棘手了。
由於對換行符的忽略,你無法判斷此時行是否結束。
在C++中,我們通常可以直接把 cin 讀取的返回作為條件判斷以此來判斷輸入是否成功,不成功則不再繼續 cin 從而退出循環,來完成對不定數目數據的讀入。
一開始可能會這樣想:while (cin >> a[n++]);
然後正如上述對換行符的忽略,換行之後 cin 並沒有 fail (可參考 cin.fail() 方法)。
然後可能會有如下想法:
1 int temp;
2 while (true)
3 {
4 cin >> temp;
5 if (temp == '\n') break;
6 a[n++] = temp;
7 }
但依然不行。因為數據中很可能有與 '\n' ASCII 碼相同的整數值,如果此時就 break 這樣讀入的數據不完整了。
然後我開始查找和提問,具體可參考下述鏈接的問題和討論:
http://segmentfault.com/q/1010000002782266
事實上,c++ 強大的支持是完全可以用已有的功能解決的,實在不行大不了總是可以讀入字符串再解析的嘛~
具體可以由上述鏈接中的答案,參考 sstream 和 sscanf。
並且,c++標准庫本身就重載了istream& operator>> (istream& (*pf)(istream&));,讓用戶自行處理一些特殊的input需求。
然而對於一個初入C++坑的騷年而言,這些我依然覺得不熟悉不簡明。
再繼續檢索了一些網上的內容之後,還是用一個類C的方式,解決了這個問題。
用到字符串,同時解析數字部分直接交給sscanf函數解決。既可以理解又保持簡潔,讓問題不至於過於深究了。
方案如下:
1 #include <string>
2 #include <iostream>
3 using namespace std;
4
5 char buffer[1024];
6 char* p = buffer;
7
8 gets(buffer);
9 while (*p != 0)
10 {
11 // 過濾空格與縮進
12 while (*p == ' ' || *p == '\t') p++;
13
14 // 讀整數
15 if (sscanf(p, "%d", &a[n++]) == 0) break;
16
17 // 偏移指針到非數字部分
18 p++;
19 while (*p >= '0' && *p <= '9') p++;
20 }
其中 a 是存儲整數的數組,n是其下標,最終也是整個數組的長度。