目錄表

國立屏東商業技術學院 資訊工程系 物件導向程式設計

4. 複合型態


本章將就C++所提供的數種複合型的資料型態加以說明,包含陣列、字串等。

4.1 陣列

基本上,C++的陣列就如同C語言中的陣列一樣,並沒有特別不同之處,除了C++的陣列可以支援較多的資料型態以及物件(當然這都是來自於C++的新功能)。關於陣列的基礎,可參考C語言的陣列,在此不予贅述。

4.2 字串

字串(string)也是一種常見的複合型態,它是一些字元的集合。C++有兩種處理字串的方法,其一為傳統的C語言所採用的方式:用char陣列或是指標,其二為新的string類別。

4.2.1 C語言的字串陣列或字串指標

關於C語言原本就支援的字串處理方法,我們在此不做贅述,同學可以自行參考C語言的字串。我們僅就C++對於字串陣列或字串指標的處理加以討論。

C++語言可以使用cout輸出字串,若有兩個以上的字串常值(String Literals)要輸出時可以直接串接。以下程式碼是等價的:

cout << "Hello " << "C++";
cout << "Hello C++";
cout << "Hello " "C++";
cout << "Hello " 
"C++";

我們可以cin取得使用者輸入的字串,請參考下例:

using namespace std;
#include <iostream>
 
int main()
{
  char name[20];
 
  cout << "Please input your name: ";
 
  cin >> name;
  cout << "Hello, " << name << endl;
  return 0;
}

此程式的執行結果如下:

[14:32 user@ws home] ./a.out
Please input your name: Jack
Hello, Jack
[14:32 user@ws home]

看起來沒問題,但如果我們輸入的名字中含有空白字元,其結果將不正確,例如:

[14:32 user@ws home] ./a.out
Please input your name: Jack Lin
Hello, Jack
[14:32 user@ws home]

注意到了嗎?那個空白字元及其後的Lin都不見了。其實cin是C++的一個物件,你應該使用它的方法來取得字串,例如get()或getline()。關於物件及其方法的概述,我們將在以後的章節再行說明。

使用cin.get()或cin.getline()可以取得使用者的輸入直到遇到換行為止,我們以cin.getline()為例,改寫上述程式如下:

using namespace std;
#include <iostream>
 
int main()
{
  char name[20];
 
  cout << "Please input your name:";
 
  cin.getline(name, 20);
 
  cout << "Hello, " << name <<  endl;
  return 0;
}

使用getline()方法需要兩個引數,第一個是存放輸入的字串,第二個則為字串的長度(最後一個字元存放「\0」)。要注意getline()會將最後的換行字元從標準輸入讀入,但不會放在輸入結果內;get()則會將該換行字元留在標準輸入內,因此下一次的輸入將有可能遇到問題。請參考下面的程式:

using namespace std;
#include <iostream>
 
int main()
{
  char firstname[20];
  char lastname[20];
 
  cout << "Please input your first name: ";
  cin.get(firstname, 20);
 
  cout << "Please input your last name: ";
  cin.get(lastname, 20);
 
  cout << "Hello, " << firstname << " " << lastname <<  endl;
  return 0;
}

測試看看,上面這個程式會遇到什麼問題? 要解決這個問題,可以在第一個cin.get()後再加上一個cin.get()將換行字元清除:

cin.get(firstname, 20);
cin.get();

或是

cin.get(firstname, 20).get();

下面這個程式解決了上述問題:

using namespace std;
#include <iostream>
 
int main()
{
  char firstname[20];
  char lastname[20];
 
  cout << "Please input your first name: ";
  cin.get(firstname, 20).get();
 
  cout << "Please input your last name: ";
  cin.get(lastname, 20);
 
  cout << "Hello, " << firstname << " " << lastname <<  endl;
  return 0;
}

在考慮下一個程式:

using namespace std;
#include <iostream>
 
