第四章 复合类型
4.1 数组
数组(array)是一种数据格式,能够存储多个同类型的值。
要创建数组,可使用声明语句。数组声明应指出以下三点:
存储在每个元素中的值的类型;
数组名;
数组中的元素数
声明数组的通用格式如下:
typeName arrayName(arraySize)
arraySize表示元素数目,它必须是整型常数或const值
arrayone.cpp中说明了数组的一些属性,包括声明数组、给数组元素赋值以及初始化数组。
// arrayone.cpp -- small arrays of integers
#include
int main()
{
using namespace std;
int yams[3]; // creates array with three elements
yams[0] = 7; // assign value to first element
yams[1] = 8;
yams[2] = 6;
int yamcosts[3] = {20, 30, 5}; // create, initialize array
// NOTE: If your C++ compiler or translator can't initialize
// this array, use static int yamcosts[3] instead of
// int yamcosts[3]
cout << "Total yams = ";
cout << yams[0] + yams[1] + yams[2] << endl;
cout << "The package with " << yams[1] << " yams costs ";
cout << yamcosts[1] << " cents per yam.\n";
int total = yams[0] * yamcosts[0] + yams[1] * yamcosts[1];
total = total + yams[2] * yamcosts[2];
cout << "The total yam expense is " << total << " cents.\n";
cout << "\nSize of yams array = " << sizeof yams;
cout << " bytes.\n";
cout << "Size of one element = " << sizeof yams[0];
cout << " bytes.\n";
// cin.get();
return 0;
}
4.1.2 数组的初始化规则
只有在定义数组时才能使用初始化,之后就不能使用了,也不能将一个数组赋给另一个数组
如果只对数组的一部分进行初始化,则编译器将把其他元素设置为0.
4.2 字符串
// strings.cpp -- storing strings in an array
#include
#include // for the strlen() function
int main()
{
using namespace std;
const int Size = 15;
char name1[Size]; // empty array
char name2[Size] = "C++owboy"; // initialized array
// NOTE: some implementations may require the static keyword
// to initialize the array name2
cout << "Howdy! I'm " << name2;
cout << "! What's your name?\n";
cin >> name1;
cout << "Well, " << name1 << ", your name has ";
cout << strlen(name1) << " letters and is stored\n";
cout << "in an array of " << sizeof(name1) << " bytes.\n";
cout << "Your initial is " << name1[0] << ".\n";
name2[3] = '\0'; // set to null character
cout << "Here are the first 3 characters of my name: ";
cout << name2 << endl;
// cin.get();
// cin.get();
return 0;
}
字符串是存储在内存的连续字节中的一系列字符。存储在连续字节中的一系列字符意味着可以将字符串存储在char数组中,其中每个字符都位于自己的数组元素中。
在确定存储字符串所需的最短数组时,别忘了将结尾的空字符计算在内。
4.2.3 字符串输入
利用cin可以完成字符串输入,cin使用空白(空格、制表符和换行符)来确定字符串的结束位置。读取该单词后,cin将该字符串放到数组中,并自动在结尾添加空字符。
4.2.4 每次读取一行字符串输入
假设要使用getline()将姓名读入到一个包含20个元素的name数组中。可以使用这样的函数调用:
cin.getline(name,20);
getline()函数读取整行,使用通过回车键输入的换行符来确定输入结尾。
面向行的输入:get()
get()的工作方式:(1)与getline()类似
(2)将两个类成员函数拼接起来,如下:
cin.get(namel,ArSize).get();
4.3 string类简介
可以使用string类型的变量而不是字符数组来存储字符串。string 类使用起来比数组简单,同时提供了将字符串作为一种数据类型的表示方法。
要使用string类,必须在在程序中包含头文件string
// strtype1.cpp -- using the C++ string class
#include
#include // make string class available
int main()
{
using namespace std;
char charr1[20]; // create an empty array
char charr2[20] = "jaguar"; // create an initialized array
string str1; // create an empty string object
string str2 = "panther"; // create an initialized string
cout << "Enter a kind of feline: ";
cin >> charr1;
cout << "Enter another kind of feline: ";
cin >> str1; // use cin for input
cout << "Here are some felines:\n";
cout << charr1 << " " << charr2 << " "
<< str1 << " " << str2 // use cout for output
<< endl;
cout << "The third letter in " << charr2 << " is "
<< charr2[2] << endl;
cout << "The third letter in " << str2 << " is "
<< str2[2] << endl; // use array notation
// cin.get();
// cin.get();
return 0;
}
可以使用数组表示法来访问存储在string对象中的字符
4.3.1 字符串初始化
char first_data[]={“LE”};
string third_data={“LE”}
4.3.2 赋值、拼接和附加
不能将一个数组赋给另一个数组,但可以将一个string对象赋给另一个string对象
string str1;
string str2=“parent”;
str1=str2;
可以使用运算符+将两个string对象合并起来:
string str3;
str3=str1+str2;
str1+=str2;
4.3.3 string类的其他操作
可以使用函数strcpy()将字符串复制到字符组中,使用strcat()将字符串附加到字符数组末尾:
strcpy(charr1,charr2); //copy charr2 to charr1
strcat(charr1,charr2); //append contents of charr2 to charr1
4.4 结构struct简介
C++中的结构是一种比数组更灵活的数据格式,因为同一个结构可以存储多种类型的数据
假设Bloataire公司要创建一种类型来描述其生产线上充气产品的成员。具体来说,这种类型应存储产品名称、容量和售价。下面的结构描述可以满足这些要求:
struct inflatable
{
char name[20];
float volume;
double price;
};
新类型的名称为inflatable。
定位结构后,便可以创建这种类型的变量了。
inflatable hat;
inflatable woopie_cushion;
inflatable mainframe;
由于hat的类型为inflatable,因此使用成员运算符(.)来访问每个成员。hat.volume表示的是结构的volume成员。
// structur.cpp -- a simple structure
#include
struct inflatable // structure declaration
{
char name[20];
float volume;
double price;
};
int main()
{
using namespace std;
inflatable guest =
{
"Glorious Gloria", // name value
1.88, // volume value
29.99 // price value
}; // guest is a structure variable of type inflatable
// It's initialized to the indicated values
inflatable pal =
{
"Audacious Arthur",
3.12,
32.99
}; // pal is a second variable of type inflatable
// NOTE: some implementations require using
// static inflatable guest =
cout << "Expand your guest list with " << guest.name;
cout << " and " << pal.name << "!\n";
// pal.name is the name member of the pal variable
cout << "You can have both for $";
cout << guest.price + pal.price << "!\n";
// cin.get();
return 0;
}
结构声明的位置非常重要。有两种选择,一是将其放在mian()函数中(内部声明),另外一种是将其放在main()函数外(外部声明),外部声明可以被其后面的任何函数使用,而内部声明只能被该声明所属的函数使用。
C++不提倡使用外部变量,但提倡使用外部结构声明。
可以同时完成定义结构和创建结构变量的工作。
struct perks
{
int key_numbers;
char car[12];
}mr_smith,ms_jones;
4.4.5 结构数组
// arrstruc.cpp -- an array of structures
#include
struct inflatable
{
char name[20];
float volume;
double price;
};
int main()
{
using namespace std;
inflatable guests[2] = // initializing an array of structs
{
{"Bambi", 0.5, 21.99}, // first structure in array
{"Godzilla", 2000, 565.99} // next structure in array
};
cout << "The guests " << guests[0].name << " and " << guests[1].name
<< "\nhave a combined volume of "
<< guests[0].volume + guests[1].volume << " cubic feet.\n";
// cin.get();
return 0;
}
4.7 指针和自由存储空间
计算机程序在存储数据时必须跟踪的3种基本属性,包括:
信息存储在何处;
存储的值为多少;
存储的信息是什么类型;
利用地址运算符(&)就可以获得变量的地址。
4.7.1 声明和初始化指针
// pointer.cpp -- our first pointer variable
#include
int main()
{
using namespace std;
int updates = 6; // declare a variable
int * p_updates; // declare pointer to an int
p_updates = &updates; // assign address of int to pointer
// express values two ways
cout << "Values: updates = " << updates;
cout << ", *p_updates = " << *p_updates << endl;
// express address two ways
cout << "Addresses: &updates = " << &updates;
cout << ", p_updates = " << p_updates << endl;
// use pointer to change value
*p_updates = *p_updates + 1;
cout << "Now updates = " << updates << endl;
// cin.get();
return 0;
}
运算符被称为间接值运算符,用于指针,可以得到该地址处存储的值。
p_updates是指针(地址),而p_updates是int,而不是指针。
int ptr; //强调ptr是一个int类型的值
int* ptr; //强调int是一种类型-----指向int的指针。
下面的声明是创建一个指针(pl)和一个int变量(p2):
int p1,p2;
可以在声明语句中初始化指针。在这种情况下,被初始化的是指针,而不是它指向的值。
int higgens=5;
int* pt=&higgens;
4.7.4 使用new来分配内存
// use_new.cpp -- using the new operator
#include
int main()
{
using namespace std;
int nights = 1001;
int * pt = new int; // allocate space for an int
*pt = 1001; // store a value there
cout << "nights value = ";
cout << nights << ": location " << &nights << endl;
cout << "int ";
cout << "value = " << *pt << ": location = " << pt << endl;
double * pd = new double; // allocate space for a double
*pd = 10000001.0; // store a double there
cout << "double ";
cout << "value = " << *pd << ": location = " << pd << endl;
cout << "location of pointer pd: " << &pd << endl;
cout << "size of pt = " << sizeof(pt);
cout << ": size of *pt = " << sizeof(*pt) << endl;
cout << "size of pd = " << sizeof pd;
cout << ": size of *pd = " << sizeof(*pd) << endl;
// cin.get();
return 0;
}
在运行阶段为一个int值分配未命名的内存,并使用指针来访问这个值。C++中可以使用new运算符来分配内存;
int* pn=new int;
new int 告诉程序,需要适合存储int的内存。new运算符根据类型来确定需要多少字节的内存。然后,它找到这样的内存,并返回其地址。接下来,将地址赋给pn,pn是被声明为指向int的指针。现在,pn是地址,而*pn是存储在那里的值。
为一个数据对象(既可以是结构,也可以是基本类型)获得并指定分配内存的通用格式如下:
typeName* pointer_name=new typeName;
4.7.5 使用deltete释放内存
int* ps=new int;
…
delete ps;
4.7.6 使用new来创建动态数组
使用new创建动态数组
int* psome=new int [10];
…
delete [] psome;
使用new和delete时,应遵守以下规则:
1)不要使用delete来释放不是new分配的内存;
2)不要使用delete释放同一个内存块两次
3)如果使用new[] 为数组分配一个内存,则应使用delete[]来释放。
4)如果使用new[] 为一个实体分配内存,则应使用delete来释放。
5)对空指针应用delete是安全的;
使用动态数组
// arraynew.cpp -- using the new operator for arrays
#include
int main()
{
using namespace std;
double * p3 = new double [3]; // space for 3 doubles
p3[0] = 0.2; // treat p3 like an array name
p3[1] = 0.5;
p3[2] = 0.8;
cout << "p3[1] is " << p3[1] << ".\n";
p3 = p3 + 1; // increment the pointer
cout << "Now p3[0] is " << p3[0] << " and ";
cout << "p3[1] is " << p3[1] << ".\n";
p3 = p3 - 1; // point back to beginning
delete [] p3; // free the memory
// cin.get();
return 0;
}
从上面的代码可知,arraynew.cpp将指针p3当作数组名来使用,p3[0]为第一个元素。无法修改数组名的值,但指针是变量,因此可以修改它的值。
4.8.4 使用new创建动态结构
将new用于结构由两步构成:创建结构和访问其成员。
创建结构:
inflatable* ps=new inflatable;
访问成员:利用箭头成员运算符(->)。
// newstrct.cpp -- using new with a structure
#include
struct inflatable // structure definition
{
char name[20];
float volume;
double price;
};
int main()
{
using namespace std;
inflatable * ps = new inflatable; // allot memory for structure
cout << "Enter name of inflatable item: ";
cin.get(ps->name, 20); // method 1 for member access
cout << "Enter volume in cubic feet: ";
cin >> (*ps).volume; // method 2 for member access
cout << "Enter price: $";
cin >> ps->price;
cout << "Name: " << (*ps).name << endl; // method 2
cout << "Volume: " << ps->volume << " cubic feet\n"; // method 1
cout << "Price: $" << ps->price << endl; // method 1
delete ps; // free memory used by structure
// cin.get();
// cin.get();
return 0;
}