1. 程式人生 > >c++--使用者自定義資料型別詳細篇

c++--使用者自定義資料型別詳細篇

結構體型別

在一個組合中包含若干個型別不同的資料項。相當於其他高階語言中的記錄。

宣告

  • 一般形式: struct 結構名 { 資料型別 成員名 1; 資料型別 成員名 2; : 資料型別 成員名 n; };
    1. 結構體型別名作為結構體型別的標誌。
    2. 宣告一個結構體型別時必須對各個成員進行型別宣告:型別名 成員名;
    3. 每一個成員也成為結構體中一個域,所以成員表又稱為域表。
    4. 結構體的成員可以是資料,又可以是函式。
  • 宣告結構體並不實際分配記憶體單元。
struct Student  //宣告一個結構體型別
{
	int num;
	char name[20];
	char sex;
	int age;
};
  • 注意:
    1. 結構變數的儲存型別概念、它的壽命、可見性及使用範圍與普通變數完全一致。
    2. 結構變數說明在結構型別宣告之後,二者也可同時進行。
    3. 結構變數佔記憶體大小可用 sizeof 運算求出: sizeof(運算量)

結構體型別變數的定義方法與初始化

  • 定義結構體型別變數的2中方法:
    1. 先宣告結構體型別再定義變數

      Student student1,student2;//student1,student2是兩個結構體型別Student的變數
      
    2. 宣告結構體型別的同時定義變數 一般形式: struct 結構體型別名{      成員名; } 變數名錶;

      struct Student
      {
      	int num;
      	char name[20];
      	char sex;
      	int age;
      }student1,student2;//student1,student2是兩個結構體型別Student的變數
      

當多檔案引用同一個結構體變數時,採用第一種方法;否則可採用第二種。 定義了結構體變數之後,系統會給它分配記憶體空間。

  • 初始化
    1. 可以在宣告結構體並定義變數時初始化

             struct Student
      		{
      			int num;
      			char name[20];
      			char sex;
      			int age;
      		}student1={201313232,“yejing”,‘f’,18};
      
    2. 結構體宣告與定義分開的情況,在定義變數時初始化。

      
          Student student1={201313232,“yejing”,‘f’,18};
      
      

引用結構體變數

  1. 可以將一個結構體變數的值賦給另一個具有相同結構的結構體變數。

    student1=student2;

  2. 可以引用一個結構體變數中的一個成員的值。 引用形式: 結構體變數名.成員名; " . " 成員運算子
#include <iostream>
using namespace std;
struct Student
{
	int num;
	char name[20];
	char sex;
	int age;
}student1,student2;
int main() {
	student1 = { 123,"yejing",'f',18 };
	student2 = student1; 
	cout << student1.num << "  " << student2.num;  //  123     123
	cout << student1.name << "  " << student2.name; // yejing  yejing
}

結構體陣列

每個陣列元素都是一個結構體型別的資料,它們分別都包含各自的成員項。

#include <iostream>
using namespace std;
struct Student
{
	char name[20];
	int count;
};
int main() {
	Student s[3] = {"Tom",0,"Rain",0,"Sun",0};
	char na[20];
	for (int i = 0; i < 10; i++) {
		cin >> na;
		//以下對分支if可以使用for+if改寫
			if (strcmp(na, s[0].name)==0)//對字元陣列的比較需要使用特殊函式
				s[0].count++;
			else if (strcmp(na, s[1].name)==0)
				s[1].count++;
			else if (strcmp(na, s[2].name)==0)
				s[2].count++;
	}
	
	for (int i = 0; i < 3; i++)
		cout << s[i].name << ":" << s[i].count<<endl;
}

結果: 在這裡插入圖片描述

指向結構體變數的指標

一個結構體變數的指標就是該變數所佔據的記憶體段的起始地址。 指標變數也可以指向結構體陣列中的元素。

  • 通過指向結構體變數的指標引用結構體變數的成員 以下3種方式等價:

    1. 結構體變數 . 成員名
    2. (* 指標名 ). 成員名
    3. 指標名->成員名
    #include <iostream>
    #include <string>
    using namespace std;
    struct Student
    {
    	string name;
    	char sex;
    	int age;
    };
    int main() {
    	Student s;
    	Student *p = &s;
    	s.name = "yj";
    	s.age = 19;
    	s.sex = 'm';
    	p->sex = 'f';//通過指標操作結構體型別變數的成員值
    	cout << s.name << " " << s.age<<" "<<s.sex<<endl;        //yj 19 f
    	cout << (*p).name << " " << (*p).age << " " << (*p).sex; //yj 19 f   注意*p兩邊的()不可以省去,因為成員運算子‘.’優先順序高於‘*’優先順序。此外p->name等價於(*p).name。
    	return 0;
    }
    
  • 用結構體變數和指向結構體變數的指標構成連結串列 連結串列:

    1. 連結串列是一種重要的資料結構。
    2. 連結串列有一個頭指標,它存放一個地址。該地址指向一個元素。
    3. 連結串列中的每一個元素稱為節點。每個節點都應該包括兩部分:使用者需要用的實際資料和下一個節點的地址。最後一個元素不在指向其他元素,它的地址部分放一個“NULL”表示空地址。連結串列到此結束。
    4. 連結串列中各元素的地址可以是不連續的,要找某個元素,可以通過上一個元素提供的地址找到它。
    5. 連結串列資料結構必須使用指標和結構體變數才能實現。可以宣告一個結構體型別,包含兩種資料成員:一種是使用者需要用的實際資料,另一種是用來存放下一個節點地址的指標變數。
