C++随笔——构造数据类型(1)

参考视频:C++语言程序设计基础——清华大学郑莉老师

参考教材:C++语言程序设计教程(第3版)清华大学出版社

定义:

用基本类型构造的用户自定义数据类型,包括枚举、数组、指针、字符串、引用、结构与联合

一、枚举

1、如果一个变量只有几种可能的取值,可以使用枚举类型来定义。定义格式如下:

enum 枚举类型名 {枚举常量1, 枚举常量2,..., 枚举常量n};

其中,枚举常量默认值为0,1,2,…。
2、枚举值可以自动转换成整型值参加运算,结果为整型值。但是如果要将整型值赋给枚举变量,需要进行强制转换

#include "pch.h"
#include
#include
using namespace std;

enum city {Beijing, Shanghai, Tianjin = 6, Chongqing};

int main()
{
	int n;
	cin >> n;
	while (n >= Beijing)
	{
		switch (n)
		{
		case Beijing:cout << "Beijing" << endl; break;
		case Shanghai:cout << "Shanghai" << endl; break;
		case Tianjin:cout << "Tianjin" << endl; break;
		case Chongqing:cout << "Chongqing" << endl; break;
		default:cout << "Invalid city number!" << endl;
		}
		cin >> n;
	}
}

C++随笔——构造数据类型(1)_第1张图片

二、数组

1、一种在内存中依次连续存放的、具有同一类型的数据变量所组成的集合。定义格式如下:

数据类型 数组名[常量表达式];

其中,数组名代表数组元素在内存中的起始地址,是一个地址常量。
2、数组所占内存大小计算如下:

n * sizeof(元素类型);
或
sizeof(数组名);

3、在函数(包括主函数)中定义数组时不初始化,数组元素值为随机值;在函数外(全局变量)定义数组时不初始化,数组元素值为0。
4、上标越界:数组元素的访问地址值超过了数组的起始地址;
下标越界:数组元素的访问地址值越过了数组最后一个元素的地址。
5、数组的整体复制,代码举例如下:

#include "pch.h"
#include
using namespace std;

int main()
{
	int a[5], b[5];
	cout << "输入数组a的5个元素:";
	for (int i = 0; i < 5; i++)
	{
		cin >> a[i];
	}
	memcpy(b, a, sizeof(a));		//memcpy函数进行内存字节复制
	cout << "输出数组b的5个元素:";
	for (int i = 0; i < 5; i++)
	{
		cout << b[i] << " ";
	}
	return 0;
}

C++随笔——构造数据类型(1)_第2张图片
6、定义数组时,只有最高维元素的个数能够省略
7、多维数组的地址表达式,以b[2][3][4]为例:
b; //起始地址
b[1]; //b[1][0][0]的地址
b[2]; //错误,下标越界
b[0]+1; //与b[0][1]相同,b[0][1][0]的地址
b[1][2]; //b[1][2][0]的地址
b[1][2]+4; //b[1][2][4]的地址,数组中没有这个元素,指向了其他地方
8、数组名作为形参是数组应用的一个重要方面, 参考教材P98代码如下

#include "pch.h"
#include
using namespace std;

enum dir {Asc, Des};

int main()
{
	int n;
	void sort(int a[][5], int n, int col, dir D);
	int a[][5] = { {20060101,1,82,86,0},
	               {20060203,2,80,80,0},
	               {20060204,2,86,90,0},
	               {20060205,2,90,83,0},
	               {20060102,1,75,86,0} };
	n = sizeof(a) / sizeof(a[0]);
	for (int i = 0; i < n; i++)
	{
		for (int j = 2; j < 4; j++)
		{
			a[i][4] += a[i][j];
		}
	}
	sort(a, n, 4, Des);
	sort(a, n, 1, Asc);
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			cout << a[i][j] << "\t";
		}
		cout << endl;
	}
	return 0;
}

void sort(int a[][5], int n, int col, dir D)
{
	int t[5];
	for (int i = 0; i < n - 1; i++)
	{
		for (int j = i + 1; j < n; j++)
		{
			if ((a[i][col] < a[j][col] && D == Des) || (a[i][col] > a[j][col] && D == Asc))
			{
				memcpy(t, a[i], sizeof(t));
				memcpy(a[i], a[j], sizeof(t));
				memcpy(a[j], t, sizeof(t));
			}
		}
	}
}

C++随笔——构造数据类型(1)_第3张图片
9、关于书中P99注意中所阐述的,在网上找到了比较详细的解析:
链接:https://wenda.so.com/q/1367451411064356?src=180
C++随笔——构造数据类型(1)_第4张图片
10、字符数组与字符串
字符数组:存放字符型数据的数组。
①用字符初始化数组,如:

char c[] = { 'c','h','i','n','a'};
cout << sizeof(c);
//cout << strlen(c);			//不是用字符串初始化数组,所以不能用strlen(),结果错误,如下所示

