1. 程式人生 > >C++入門筆記--複雜的資料型別--陣列和getline()函式

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;
} 

可是很顯然,這個程式很不成熟,通用性也不強,所以就要對他做進一步的改進。

下面改進的程式碼

  1. 對陣列的長度做了巨集定義,或者也可以用靜態變數(const unsigned short ITEM=5)。
  2. 再者就是對輸入的資料做了一個檢查,如果輸入的資料不合法的話,就要進行異常處理。前面幾個筆記裡已經講過cin>>array[i]如果呼叫成功的話返回值是1,否則是0.所以要充分利用這個特點,當其呼叫不成功的時候就要對它做異常處理---while語句塊裡的內容,但是在這裡十分必要的一個語句是cin.clear(),這個函式可不是用來清除緩衝區的。
  3. 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類的內建功能非常多,例如

  1. 提取子字串:

    string常用擷取字串方法有很多,但是配合使用以下兩種,基本都能滿足要求:

    find(string strSub, npos);

    find_last_of(string strSub, npos);

    其中strSub是需要尋找的子字串,npos為查詢起始位置。找到返回子字串首次出現的位置,否則返回-1。

  2. strmap(str1,str2):比較字串1和字串2是否想等。返回一個整數。(1)如果返回0則說明字串1和字串2相等(2)如果返回的數為正整數,則說明字串1大於字串2(3)如果返回的數為負整數,則說明字串1小於字串2

  3. strcat(str1,str2);

    將兩個字串連線起來。如a[3]={'a','b'};b[3]={'c','d'};cout<<strcat(a,b)<<endl;