#include <iostream>
#include <string>
using namespace std;
struct Student {
	int sno;
	string name;
	Student *next;
};
int main() {
	Student a, b, c;
	a.sno = 11; a.name = "Tom";
	b.sno = 22; b.name = "Sun";
	c.sno = 33; c.name = "Cloud"; 
	Student *head;
	Student *p;
	head = &a;
	a.next = &b;
	b.next = &c;
	c.next = NULL;
	p = head;
	do {
		cout << p->sno << " " << p->name << " " <<endl;  //輸出p指向的節點的資料
		p=p->next;                                       //使p指向下一個節點;相當於p=(*p).next;(*)p.next相當於a.next;
	} while (p!=NULL);                                   //輸出節點c資料後,p指標為null;
	return 0;
}
輸出:  11 Tom
		22 Sun
		33 Cloud

結構體型別資料作為函式引數

  1. 結構體變數名作為作引數
  2. 用指向結構體變數的指標作形參,結構體變數的地址作為實參
  3. 用結構體變數的引用作為函式形參,它成為實參的別名。
#include <iostream>
#include <string>
using namespace std;
struct Student {
	int sno;
	string name;
};
int main() {
	Student a, b, c;
	a.sno = 11; a.name = "Tom";
	b.sno = 22; b.name = "Sun";
	c.sno = 33; c.name = "Cloud"; 
	void print(Student s);
	void print(Student *p);
	void print1(Student &ss);
	print(a);    //Tom 11
	print(&b);   //Sun 22
	print1(c);   //Cloud 33
	return 0;
}
//1. 結構體變數名作為作引數
void print(Student s) {
	cout << s.name << " " << s.sno << endl;
}
//2. 用指向結構體變數的指標作形參,結構體變數的地址作為實參
void print(Student *p) {
	cout << p->name << " " << p->sno;
}
//3. 用結構體變數的引用作為函式形參,它成為實參的別名。
void print1(Student &s) {
	cout << s.name << " " << s.sno << endl;
}

動態空間分配與釋放

c語言中,使用庫函式malloc和free來分配和撤銷記憶體空間。 c++提供運算子new和delete來取代malloc和free函式。

  • new 和delete是運算子,而不是函式,執行效率高。

  • 一般形式: new 型別 [初值];

    1. 用new分配陣列空間時不可以指定初值。
    2. 若因為記憶體原因而導致不能正常分配空間,new會返回一個空指標。
    new int;     //開闢一個存放整數的儲存空間,返回一個指向該儲存空間的地址(即指標);
    	new int(100);//開闢一個存放整數的儲存空間,並且初值為100,返回一個指向該儲存空間的地址(即指標);
    
    	new char[10];//開闢一個存放字元陣列的空間,返回一個指向字元陣列首元素的地址(即指標);
    	new int[4][3];//開闢一個存放二維整型陣列的空間,返回一個指向該陣列首元素的地址(即指標);
    
    	float *p = new float(3.14);//開闢一個存放單精度數的空間,並指定初值為3.14,將返回的該空間的地址賦給指標變數p
    
    

    delete 指標變數------- --對變數 delete [] 指標變數 -------對陣列

        char *p1=new char[10];//開闢一個存放字元陣列的空間,返回一個指向字元陣列首元素的地址(即指標);
    	delete[]  p1;         //釋放開闢的空間
    	
    	int **p2 =new int[4][3]; //錯誤(活動)	E0144	"int (*)[3]" 型別的值不能用於初始化 "int **" 型別的實體,  C2440	“初始化” : 無法從“int(*)[3]”轉換為“int **”
    	delete[] p2;
    
    	float *p = new float(float(3.14));//開闢一個存放單精度數的空間,並指定初值為3.14,將返回的該空間的地址賦給指標變數p
        delete p;//釋放開闢的空間
    

列舉型別–enum

  • 只要將需要的變數值一一列舉出來,便構成了一個列舉型別。
  • 列舉型別的宣告形式如下: enum 列舉型別名 {變數值列表};

• 例如: enum Weekday {SUN, MON, TUE, WED, THU, FRI, SAT};

  • 列舉型別應用說明:
  1. 對列舉元素按常量處理,不能對它們賦值。例如,不能寫: SUN = 0;
  2. 列舉元素具有預設值,它們依次為:0,1,2,…。
  3. 也可以在宣告時另行指定列舉元素的值,如: enum Weekday {SUN=7,MON=1,TUE,WED,THU,FRI,SAT};
  4. 列舉值可以進行關係運算。
  5. 整數值不能直接賦給列舉變數,如需要將整數賦值給列舉變數,應進行強制型別轉換

設某次體育比賽的結果有四種可能:勝(WIN)、負(LOSE)、平局(TIE)、比賽取(CANCEL),編寫程式順序輸出這四種情況。 在這裡插入圖片描述

typedef語句

  • 為一個已有的資料型別另外命名

  • 語法形式 typedef     已有型別名     新型別名錶;

    • 例如 typedef double Area; Area a;

  • 不推薦使用,降低可讀性

聯合體

  1. 宣告形式: union 聯合名 { 資料型別 成員名 1; 資料型別 成員名 2; : 資料型別 成員名 n; };
  2. 聯合體型別變數說明的語法形式 聯合名 聯合變數名;
  3. 引用形式: 聯合名.成員名

例如: union uarea { char c_data; short s_data; long l_data; }

  1. 無名聯合 • 無名聯合沒有標記名,只是宣告一個成員項的集合,這些成員項具有相同的記憶體地址,可以由成員項的名字直接訪問。

例: union { int i; float f; } 在程式中可以這樣使用: i=10; f=2.2;