学习C++——复合类型

来源:互联网 发布:保险网络大学考证 编辑:程序博客网 时间:2024/05/16 01:47

一、数组

声明数组的通用格式:数据类型  数组名字[数组元素个数];

       数组初始化:int cat[4] = {1,2,3,4};这种方式只能在声明数组的时候进行初始化赋值。这样也行,int cat[] = {1,2,3,4};

       C++标准模板库(STL)提供了一种数组的替代品——模板类vector,而C++11新增了模板类array。

二、字符串

 1、字符串的存储

char dog[10] = {'a','g','d','h','\0'};//字符串存储在字符数组中,并以空字符(‘\0’)结束。

char dog[10] = "agdh";//自动在字符串的末尾添加上空字符(‘\0’)。

要将字符串存储到数组中,一是将数组初始化位字符串常量,二是将键盘或文件输入读入到数组中。

2、字符串的输入

①cin

<span style="font-size:10px;"><span style="font-size:12px;">#include <iostream>int main(){using namespace std;const int arSize = 10;char name[arSize];cout << "Enter your name:";cin >> name;cout << "The name is " << name << endl;cin.get();cin.get();//while(1);return 0;}</span></span>



cin用空白符来确定字符串的结束位置,这也意味着使用cin输入字符串的时候只能读取一个单词。读取该单词之后,cin将该字符串放到数组中,并自动在末尾加上空字符。但是此时的换行符留在了输入队列中。

比如:cin >> year;

cin.getline(name,arSize);则因为此语句读取的第一个字符就是换行符,所以读入到数组name中的内容为空。应该先将换行符读取走。改进 cin >> year;

cin.get();

cin.getline(name,arSize);

②面向行的输入:getline()

getline()函数读取整行,它使用通过回车输入的换行符来确定输入结尾。使用方法是cin.getline(数组名,元素个数);其中元素个数包括空字符。

它在读取指定数目的字符之后或者遇到换行符的时候会停止读取操作。但是它并不保存换行符,而是在最后加上一个空字符,也就是用空字符来替换换行符,此时的输入队列中并没有换行符,而是被丢弃了

<span style="font-size:10px;"><span style="font-size:12px;">#include <iostream>int main(){using namespace std;const int arSize = 10;char name[arSize];cout << "Enter your name:";cin >> name;cout << "The name is " << name << endl;cin.getline(name,9);cout << "The name is " << name << endl;cin.get();//while(1);return 0;}</span></span>

第二次name数组中的元素为:' ','x','i','n',' ','x','i','n','\0'

面向行的输入:get()

该函数有好几种形式,其中有一种形式和getline()类似,但是get()并不读取并丢弃换行符,而是将换行符留在输入队列中。

cin.get(name1,arSize);

cin.get(name2,arSize);

由于第一次调用后,将换行符留在了输入队列中,因此第二次调用时读取的第一个字符就是换行符,此时函数认为已经到了末尾,便不再读取任何字符。

解决办法是中间假如cin.get()用来将换行符读取。

cin.get(name1,arSize);

cin.get();

cin.get(name2,arSize);

由于cin.get(name,arSize)返回的是一个cin对象,所以上面等价于是cin.get(name1,arSize).get().get(name2,arSize);也等价于cin.getline(name1,arSize).getline(name2,arSize);


<span style="font-size:10px;"><span style="font-size:12px;">#include <iostream>int main(){using namespace std;const int arSize = 20;char name[arSize];char lunch[arSize];cout << "Enter your name:";cin.get(name,arSize).get();cout << "The name is " << name << endl;cout << "Enter your lunch:";cin.get(lunch,arSize).get();cout << "The lunch is " << lunch << endl;cin.get();return 0;}</span></span>


如果没有加上get()则:此时数组lunch为空数组,没有内容。

<span style="font-size:10px;"><span style="font-size:12px;">#include <iostream>int main(){using namespace std;const int arSize = 20;char name[arSize];char lunch[arSize];cout << "Enter your name:";cin.get(name,arSize);cout << "The name is " << name << endl;cout << "Enter your lunch:";cin.get(lunch,arSize);cout << "The lunch is " << lunch << endl;while(1);return 0;}</span></span>




三、string类简介

①例子

