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. 可以引用一个结构体变量中的一个成员的值。
    引用形式:
    结构体变量名.成员名;
    " . " 成员运算符

    student1.name;

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

猜你喜欢

转载自blog.csdn.net/qq_41498261/article/details/82934918