C++編程入門系列之八(自定義數據類型)
上兩節中雞啄米講了編程入門知識-算法的選擇結構和循環結構,這一講雞啄米給大家介紹下自定義數據類型。
什麼是自定義數據類型呢?大家記得像char、int、float等類型嗎?這些都是C++內置的基本數據類型,這些數據類型是不能滿足我們在編程中的要求的,需要自己定義一些數據類型使用。自定義數據類型有:枚舉類型、結構類型、聯合類型、數組類型和類等。這一講雞啄米主要講枚舉類型、結構類型和聯合類型,其他類型後面雞啄米會細講。
1.枚舉類型
我們在現實當中經常遇到這種情況,描述一件事情時只能取幾個有限的值,比如,一週只有星期一、星期二…星期日七天,比賽結果只有勝、負、平和比賽取消等四種結果。我們可以用0到6的整數表示星期一到星期日,7,8,9等都不是合法數據,如果我們用整數來表示星期幾那就需要專門判斷下是不是在0到6之間,但是如果用枚舉類型定義就沒有這種問題,因爲枚舉類型就那幾個可能的值。枚舉類型的聲明形式爲: enum 枚舉類型名 { 變量值列表 }; 變量值列表裏都是整型變量,另外不要忘記最後面的分號!
比如,enum weekday { sun,mon,tue,wed,thu,fri,sat };
這裏的枚舉元素sun、mon…都沒有指定值,它們就使用默認值,依次爲0,1,2…。即sun就是0,mon就是1,…sat是6。也可以在聲明枚舉類型時指定枚舉元素的值,比如
enum weekday { sun=7, mon=1, tue, wed, thu, fri, sat };
這裏sun就是7,mon是1,後面的值在mon的基礎上依次加1,即tue等於2,wed爲3…sat是6。枚舉元素按常量處理,不能對它們賦值除了聲明的時候,像sun=0;這樣的語句就是非法的。
枚舉類型我們聲明瞭以後就能像int、float等類型那樣用了,可以定義枚舉類型的變量。整數值需要賦給枚舉變量時,應進行強制類型轉換。
雞啄米給大家個例子:設某次體育比賽的結果有四種可能:勝(win)、負(lose)、平局(tie)、比賽取消(cancel),編寫程序順序輸出這四種情況。分析:由於比賽結果只有四種可能,所以可以聲明一個枚舉類型,聲明一個枚舉類型的變量來存放比賽結果。
#include <iostream>
using namespace std;
enum game_result {WIN, LOSE, TIE, CANCEL};
int _tmain(int argc, _TCHAR* argv[])
{
game_result result; // 聲明變量時,可以不寫關鍵字enum
enum game_result omit = CANCEL; // 也可以在類型名前寫上關鍵字enum
int count;
for (count = WIN ; count <= CANCEL ; count++)
{
result = (game_result)count;
if (result == omit)
{
cout << "The game was cancelled\n";
}
else
{
cout << "The game was played ";
if (result == WIN)
cout << "and we won!";
if (result == LOSE)
cout << "and we lost.";
cout << "\n";
}
}
return 0;
}
運行結果是:
- The game was played and we won!
- The game was played and we lost.
- The game was played
- The game was cancelled
2.結構體
有時候我們需要將一些不同類型的數據組合成一個整體,例如,一個學生的學號、姓名、年齡和成績等,它們數據類型不同,但都屬於一個人。這就要用到結構體了,結構體就是由不同數據類型也可以是相同數據類型的若干數據組成的結合體,聲明形式爲:
struct 結構體名
{
數據類型 成員名 1;
數據類型 成員名 2;
:
數據類型 成員名 n;
};
這裏最後那個分號也不要忘記哦。雞啄米把上面提到的那個學生的結構體可以定義成如下形式:
struct student //學生信息結構體
{
int num; //學號
char name[20]; //姓名
char sex; //性別
int age; //年齡
float score; //成績
char addr[30]; //住址
};
定義了結構體類型,我們就可以用它來定義結構體變量,就像int a;那樣。結構體型變量的定義形式也類似int等類型: 結構體類型名 結構體變量名;。比如,定義一個上面的那個結構體變量,student s;。可以像這樣聲明瞭結構體類型以後再定義結構體變量,也可以把它們放在一起。結構體變量佔用內存的大小可以用sizeof(結構體類型名或變量名)計算。在定義結構體變量時可以直接賦初值。結構體成員的使用形式是:結構體變量名.成員名。
雞啄米給大家一個結構體變量的例子。
#include <iostream>
using namespace std;
struct student //學生信息結構體
{
int num;//學號
char name[20];//姓名
char sex;//性別
int age;//年齡
}stu={97001,"Lin Lin",'F',19}; // 聲明結構體類型的同時,定義結構體類型的變量,並賦初值。也可以分開。
int _tmain(int argc, _TCHAR* argv[])
{
cout<<stu.num<<" "<<stu.name<<" "<<stu.sex<<" "<<stu.age;
return 0;
}
大家可以放到vs2010上運行下看看結果。
3.聯合體
有的時候需要幾個不同類型的變量共用一組內存單元,這時就需要用聯合體,聯合體類型聲明的語法形式爲:
union 聯合名
{
數據類型 成員名 1;
數據類型 成員名 2;
:
數據類型 成員名 n;
};
聯合體類型變量聲明的語法形式是:聯合體類型名 聯合體變量名;。聯合體類型變量的引用形式是:聯合體變量名.成員名。
雞啄米給大家舉個聯合體類型的例子:
union uarea
{
char c_data;
short s_data;
long l_data;
};
聯合體類型在內存中是怎樣佔用內存單元的呢?聯合體佔用的內存大小是其佔內存最大的成員需要的內存大小,就像上邊的uarea,它佔用的內存大小就是最大成員long需要的4個字節。聯合體裏同時只能放一個成員的值。uarea放c_data時c_data佔用第一個字節,放s_data時s_data佔用前兩個字節,放l_data時l_data佔用全部的4個字節。
聯合體也可以沒有名稱,叫做無名聯合體。無名聯合體只是聲明一個成員項的集合,這些成員有相同的內存地址,可以用成員項的名字直接訪問。雞啄米給大家一個無名聯合體例子:
union
{
int i;
float f;
}
在程序總可以直接用成員項i和f的名字訪問i和f,比如 i=2; f=3.2;。無名聯合體一般是用作結構體的內嵌成員。雞啄米給寫一個使用聯合體的例子:
#include <iostream>
using namespace std;
union myun
{
int k;
struct { int x; int y; int z; }u;
}a;
int _tmain(int argc, _TCHAR* argv[])
{
a.u.x =4;
a.u.y =5;
a.u.z =6;
a.k = 0;
cout<<a.u.x<<" "<<a.u.y<<" "<<a.u.z<<" ";
return 0;
}
這個程序輸出0 5 6。爲什麼呢?不應該是4,5,6嗎?因爲聯合體的成員共用內存,所以a.u.x佔用的內存裏的4被後來的a.k**覆蓋了**,變成了0。
4.類型定義語句–typedef
我們編程時除了可以使用基本數據類型名和自定義的數據類型名以外還可以給一個已經存在的數據類型起個別名,這樣做有幾個好處,可以給已有的類型起一個有意義的名字,我們一看就知道它表示什麼,提高可讀性;還可以給較長的類型名另起一個短名。使用的語法形式是:typedef 已有類型名 新類型名錶;。新類型名錶中可以有多個標識符,它們之間用逗號分開,就是在一個typedef語句中可以爲一個已有數據類型聲明多個別名,比如,
typedef double length,width;
length a;
width b;
雞啄米講了幾個複雜點的自定義數據類型,大家好好消化吧,結構體類型用的比較多,而且結構體裏可以放函數的,只是我們一般不那樣用,跟我們以後要講的C++中的核心概念-類很相似,可以說基本一樣。就到這裏了,大家辛苦了!
思考:
- 本文講述了哪幾個自定義的數據類型?
- 枚舉類型的用處是什麼? 寫出一個枚舉類型
- 結構體定義的形式以及在內存中存儲的大小?
- 什麼是聯合體?如何定義的?佔用的內存單元是多少?本文例子中的結果爲什麼與預想的不同