<span style="font-size:10px;"><span style="font-size:12px;">#include <iostream>#include <string>int main(){using namespace std;string str1;string str2 = "yao xiaokui";//初始化字符串string str3;string str4;cout << "输入字符串str1 :"; cin >> str1;cout << "str1 = " << str1 << endl;cout << "str2 = " << str2 << endl;cout << "str2[4] = " << str2[4] << endl;str3 = str1 + str2;//相加cout << "str3 = " << str3 << endl;str4 = str3;//赋值cout << "str4 = " << str4 << endl;cin.get();cin.get();return 0;}</span></span>


②常见函数(这些函数位于头文件 <cstring>中,所以要有语句 #include<cstring>)

strcpy(str1,str2);将str2复制到str1中

strcat(str1,str2);将str2附加到str1的末尾

str1_length = str1.size();测的str1的长度

getline(cin,str);此时cin作为getline()函数的一个参数

<span style="font-size:10px;"><span style="font-size:12px;">#include <iostream>#include <string>int main(){using namespace std;char charr[20];string str;cout << "Length of charr[] = " << strlen(charr) << endl;cout << "Length of str = " << str.size() << endl;cout << "输入charr:";cin.getline(charr,20);cout << "charr = " << charr << endl ;cout << "输入str:";getline(cin,str);cout << "str = " << str << endl;cin.get();return 0;}</span></span>


备注:cin.getline(数组名,元素个数);此时getline是istream类中的一个成员函数(方法)。但是没有cin.getline(str,元素个数)。也就是说在istream类中有double、int和其它基本类型的类方法,但是没有处理string对象的类方法。

备注:string类中的size()可以获得字符串中的字符数。str.size()就得到str对象的字符个数。

总之输入string对象的方法主要有cin>>str;和getline(cin,str);   


四、结构

1、结构的组成部分

struct 结构名

{

char name[23];

int n;

double price;

};

2、例子

<span style="font-size:10px;"><span style="font-size:12px;">#include <iostream>struct inflatable{char name[20];float volume;double price;};int main(){using namespace std;inflatable guest = {"yao kui",0.12,23.3};cout << "guest's name is  " << guest.name <<endl;cout << "guest's price is " << guest.price << endl;cin.get();return 0;}</span></span>



备注:结构体的声明可以位于main函数之前,也可以位于mian函数中。还可以定义结构数组,如inflatable  fits[100];

五、共用体

共用体(union)是一种数据格式,它能够存储不同的数据类型,但只能同时存储其中的一种类型。也就是说结构可以同时存储int、long、double;但是共用体只能存储int,long,double的其中一种数据类型。

union 名字

{

int i;

double sum;

float price;

};


六、枚举

C++的enum工具提供了另一种创建符号常量的方式,这种方式可以替代const。它还允许定义新的类型,但必须按照严格的限制进行。

enum spectrum {red, orange, yellow, green, blue, violet, indigo, ultraviolet};

让spectrum称为新类型的名称,spectrum被称为枚举,将red,orange,yellow等等作为符号常量,它们对应整数值0~7。这些常量叫做枚举量。

1、

spectrum band;

band = orange; //band = 1;

2、band = spectrum(1);//强制类型转换

3、enum bits {one = 1, two = 2, four = 4, eight = 8};//显示地设置枚举量的值

4、enum bigstep {first, second = 100, third};//first默认是0,second=100,third为101。后面没有被初始化的枚举量将比它前面的枚举量大1。

七、指针和自由存储空间

1、存储数据的时候,定义一个变量,声明语句指出了值得类型和符号名,还让程序为值分配内存,并在内部跟踪该内存单元。指针变量存储的数据的地址。int * 值一种类型——指向int的指针。如 int * ptr;//ptr值一个指向int类型数据的指针。

2、指针的危险:C++在创建指针变量时,计算机将分配用来存储地址的内存,但是不会分配存储指针所指向的数据的内存。所以一定要把指针初始化为一个确定的适当的地址。

3、使用new来分配内存

指针真正的用武之地是在运行的阶段分配未命名的内存以存储值,并用指针来访问它。在C语言中,用库函数malloc()函数来分配内存;在C++中,用new来分配内存。

typeName * pointer_name = new typeName;  比如 int * p_int = new int;

常规变量的值存储在成为栈(stack)的内存区域中,而new从被称为堆(heap)的地方或自由存储区(free store)的内存区域分配内存。

4、使用delete释放内存

当需要内存的时候,用new来请求内存。当使用完分配的内存之后,使用delete来释放内存,归还给内存池。delete pointer_name;它将释放指针指向的内存区域,但是并不会使指针变量消失。

5、使用new来创建动态数组

在编译时给数组分配内存被称为静态联翩(static binding),意味着数组是在编译时加入到程序中的,在编写程序时就要指定数组的长度。

使用new的时候,是在运行阶段创建的,还可以选择数组的长度,这称为是动态联翩(dynamic binding),这种数组叫做动态数组(dynamic array)。

使用new来创建动态数组

int * psome = new int [10];//new运算符返回第一个元素的地址

释放分配的动态数组

delete [ ]  psome;//释放动态数组

 表示动态数组中的元素

psome[i];表示数组中第i+1个元素。

6、使用new和delete时要注意的事项

①不要使用delete释放不是new分配的内存

②不要使用delete释放同一个内存块两次

③如果使用new[]为数组分配内存,则应使用delete [] 来释放内存

④如果使用new []为一个实体分配内存,则应使用delete来释放内存

⑤对空指针使用delete是安全的


八、指针、数组和指针算术

1、C++将数组名解释为数组中第一个元素的地址;

double arr[n];

double *parr = arr; 等价于 double parr = &arr[0];

arr[2] = *(arr + 2);

parr[2]= *(parr + 2);

总之,在很多情况下,可以以相同的方式使用指针名和数组名。区别在于,可以修改指针的值,而数组名是常量;另外,对数组名用sizeof运算得到是数组的长度,但是对指针名用sizeof运算得到的是指针变量的长度。

int cat[10];

&cat[0]和&cat在数值上是相同的,但是含义是不同的。&cat[0]是一个4字节内存块的地址,&cat是一个40字节内存块的地址。

int * p_cat0 = &cat[0];

int (* p_cat) [40] = &cat;

2、const char * peo = "people";

"people"实际上表示的是字符串的地址,这条语句是把"people"的地址赋给了peo指针。

以这种方式使用const意味着可以用peo来访问字符串,但是不能修改它。

九、使用new创建动态结构

将new用于创建动态结构由两部组成:创建结构和访问其成员。

创建结构:inflatable * ps = new inflatable;

访问成员:ps->price;用于访问结构中的price成员

此时*ps就是结构,所以ps->price等价于是(*ps).price


十、使用new和delete的一个例子

<span style="font-size:10px;">#include <iostream>#include <cstring>using namespace std;char * getname(void);int main(){char * name;name = getname();cout << name << " at " << (int *)name << endl;delete [] name;name = getname();cout << name << " at " << (int *)name << endl;delete [] name; cin.get();cin.get();return 0;}char * getname(){char temp[80];cout << "Enter last name: ";cin >> temp;char * pn = new char[strlen(temp)+1];strcpy(pn,temp);return pn;}</span>

备注:如果返回的是temp,则程序失败。因为当调用的函数完毕之后,temp数组将消失,因为该数组属于是自动存储。但是pn指向的空间属于是动态存储,并不随调用函数的结束而消失。所以应该返回pn。

十一、自动存储、静态存储和动态存储

1、自动存储

在函数内部定义的常规变量使用自动存储空间,称为是自动变量。这意味着它们在所属的函数被调用时自动产生,在该函数结束时消失。

自动变量是一个局部变量;通常存储在栈中。

2、静态存储

静态存储是在整个程序执行的过程中一直都存在的存储方式。使变量称为静态的方式有两种:一种是在函数的外面定义它,另一种是在声明变量时使用关键字static,如

static double fee = 123.333

3、动态存储

由new和delete实现动态存储,它们管理着一个内存池,称为是自由存储区或者是堆(heap)。该内存池与静态变量和自动便量的存储是分开的。

十二、数组的替代品

1、模板类vector

模板类vector类似于string类,也是一种动态数组,对象存储在中。可以再运行阶段设置vector对象的长度,可以在末尾附加上新数据,还可以在中间插入新数据。事实上,vector类是使用new和delete来管理内存的,但是这种工作是自动完成的。

首先,要使用vector对象,必须包含头文件vector;其次,vector包含在名称空间std中,因此可以使用using或者std::vector;第三,模拟使用不同的语法来指出它存储的数据类型;第四,vector类使用不同的语法来指定元素数。

vector<typeName> vt(n_elem);声明了一个名为vt的vector对象,可以存储n_elem个类型为typeName的元素。

2、模板类array(C++11)

C++11新增了模板类array,它也位于名称空间std中。与数组一样,array对象的长度也是固定的,也使用(静态内存分配),而不是自由存储区。

要创建array对象,需要包含array头文件。

array<typeName,n_elem> arr; 创建了一个名为arr的array对象,包含n_elem个类型的typeName的元素。

可以将一个array对象直接赋给另外一个array对象。

0 0