C++随笔——构造数据类型(1)_第5张图片
②用字符串进行初始化,如:

char d[] = "china";
cout << sizeof(d) << endl;
cout << strlen(d) << endl;			//可以使用strlen(),结果如下所示

C++随笔——构造数据类型(1)_第6张图片

注意:

一、在用字符初始化数组时,除非将‘\0’作为数组元素放在初值表中,否则‘\0’不会自动附在初值表中的字符后,因此,一个字符数组不一定是字符串。如:

char c[] = { 'c','h','i','n','a','\0' };
cout << sizeof(c) << endl;
cout << strlen(c) << endl;			//字符数组初值表最后写入一个‘\0’元素,所以是一个字符串,可以用strlen(),结果如下所示

C++随笔——构造数据类型(1)_第7张图片
二、使用字符初始化数组时,初值表要加{},否则会出错。如下:

char s[] = { '\0' };
cout << sizeof(s) << endl;
cout << strlen(s) << endl;

C++随笔——构造数据类型(1)_第8张图片

三、指针

1、指针变量存储地址,指向内存单元
2、声明一个指针时,编译器只会为指针本身保留内存空间;而声名一个数组时,编译器会根据数组元素的个数申请内存空间。
3、所有指针变量都占四个字节包括字符指针

char *p = "abcdef";
cout << strlen(p) << endl;
cout << sizeof(p) << endl;

C++随笔——构造数据类型(1)_第9张图片
4、指针变量在使用之前必须有确切的指向,应先赋值,然后再引用
5、字符指针:指向字符的指针,可以通过指针访问字符串。
6、定义字符指针时仅分配存放指针的内存,不会分配内存来存放指针指向的字符串,如下,“=”后面的“abcd”以常量形式存于静态数据区,指针指向改区的首地址,只能读取,不能写入,所以指针p和q指向同一块内存区,(p==b)为真。(这种形式的字符串称为字符串常量,还更改指针变量本身的指向,但是不能修改指向的字符串中的字符。)
定义字符数组时会对数组元素分配内存空间,存储在全局数据区或栈区,可以读取和写入。

char *p = "abcdef";
char *q = "abcdef";
char a[] = "abcd";
char b[] = "abcd";
cout << boolalpha << (a == b) << endl;
cout << boolalpha << (p == q) << endl;

C++随笔——构造数据类型(1)_第10张图片
7、想要查看字符数组的首地址。 如果直接写a,则会输出字符串。结果如下:

cout << (int *)a << "," << &a << endl;
cout << a << endl;

C++随笔——构造数据类型(1)_第11张图片
想要通过字符指针查看字符串首地址。

cout << (int *)p << endl;

C++随笔——构造数据类型(1)_第12张图片
8、由于字符指针变量本身不是字符数组,如果它不指向一个字符数组或其他有效内存,就不能将字符串复制给该字符指针。,如下代码运行结果错误。

#include "pch.h"
#include
using namespace std;
int main()
{
	char *p = "abcdef";
	char *q = "123456";
	int i;
	for (i = 0; p[i] != '\0'; i++)
	{
		q[i] = p[i];
	}
	q[i] = '\0';
	cout << q << endl;
}

错误结果如下图:
C++随笔——构造数据类型(1)_第13张图片
错误原因: 字符指针指向的字符串以常量形式存于静态数据区,指针指向改区的首地址,只能读取,不能写入。
下面给出把字符串常量复制给字符指针的三种方法
方法一:代码如下

#include "pch.h"
#include
using namespace std;

int main()
{
	char *p = "abcdef";
	char *q = "123456";
	char str[12];
	q = str;
	int i;
	for (i = 0; p[i] != '\0'; i++)
	{
		q[i] = p[i];
	}
	q[i] = '\0';
	cout << q << endl;
}

C++随笔——构造数据类型(1)_第14张图片
方法二:代码如下

#include "pch.h"
#include
using namespace std;

int main()
{
	char *p = "abcdef";
	char *q = "123456";
	char str[12];
	q = str;
	strcpy(q, p);			//strcpy(串s1,串s2)功能:将串s2复制到s1指向的存储空间中,然后返回s1。
	                             其中,串s2可以是字符串常量。
	cout << q << endl;
}

C++随笔——构造数据类型(1)_第15张图片
方法三:代码如下

#include "pch.h"
#include
using namespace std;

int main()
{
	char *p = "abcdef";
	char *q = "123456";
	char str[12];
	q = str;
	while (*p)
	{
		*q++ = *p++;
	}
	*q = '\0';
	q = str;			//指针q在复制过程中一直在向后移动,所以在复制完成后需要重新指向首地址
	cout << q << endl;
}

C++随笔——构造数据类型(1)_第16张图片
后续内容,接下篇…

你可能感兴趣的:(C++)