前言
复合类型是指在其他类型的基础上定义的类型。C++中内置的复合类型包括指针、引用、数组、结构体、共用体和枚举。下面将会给大家一一介绍。
数组
数组是一种数据格式,能够存储多个同类型的值。大家有时候会遇到这样的情况,需要给班上50个人的身高排序,大家会怎么做?首先需要把所有人的身高存入内存,再进行排序。可这要怎么做?不可能写50个int吧,这就要提到刚刚讲的数组了。
数组的声明
数组的声明很简单,只需要指出以下三点:
1.存储在每个元素中的值的类型;
2.数组名;
3.数组中元素的个数;
根据上面的问题可以声明下面的数组
int height [50];
表达式中的int是数组每个元素中的值的类型,height是数组名,通常也会解释为数组第一个元素的地址, 其中“[ ]”内需为整型常量或者常量表达式也可以是const(限定符)值,即其中的所有值都是在编译时已知的。
数组的初始化
数组只能在定义的时候才能进行初始化,此后就不能再使用了,也不可以将一个数组的值赋给另一个数组(当然可以用指针解决这个问题)。
#include<iostream>
using namespace std
int main(){
int cards[4]={3,6,8,10};//正确
int hand[4];//正确
head={2,3,4,5};//错误
head=cards;//错误
int (*hin)[4]=&cards;//正确,使用指针的方法,将数组cards的值赋给*hin,(*hin)[1]等于cards[1]
double hotel[5]={0.4,0.6}//正确,对数组一部分初始化,后面的将会被编译器置为0
long totals[5]={0};//正确,数组所有元素都置为0
return 0;
}
数组的访问
数组在访问时可以通过下标进行访问 ,还可以通过*(解除引用运算符)来访问。
#include<iostream>
using namespace std
int main(){
int yams[3]={1,2,3};
cout<<yams[0]<<endl;// 1
yams[1]=5;
cout<<*(yams+1)<<endl;// 5
yams[4]=9;//错误,但编译器并不会指出错误
return o;
}
需要说明的是*(yams+1),之所以可以这样用是因为数组名通常也会解释为数组第一个元素的地址,当然+1不同于整数相加,后面在指针部分会解释。yams[4]=9很显然这是错误的,[4]不是有效的下标,这个元素并不存在,虽然编译器并不会指出错误,但是程序运行过程中,这种赋值可能引发问题。所以大家还是要注意下标的使用。
字符串
字符串是存储在内存的连续字节中的一系列字符。可以将字符串存储在char数组中,其中每个字符都位于自己的数组元素中。
存储字符串常量
上面说了可以将字符串存在char数组中,那应该如何存进去了,下面介绍几种方法:
#include<iostream>
using namespace std
int main(){
char dog[8]={'b','e','f','d','g','\0'};//方式一
char fish[8]="Bubbles";//方式二
char baid[]="ghfds";//方式三
return o;
}
方式一是逐个的处理字符串中的字符,直到空字符为止,'\0'字符很重要,很重要,很重要(重要的事情说三遍!);如何重要呢?这是判断字符串是否结束的标志,如果你没写,那么恭喜你,当你使用cout输出这个字符串的时候,你会发现屏幕上会打印很多其他东西,很多是多少了?我也不晓得,可能一个,也可能没有,也可能10多个。这是因为cout在打印的时候会一直跟着数组后面的内存一直找,直到遇到'\0'字符为止。
方式二很简单只需要用引号将字符串括起就可以了,也不用写'\0',因为引号括起的字符串隐式的包括了结尾的空字符,不过在计算数组的大小时一定要加上空字符。
方式三并没有直接确定数组的大小,这并没有问题,编译器会根据后面字符串的大小来确定数组的大小,后面可以通过sizeof运算符和strlen()来确定字符串的大小。前者返回数组大小,后者返回可见字符长度即不算空字符。
字符串输入
char数组如何将键盘中输入的字符串存进去的?可以使用cin以及get()和getline()函数。
#include<iostream>
using namespace std
int main(){
char a[20];
char b[20];
cin>>a;//只能输入一个字符串,遇到空格会自动结束
cin.getline(b,20)//能输入一行字符串,且会自动替换换行符
cin.get(a,20);//能输入一行字符串,不会丢弃换行符
cin.get();//处理换行符
cin.get(b.20);
return o;
}
很多人会感觉使用getline()方便一些,但get()会更仔细一点,因为当我们需要知道数组是否将字符串全部存入,则可以根据数组中是否有换行符来确定。
string类
string类使用起来比数组简单,同时提供了将字符串作为一种数据类型的表示方法,使用string类的时候一定要包含头文件string。string对象的使用方式与字符数组相同。
1.可以使用C风格字符串来初始化string对象;
2.可以使用cin来将键盘的输入存储到string对象中;
3.可以使用cout来显示string对象;
4.可以用数组表示法来访问string对象中的字符;
除此外,string对象还能完成很多数组不能做到的,例如:可以将一个string对象的值赋给另一个string对象,可以用算术运算符+将两个string对象合并,还可以添加cstring头文件,然后使用strcpy()将一个字符串复制到一个数组中,strcat()将字符串添加到数组末尾等等,还有很多之后有机会再详细介绍。
结构、共用体以及枚举
结构
结构时一种比数组更灵活的数据格式,可以存储多种类型的数据。
#include<iostream>
using namespace std
int main(){
struct infl
{
int a;
float e;
char r[20];
}mr;//第一种声明方式
inf ms={1,1.2,'c','d'};//第二种声明方式及初始化方式
cout<<mr.a<<endl;
return o;
}
结构可以定义在main函数前外,也可以定义在main函数内,只是作用域与数据存储位置不同。struct是结构关键字,标识符infl是这种数据结构的名称,可以像声明int变量那样声明infl,也可以用代码中方式一的方法。访问结构体成员可以通过成员运算符“.”访问,这和对象很相似。
共用体
共用体(union)能存储不同的数据类型,但只能同时存储其中的一种类型。
#include<iostream>
using namespace std
int main(){
union one
{
int a;
float e;
char r;
};
one.a=5;
one.e=3.2;
return o;
}
值得注意的是共用体的长度为其最大成员的长度。这样可以节省很多内存空间。
枚举
enum工具提供一种创建符号常量的方式,这种方式可以代替const。还允许定义新类型。
#include <iostream>
using namespace std;
int main(){
enum day
{ saturday,sunday,monday,tuesday,wednesday,thursday,friday };
int a = 1;
enum day weekend;
weekend = ( enum day ) a; //类型转换
weekend = a; //错误
return 0;
}
weekend = a错误,是因为枚举量是整型,可以提升为int,但int类型不能自动转换为枚举类型。 saturday在默认的情况下是0,后面没有初始化的枚举量将比前一个枚举量大1;每个枚举都有取值范围,通过强制类型转换,可以将取值范围中的任何一个整数赋给这个变量。取值范围上限为大于枚举量中的最大值的最小2的幂,将它减一,就是上限了。如果枚举量中没有负数,则下限不得小于0;如果有负数则与找上限的方式相同只是要加上负号。
今天就到这了,后面关于指针的将会在下篇文章介绍。