int main()
{
  char firstname[20];
  char lastname[20];
  int lucky;
 
  cout << "Please input a lucky number: ";
  cin >> lucky;
 
  cout << "Please input your first name: ";
  cin.get(firstname, 20).get();
 
  cout << "Please input your last name: ";
  cin.get(lastname, 20);
 
  cout << "Hello, " << firstname << " " << lastname <<  endl;
  return 0;
}

執行看看,會發生什麼結果?為解決此問題,我們可以在取得字串前,先以一個cin.get()來將前一個輸入數字時所遺留下來的換行清除掉,請參考下例:

using namespace std;
#include <iostream>
 
int main()
{
  char firstname[20];
  char lastname[20];
  int lucky;
 
  cout << "Please input a lucky number: ";
  (cin >> lucky).get();
//  cin >> lucky;
//  cin.get();
 
  cout << "Please input your first name: ";
  cin.get(firstname, 20).get();
 
  cout << "Please input your last name: ";
  cin.get(lastname, 20);
 
  cout << "Hello, " << firstname << " " << lastname <<  endl;
  return 0;
}

最後,如果你要使用原本C語言相關的字串處理函式時,請記得載入「cstring」,請參考下面的程式:

using namespace std;
#include <iostream>
#include <cstring>
 
int main()
{
  char *str1="Hello";
  char *str2=" World";
  char str3[20];
 
  cout << "str1=" << str1 << endl;
  cout << "str2=" << str2 << endl;
 
  strcat(str3, str1);
  strcat(str3, str2);
 
  cout << "The length of str1 is " << strlen(str1) << endl;
  cout << "str1+str2= " << str3 << endl;
  return 0;
}

4.2.2 C++的string類別

不同於C語言,C++提供了一個string類別,我們可以利用此類別進行字串的操作。以string類別進行字串處理,必須先宣告產生string類別的物件,然後才可以使用。使用string類別須載入「string」(#include <string>),下面的程式顯示一個簡單的例子:

using namespace std;
#include <iostream>
#include <string>
 
int main()
{
  string str;
 
  cout << "Enter your name: ";
  getline(cin, str);
 
  cout << "Hi, " << str << "!" << endl;
  cout << "The third letter in your name is " << str[2] << "." << endl;
 
  return 0;
}

要注意的是,我們使用的是在string中的getline()函式,而非cin.getline(),這兩者是不同的。getline()函式的第一個引數為所要取得輸入的資料流物件(也就是透過cin來取得),第二個引數為所要儲存的字串(string類別的物件)。string類別的物件,也可以被當成是字串陣列,直接以陣列的索引值加以存取。以下我們將詳細說明string類別的字串物件:

4.2.2.1 字串初始化

其實,在還沒開始學習何謂物件、何謂類別之前,我們可以暫時把string類別視為一種資料型態(當然是比較特別的資料型態),其字串的宣告與初始化就如同一般的變數宣告一樣:

string strName = "Hello";
string strName ("Hello");
string strName = {"Hello"};
string strName {"Hello"};

4.2.2.2 字串操作

string類別的字串物件可以進行各式的操作,包含assignment、concatenation、appending等,請參考以下的程式碼:

string str1;
string str2 {"Hello"};
string str3;
 
str1 = str2; //assignment
str3 = str1 + str2; //assign str3 the joined strings
str1 += str2; //ass str2 to the end of str1

另外,string類別的物件還提供許多操作的方法,包含:

假如要使用上述的方法,則以物件名稱加上「.」方法名稱即可,請參考下面的範例:

string str1;
getline(cin, str1);
cout << str1.size() << endl;

4.3 Structure

C++的structure和C語言一樣,本節僅列出其差異處,其一為:

struct point
{
   int x, y;
};
 
struct point p1;
point p2;         // C++允許不用寫struct
point p3 = {5,5};
point p4 {10,10}; // C++允許不用寫= 

第二個不同之處,是C++可以使用string類別的物件(當然也可以使用其它類別的物件)。

對structure不熟悉的同學,請參考C語言的結構體

4.4 Union 與 Enumeration

C++的union與enumeration和C語言一樣,在此不再贅述。對structure不熟悉的同學,請參考C語言的union與enurmation