C++入門筆記--複雜的資料型別--陣列和getline()函式
學習完複雜的資料型別的設計思路和使用習慣,就開始面向物件的學習。
1.陣列
陣列是許多程式設計語言的重要組成部分,尤其是在C語言程式裡會經常碰到他們。
陣列的優點在於,一個數組可以把多個同類型的值儲存在同一變數名下,需要被宣告為一種特定的型別。type name[length].
下面用C++實現一個試用陣列的任務,並談談在使用中有哪些地方需要注意。
程式設計任務:定義一個數組容納十個整數,這些整數來自使用者的輸入,我們將這些值的累加和,平均值計算並輸出
#include<iostream> using namespace std; int main(){ int array[10]; float total=0; cout<<"請輸入10個整形資料:\n\n"; for(int i=0;i<10;i++){ cout<<"請輸入第"<<i+1<<"個數據:"; cin>>array[i]; total += array[i]; } cout<<"累加和是:"<<total; cout<<"\n平均值是:"<<total/10; return 0; }
可是很顯然,這個程式很不成熟,通用性也不強,所以就要對他做進一步的改進。
下面改進的程式碼
- 對陣列的長度做了巨集定義,或者也可以用靜態變數(const unsigned short ITEM=5)。
- 再者就是對輸入的資料做了一個檢查,如果輸入的資料不合法的話,就要進行異常處理。前面幾個筆記裡已經講過cin>>array[i]如果呼叫成功的話返回值是1,否則是0.所以要充分利用這個特點,當其呼叫不成功的時候就要對它做異常處理---while語句塊裡的內容,但是在這裡十分必要的一個語句是cin.clear(),這個函式可不是用來清除緩衝區的。
- cin.clear()預設引數為0,即無錯誤,正常操作.我們可以繼續輸入,用cin來讀取。但是當我們輸入英文字母'k'時,不是int型,它的狀態標識改為fail,即錯誤,這時候cin就不能再正常讀取了,我們也無法輸入了。在這裡用cout對使用者輸出資訊,再用cin.clear讓錯誤標識改回為0,讓我們可以繼續輸入,再清空流資料繼續輸入(ignore).如果我們沒有了cin.clear,則會進入死迴圈,其過程為我們輸入了英文字母,它的狀態標識便為fail,當執行到條件判斷時,便總是回到錯誤的條件表示裡,並且我們再也沒辦法輸入,因為錯誤的表示關閉了cin,所以會進入死迴圈.
#include<iostream> #define ITEM 5 using namespace std; int main(){ // const unsigned short ITEM=5; 這句和開頭的巨集定義起的作用差不多一樣 根據自己的喜好二選一 int array[ITEM]; float total=0; cout<<"請輸入"<<ITEM<<"個整形資料:\n\n"; for(int i=0;i<ITEM;i++){ cout<<"請輸入第"<<i+1<<"個數據:"; while(!(cin>>array[i])){//對輸入資料做檢查 cout<<"請重新輸入一個合法的值!\n"; cin.clear();//將錯誤的識別符號重新改為0 否則就會陷入死迴圈 cin.ignore(100,'\n');//清除緩衝區的內容 }; total += array[i]; } cout<<"累加和是:"<<total; cout<<"\n平均值是:"<<total/ITEM; return 0; }
在C語言裡,字元被實際儲存在一個字元數組裡。在C++裡我們可以用同樣的方式來實現字串的儲存,但是我們一把不用,因為它提供了一個更好的std::string型別。
程式設計任務:分別嘗試用C和C++實現將使用者輸入的字串打印出來
//C語言
#include<stdio.h>
int main(){
const unsigned short LENGTH = 100;
char str[LENGTH];
gets(str);
puts(str);
}
下面用C++來實現,比較兩次輸入發現第一次輸出只有I,第二次全部輸出,說明cin>>str接收到空格的時候就以為要停止了。所以用getline()來獲取一段字串 。
//C++錯誤示範
#include<iostream>
#include<string>
int main(){
std::string str;
std::cout<<"請任意輸入一段字串:\n";
std::cin>>str;
std::cout<<str;
return 0;
}
//輸入:I love C++!
//輸出:I
//輸入:IloveC++
//輸出:IloveC++
getline():
getline()的原型是istream& getline ( istream &is , string &str , char delim );其中 istream &is 表示一個輸入流,譬如cin;string&str表示把從輸入流讀入的字串存放在這個字串中(可以自己隨便命名,str什麼的都可以);char delim表示遇到這個字元停止讀入,在不設定的情況下系統預設該字元為'\n',也就是回車換行符(遇到回車停止讀入)。
//C++正確示範
#include<iostream>
#include<string>
int main(){
std::string str;
std::cout<<"請任意輸入一段字串:\n";
std::getline(std::cin,str);
std::cout<<str<<"\n";
return 0;
}
//輸入:I love C++!
//輸出:I love C++!
關於getline()函式的進一步解釋:
//getline()函式,在C++premer中,標準string型別第二小節就是“用getline讀取整行文字”。書上給的程//序如下:
int main()
{
string line:
while(getline(cin,line))
cout<<line<<endl;
return 0;
}
/*
大家會發現執行時怎麼也跳不出迴圈,甚至會發生各種莫名其妙的錯誤。這是為什麼呢?在這裡我給大家做一個詳細的講解。
首先給大家介紹一下getline()函式(個人覺得百度百科給的果斷不夠詳細)
大家百度會發現getline()的原型是istream& getline ( istream &is , string &str , char delim );
其中 istream &is 表示一個輸入流,譬如cin;string&str表示把從輸入流讀入的字串存放在這個字串中(可以自己隨便命名,str什麼的都可以);char delim表示遇到這個字元停止讀入,在不設定的情況下系統預設該字元為'\n',也就是回車換行符(遇到回車停止讀入)。給大家舉個例子:
*/
string line;
cout<<"please cin a line:"
getline(cin,line,'#');
cout<<endl<<"The line you give is:"line;
/*
那麼當我輸入"You are the #best!" 的時候,輸入流實際上只讀入了"You are the ",#後面的並沒有存放到line中(應該是在緩衝區裡吧)。然後程式執行結果應該是這樣的:
*/
please cin a line:You are the #best!
The line you give is:You are the
/*
而且這裡把終止符設為#,你輸入的時候就算輸入幾個回車換行也沒關係,輸入流照樣會讀入,譬如*/
please cin a line:You are the best!
//這裡輸入了一個回車換行
Thank you!
# //終止讀入
The line you give is:You are the best!
//換行照樣讀入並且輸出
Thank you!
/*
以上就是getline()函式一個小小的例項了。
那麼如果把getline()作為while的判斷語句會怎麼樣呢?
讓我們一起來分析一下while(getline(cin,line))語句
注意這裡預設回車符停止讀入,按Ctrl+Z或鍵入EOF回車即可退出迴圈。
在這個語句中,首先getline從標準輸入裝置上讀入字元,然後返回給輸入流cin,注意了,是cin,所以while判斷語句的真實判斷物件是cin,也就是判斷當前是否存在有效的輸入流。在這種情況下,我想只要你的電腦不中毒不發神經你的輸入流怎麼會沒有效?所以這種情況下不管你怎麼輸入都跳不出迴圈,因為你的輸入流有效,跳不出迴圈。
然而有些同學誤以為while判斷語句的判斷物件是line(也就是line是否為空),然後想通過直接回車(即輸入一個空的line)跳出迴圈,卻發現怎麼也跳不出迴圈。這是因為你的回車只會終止getline()函式的讀入操作。getline()函式終止後又進行while()判斷(即判斷輸入流是否有效,你的輸入流當然有效,滿足條件),所以又執行getline()函式,所以,就這樣....
*/
C++裡關於string類的內建功能非常多,例如
- 提取子字串:
string常用擷取字串方法有很多,但是配合使用以下兩種,基本都能滿足要求:
find(string strSub, npos);
find_last_of(string strSub, npos);
其中strSub是需要尋找的子字串,npos為查詢起始位置。找到返回子字串首次出現的位置,否則返回-1。
-
strmap(str1,str2):比較字串1和字串2是否想等。返回一個整數。(1)如果返回0則說明字串1和字串2相等(2)如果返回的數為正整數,則說明字串1大於字串2(3)如果返回的數為負整數,則說明字串1小於字串2
-
strcat(str1,str2);
將兩個字串連線起來。如a[3]={'a','b'};b[3]={'c','d'};cout<<strcat(a,b)<<endl;