本章内容包括:
1. 创建和使用数组 | 2. 创建和使用C-风格字符串 |
3. 创建和使用string类字符串 | 4. 使用方法getline()和get()读取字符串 |
5. 混合输入字符串和数字 | 6. 创建和使用结构 |
7. 创建和使用共同体 | 8. 创建和使用枚举 |
9. 创建和使用指针 | 10. 使用new和delete管理动态内存 |
11. 创建动态数组 | 12. 创建动态结构 |
13. 自动存储、静态存储和动态存储 | 14. vector和array类简介 |
4.1 数组
数组array是一种数据结构,能够存储多个同类型的值
声明数组的通用格式 typeName arrayName[arraySize];
arraySize必须是整型常量或所有值都已知的常量表达式,不能是变量
C++数组从0开始编号,数组最后一个元素索引比数组长度小1
编译器不会检查使用下标是否有效
程序清单4.1 arrayone.cpp
// arrayone.cpp -- small arrays of integers
#include <iostream> //马铃薯分析程序 说明数组的一些属性
int main()
{
using namespace std;
int yams[3]; //声明数组
yams[0] = 7;
yams[1] = 8;
yams[2] = 6;
int yamcosts[3] = {20, 30, 5}; //声明时直接赋值
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;
}
只有在定义数组时才能使用初始化,此后就不能使用了,也不能将一个数组赋给另一个数组
可以使用下标分别给数组中的元素赋值
如果只对数组的一部分进行初始化,则编译器将把其他元素设置为0(技巧:将数组都定义为0 初始化第一个元素赋值为0)
如果初始化数组时方括号内([ ])为空,C++编译器将计算元素个数,使数组包含已有数据的个数
C++11新加特性 列表初始化可以省略 = , 可直接在大括号不写任何东西,直接都设置为0 , 列表初始化禁止缩窄转换
C++处理字符串方式有两种,一个C-风格字符串,一种基于string类库的方法
'\0' 手动停止
可以直接用引号括起,隐式带有\0 char bird[11] = "Mr. Cheeps"
在确定存储字符串所需的最短数组时,别忘了将结尾的空字符计算在内 隐式加的\0多出一位
任何两个由空白(空格、制表符和换行符)分隔的字符串常量都将自动拼接成一个
头文件cstring提供了很多字符串相关函数
程序清单4.2 string.cpp
// strings.cpp -- storing strings in an array
#include <iostream>
#include <cstring>
int main()
{
using namespace std;
const int Size = 15;
char name1[Size];
char name2[Size] = "C++owboy"; //声明数组
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"; //strlen计算可见字符,不算空字符
cout << "in an array of " << sizeof(name1) << " bytes.\n"; //sizeof指出数组长度
cout << "Your initial is " << name1[0] << ".\n";
name2[3] = '\0'; //结束字符串
cout << "Here are the first 3 characters of my name: ";
cout << name2 << endl;
cin.get();
cin.get();
return 0;
}
strlen()只计算可见的字符,而不把空字符计算在内
sizeof()计算数组的长度
程序清单4.3 instr1.cpp
// instrl.cpp -- reading more than one string
#include <iostream>
int main()
{
using namespace std;
const int ArSize = 20;
char name[ArSize]; //声明数组
char dessert[ArSize];
cout << "Enter your name:\n";
cin >> name;
cout << "Enter your favorite dessert:\n";
cin >> dessert;
cout << "I have some delicious " << dessert;
cout << " for you, " << name << ".\n";
cin.get();
cin.get();
return 0;
}
cin使用空白(空格、制表符和换行符)来确定字符串的结束位置
istream中的类(如cin)提供了一些面向行的类成员函数:getline()和get() 这两个函数都读取一行输入,直到换行符
cin.getline(name,20);
程序清单4.4 instr2.cpp
// instr2.cpp -- reading more than one word with getline
#include <iostream> //只是简单的把之前的改成了getline 正常了
int main()
{
using namespace std;
const int ArSize = 20;
char name[ArSize];
char dessert[ArSize];
cout << "Enter your name:\n";
cin.getline(name, ArSize);
cout << "Enter your favorite dessert:\n";
cin.getline(dessert, ArSize);
cout << "I have some delicious " << dessert;
cout << " for you, " << name << ".\n";
cin.get();
cin.get();
return 0;
}
getline()通过换行符来确定行尾,但不保存换行符。相反,存储字符串时,它用空字符来替换换行符
get() 面向行输出,多种变体 P80
程序清单4.5 instr3.cpp
// instr3.cpp -- reading more than one word with get() & get()
#include <iostream> //演示get() 拼接方式的输出
int main()
{
using namespace std;
const int ArSize = 20;
char name[ArSize];
char dessert[ArSize];
cout << "Enter your name:\n";
cin.get(name, ArSize).get();
cout << "Enter your favorite dessert:\n";
cin.get(dessert, ArSize).get(); //就是这,拼接方式
cout << "I have some delicious " << dessert;
cout << " for you, " << name << ".\n";
cin.get();
return 0;
}
当get()输入被阻断,用cin.clear()可以恢复输出
程序清单4.6 numstr.cpp
// numstr.cpp -- following number input with line input
#include <iostream>
int main()
{
using namespace std;
cout << "What year was your house built?\n";
int year;
cin >> year;
//cin.get(); //两种方法都可以
//(cin >> year).get();
cout << "What is its street address?\n";
char address[80];
cin.getline(address, 80);
cout << "Year built: " << year << endl;
cout << "Address: " << address << endl;
cout << "Done!\n";
cin.get();
cin.get();
return 0;
}
混合输入字符串和数字 后边的getline() 看到前边输入的会认为是换行符,在读取前用cin.get()丢掉换行符
方法多种,如(cin >> year).get();
要使用string类,头文件需要包含string,string类使得字符串隐藏数组性质,像处理普通变量一样
程序清单4.7 strtype1.cpp
// strtype1.cpp -- using the C++ string class
#include <iostream> //演示两种字符形式处理结果是一样
#include <string> //加载头文件
int main()
{
using namespace std;
char charr1[20];
char charr2[20] = "jaguar";
string str1;
string str2 = "panther";
cout << "Enter a kind of feline: ";
cin >> charr1;
cout << "Enter another kind of feline: ";
cin >> str1;
cout << "Here are some felines:\n";
cout << charr1 << " " << charr2 << " "
<< str1 << " " << str2
<< endl;
cout << "The third letter in " << charr2 << " is "
<< charr2[2] << endl;
cout << "The third letter in " << str2 << " is "
<< str2[2] << endl;
cin.get();
cin.get();
return 0;
}
可以将string对象声明为简单变量,且能自动调整string类的大小,
可以将char数组视为一组用于储存一个字符串的char存储单元,而string类变量是一个表示字符串的实体
不能将一个数组赋给另一个数组,但可以将一个string对象赋给另一个string对象
string可以使用+将两个string相加,+=将字符串附加在string对象的末尾(这里是不是char也可以)
程序清单4.8 strtype2.cpp
// strtype2.cpp -- assigning, adding, and appending
#include <iostream>
#include <string> //演示string类的一些操作和性质
int main()
{
using namespace std;
string s1 = "penguin";
string s2, s3;
cout << "You can assign one string object to another: s2 = s1\n";
s2 = s1;
cout << "s1: " << s1 << ", s2: " << s2 << endl;
cout << "You can assign a C-style string to a string object.\n";
cout << "s2 = \"buzzard\"\n";
s2 = "buzzard";
cout << "s2: " << s2 << endl;
cout << "You can append strings.\n";
s1 += s2;
cout << "s1 += s2 yields s1 = " << s1 << endl;
s2 += " for a day";
cout << "s2 += \" for a day\" yields s2 = " << s2 << endl;
cin.get();
cin.get();
return 0;
}
头文件cstring提供函数 strcpy()将字符串复制到字符数组中,使用函数strcat()将字符串附加到字符数组末尾
程序清单4.9 strtype3.cpp
// strtype3.cpp -- more string class features
#include <iostream>
#include <string> //string类的新特性 技术进行比较
#include <cstring>
int main()
{
using namespace std;
char charr1[20];
char charr2[20] = "jaguar";
string str1;
string str2 = "panther";
str1 = str2; //赋值和复制的比较
strcpy(charr1, charr2);
str1 += " paste"; //将字符串附加到字符数组末尾的比较
strcat(charr1, " juice");
int len1 = str1.size(); //两种计算字符串长度的方法
int len2 = strlen(charr1);
cout << "The string " << str1 << " contains "
<< len1 << " characters.\n";
cout << "The string " << charr1 << " contains "
<< len2 << " characters.\n";
cin.get();
return 0;
}
函数strlen()是一个常规函数, .size()是一个类方法,演示如4.9程序清单4.10 strtype4.cpp
// strtype4.cpp -- line input
#include <iostream>
#include <string>
#include <cstring>
int main()
{
using namespace std;
char charr[20]; //设定字符串长度
string str;
cout << "Length of string in charr before input: "
<< strlen(charr) << endl; //未被初始化字符串 遇到空字符才停止,这种情况是随机的
cout << "Length of string in str before input: "
<< str.size() << endl;
cout << "Enter a line of text:\n";
cin.getline(charr, 20);
cout << "You entered: " << charr << endl;
cout << "Enter another line of txet:\n";
getline(cin, str);
cout << "You entered: " << str << endl;
cout << "Length of string in charr after input: "
<< strlen(charr) << endl;
cout << "Length of string in str after input: "
<< str.size() << endl;
cin.get();
return 0;
}
cin.getline(charr, 20); 是类方法 处理基本类型 getline(cin, str);不是类方法,
可以将cin和cout用于string对象,而不用考虑其内部工作原理
其他形式的字符串字面值 P87 (没看)
4.4 结构简介
同一个数组可以存储多种类型的数据
struct关键字 新类型名称 大括号 包含结构成员
结构可以使用成运算符访问各个成员(.)
程序清单4.11 structur.cpp
// structur.cpp -- a simple structure
#include <iostream> //演示如何初始化结构
struct inflatable
{
char name[20];
float volume;
double price; //定义结构各个类型
};
int main()
{
using namespace std;
inflatable guest =
{
"Glorious Gloria",
1.88,
29.99 //声明一个结构 并初始化
};
inflatable pal =
{
"Audacious Arthur",
3.12,
32.99
};
cout << "Expand your guest list with " << guest.name;
cout << " and " << pal.name << "!\n"; //演示下功能
cout << "You can have both for $";
cout << guest.price + pal.price << "!\n";
cin.get();
return 0;
}
外部函数位于函数外边,可以被其后边任何函数使用,内部函数只能被该生命所属的函数使用
变量同理
初始化时与数组一样,用花括号括起,每个值占一行,也可在一行
C++11支持将列表初始化用于结构,= 等号可选,不允许缩窄转换
程序清单4.12 assgn_st.cpp
// assgn_st.cpp -- assigning structures
#include <iostream> //演示结构之间成员赋值
struct inflatable //声明结构
{
char name[20];
float volume;
double price;
};
int main()
{
using namespace std;
inflatable bouquet = //声明初始化
{
"sunflowers",
0.20,
12.49
};
inflatable choice; //声明
cout << "bouquet:" << bouquet.name << " for $";
cout << bouquet.price << endl;
choice = bouquet; //成员赋值
cout << "choice: " << choice.name << " for $";
cout << choice.price << endl;
cin.get();
return 0;
}
可同时完成初始化和创建结构变量的工作,只需将变量名放在结束括号的后面即可
在将变量名放在结束括号后边还可以直接进行赋值
还可以声明没有名称的结构类型 本书不讨论 P92
结构还可以组成数组 创建 inflatable gifts[100] ,这样就可以使用索引调用数组中的每个结构了
初始化结构数组时,第一个参数是结构名 然后多行花括号并列
程序清单4.13 arrstruc.cpp
// arrstruc.cpp -- an array of structures
#include <iostream> //演示结构数组的使用
struct inflatable
{
char name[20];
float volume;
double price;
};
int main()
{
using namespace std;
inflatable guests[2] =
{
{"Bambi", 0.5, 21.99},
{"Godzilla", 2000, 565.99}
};
cout << "The guests " << guests[0].name << " and " << guests[1].name
<< "\nhave a combined volum of "
<< guests[0].volume + guests[1].volume << " cubic feet.\n";
cin.get();
return 0;
}
结构中的位字段 P94
4.5 共用体
共用体union是一种数据格式, 能够存储不同数据结构,但只能同时存储其中一种类型 类型只有int long double
共用体每次只能存储一个值,所以长度为其中的最大成员那长度
共用体还有匿名的 用法P95
4.6 枚举
C++的enum工具提供了另一种创建符号常量的方式,可以代替const ,同时允许定义新类型
在默认情况下,将整数值赋给枚举量,初始值为0,也可自定义
在不进行强制类型转换的情况下,只能将定义枚举时使用的枚举量赋给这种枚举的变量
如果打算只使用常量,而不创建枚举类型的变量,则可以省略枚举类型的名称
可以使用赋值运算符显示设置枚举量的值
可以只设置一部分,但都必须是整数,没有被初始化的枚举量都比前边大1
可以创建多个值相同的枚举量
可以使用int long long long
取值范围找到最大最小的2次幂 再减1 如果不小于0 最小值为0
4.7 指针和自由存储空间
对变量应用地址运算符(&),可以获得地址
程序清单4.14 address.cpp
// address.cpp -- using the & operator to find addresses
#include <iostream> //演示地址运算符用法
int main()
{
using namespace std;
int donuts = 6;
double cups = 4.5;
cout << "donuts value = " << donuts;
cout << " and donuts address = " << &donuts << endl;
cout << "cups value = " << cups;
cout << " and cups address = " << &cups << endl;
cin.get();
return 0;
}
指针用于存储值的地址,指针名是地址
*运算符被称为间接值或解除引用运算符,将其应用于指针,可以得到该地址处存储的值
程序清单4.15 pointer.cpp
// pointer.cpp -- our first pointer variable
#include <iostream> //演示指针代表含义
int main()
{
using namespace std;
int updates = 6;
int * p_updates; //声明指针
p_updates = &updates; //指针指向updates的地址
cout << "Values: updates = " << updates;
cout << ", *p_updates = " << *p_updates << endl;
cout << "Addresses: &updates = " << &updates;
cout << ", p_updates = " << p_updates << endl;
*p_updates = *p_updates + 1; //所在地址的值加1
cout << "Now updates = " << updates << endl;
cin.get();
return 0;
}
中间空格可选,对于每个指针变量,都需要一个*
程序清单 4.16 init_ptr.cpp
// init_ptr.cpp -- initialize a pointer
#include <iostream> //演示将指针初始化为一个地址
int main()
{
using namespace std;
int higgens = 5;
int * pt = &higgens; //将地址给声明的指针
cout << "Value of higgens = " << higgens
<< "; Address of higgens = " << &higgens << endl;
cout << "Value of *pt = " << *pt
<< "; Value of pt = " << pt << endl;
cin.get();
return 0;
}
C++创建指针时,计算机将分配用来存储地址的内存,但不会分配用来存储指针所指向的数据的内存
为数据提供内存是一个独立的步骤
在对指针应用解除引用运算符(*)之前,将指针初始化为一个确定的、适当的地址
指针不是整型,整数执行运算的数字,指针指向地址
要将数字值作为地址来使用,应通过强制类型转换将数字转换为适当的地址类型 pt = (int * ) 0xB8000000
C语言中,用库函数malloc()来分配内存,在C++中仍然可以这样做,C++也可以用new运算符
为一个数据对象(可以是结构,也可以是基本类型)获得并指定分配内存的通用格式如下:
typeName * pointer_name = new typeName;
程序清单 4.17 use_new.cpp
// use_new.cpp -- using the new operator
#include <iostream> //演示如何将new用于两种不同的类型
int main()
{
using namespace std;
int nights = 1001;
int * pt = new int;
*pt = 1001;
cout << "nights value = ";
cout << nights << ": location " << &nights << endl;
cout << "int ";
cout << "value = " << *pt << ": location = " << pt << endl;
double * pd = new double;
*pd = 10000001.0;
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;
}
new分配的内存块通常与常规变量声明分配的内存块不同,前边是栈,后边是堆或自由存储区
C++提供检测并处理内存分配失败的工具,将指针值为0,空指针
使用delete释放用new分配的内存,不能释放声明变量所获得的内存
对空指针使用delete是安全的
delete不用于new的指针,用于new的内存
一般来说,不要创建两个指向同一个内存块的指针,因为这样增加错误地删除同一个内存块两次的可能性
在编译时给数组分配内存被称为静态联编,意味着数组实在编译时加入到程序中的
使用new,如果运行阶段需要数组,就创建,不需要,不创建,在程序运行中选择数组长度,被称为动态联编和动态数组
静态联编编写程序时指定数组长度,动态联编长须在运行时确定数组长度
new创建动态数组 int * psome = new int [10]; 释放分配的内存块 delete [] psome; 方括号告诉程序应该释放整个数组
不能使用sizeof()运算符来确定动态分配的数组包含的字节数
为数组分配内存的通用格式如下:
type_name * pointer_name = new type_name [num_elements];
可以用数组名的方式来使用
程序清单 4.18 arraynew.cpp
// arraynew.cpp -- using the new operator for arrays
#include <iostream> //演示用数组名的方式来使用动态数组
int main()
{
using namespace std;
double * p3 = new double [3];
p3[0] = 0.2;
p3[1] = 0.5;
p3[2] = 0.8;
cout << "p3[1] is " << p3[1] << ".\n";
p3 = p3 - 1;
cout << "Now p3[0] is " << p3[0] << " and ";
cout << "p3[1] is " << p3[1] << ".\n";
p3 = p3 - 1;
delete [] p3;
cin.get();
return 0;
}
不能修改数组名的值,但指针是变量,可以修改指针的值
4.8 指针、数组和指针算法
C++将数组名解释为地址
程序清单4.19 addpntrs.cpp
// addpntrs.cpp -- pointer addition
#include <iostream>
int main()
{
using namespace std;
double wages[3] = {10000.0, 20000.0, 30000.0}; //新建数组
short stacks[3] = {3, 2, 1};
double * pw = wages; //数组的地址,其实也就是指向数组第一个数
short * ps = &stacks[0]; //数组第一个数的地址
cout << "pw = " << pw << " , *pw = " << *pw << endl; //输出pw 和*pw
//输出的是pw 指针 地址 *pw 数组第一个值
pw = pw + 1; //做运算,是序号增加
cout << "add 1 to the pw pointer:\n";
cout << "pw = " << pw << " , *pw = " << *pw << "\n\n";
cout << "ps = " << ps << " , *ps = " << *ps << endl;
ps = ps + 1;
cout << "add 1 to the pw pointer:\n"; //序号增加
cout << "ps = " << ps << " , *ps = " << *ps << "\n\n";
cout << "access two elements with array notation\n";
cout << "stacks[0] = " << stacks[0]
<< ", stacks[1] = " << stacks[1] << endl;
cout << sizeof(wages) << " = size of wages array\n";
cout << sizeof(pw) << " = size of pw pointer\n";
cin.get();
return 0;
}
对数组应用sizeof运算符得到的是数组的长度,而对指针应用sizeof得到的是指针的长度,即使指针指向的是一个数组
数组的地址看的不太明白 P109
使用头文件cstring中的两个函数 strlen()和strcpy()
程序清单4.20 ptrstr.cpp
// ptrstr.cpp -- using pointers to strings
#include <iostream> //演示如何使用不同形式的字符串
#include <cstring> //加载函数头文件 调用strlen() strcpy()
int main() //主函数
{
using namespace std; //啊
char animal[20] = "bear"; //声明一个数组 长度20 初始化为字符串"bear" 是地址
const char * bird = "wren"; //将char指针初始化为指向一个字符串"wren" "wren"实际表示的是字符串的地址 可以像处理字符串处理指针
char * ps; //声明了个指针
cout << animal << " and "; //输出的是数组的地址
cout << bird << "\n"; //bird是指针的地址,指针的地址是 "wren"
cout << "Enter a kind of animal: "; //
cin >> animal; //输入一个新的字符串 不能用字符串代替,有些编译器将字符串字面值视为只读常量,如果试图修改他们,将导致运行阶段错误
ps = animal; //把animal赋给ps,只是复制了地址,两个指针都指向相同内存空间和字符串
cout << ps << "!\n"; //打印ps的地址,是新输入的字符串
cout << "Before using strcpy():\n"; //演示使用了复制
cout << animal << " at " << (int * ) animal << endl; //如果给cout提供一个指针,它将打印地址,但如果指针的类型为char*
cout << ps << " at " << (int * ) ps << endl; //则cout将显示指向的字符串。如果要显示的是字符串地址,则必须强制转换,如(int *)
//指针的地址是字符串,字符串本身也有地址
ps = new char[strlen(animal) + 1]; //如果想复制,需要分配内存空间,并且求字符串长度正好分配合适的长度
strcpy(ps, animal); //使用函数复制
cout << "After using strcpy():\n";
cout << animal << " at " << (int *) animal << endl;
cout << ps << " at " << (int *) ps << endl; //再看字符串的地址,已经是新的地址了
delete [] ps; //虽然一开始ps没有[] ,但是从animal继承,释放时需要加上
cin.get();
cin.get();
return 0;
}
strcpy()函数接受两个参数,第一个是目标参数,第二个是要复制的字符串的地址
在运行时创建数组优于在编译时创建数组,对于结构也是如此
将new用于结构由两步组成:创建结构和访问访问其成员
运算符-> 用于指向结构的指针,点运算符用于结构名 一种方式 ps->price 另一种方式 (*ps).price
程序清单4.21 newstrct.cpp
// newstrct.cpp -- using new with a structure
#include <iostream> //演示结构 各用法
struct inflatable //定义结构
{
char name[20];
float volume;
double price;
};
int main()
{
using namespace std;
inflatable * ps = new inflatable; //运行时创建结构,分配内存,并赋给一个指针
cout << "Enter name of inflatable item: ";
cin.get(ps->name, 20); //指针方式输入
cout << "Enter volume in cubic feet: ";
cin >> (*ps).volume; //运算符句点输入
cout << "Enter price:$";
cin >> ps->price; //指针
cout << "Name: " << (*ps).name << endl;
cout << "Volume: " << ps->volume << " cubic feet\n";
cout << "Price: $" << ps->price << endl;
delete ps;
cin.get();
cin.get();
cin.get();
return 0;
}
使用new和delete的示例
程序清单4.22 delete.cpp
// delete.cpp -- using the delete operator
#include <iostream> //演示delete的用法
#include <cstring>
using namespace std;
char * getname(void); //声明一个函数
int main()
{
char * name; //指针
name = getname(); //返回值地址给了name指针,指向分配的内存块
cout << name << " at " << (int *) name << "\n"; //程序打印该字符串和地址
delete [] name; //释放name指向的内存块后
name = getname(); //再次调用
cout << name << " at " << (int *) name << "\n";
delete [] name;
cin.get();
cin.get();
return 0;
}
char * getname()
{
char temp[80]; //定义数组
cout << "Enter last name: ";
cin >> temp; //将输入单词放到temp数组
char * pn = new char[strlen(temp) + 1]; //然后使用new分配内存,指向pn 定义需要的长度
strcpy(pn, temp); //然后函数用cstring中的strcpy复制数组中的值到新的内存中
return pn; //返回了一个正合适的内存 这是字符串副本的地址
}
getname()函数,使用cin将输入的单词放到temp数组中,然后使用new分配新内存
C++不保证新释放的内存就是下一次使用new是选择的内存
C++有3种管理数据内存的方式:自动存储、静态存储和动态存储(有时也叫作自由存储空间或堆)
自动存储是局部变量,在栈中先进后出
静态存储是整个程序执行期间都存在的存储方式
使变量称为静态的方式有两种:一种是在函数外面定义它,另一种是在声明变量时使用关键字static static double fee = 56.50;
new和delete通过管理内存池,不受程序或函数的生存时间控制
4.9 类型组合
创建结构后,1.可以创建这种类型的变量 2.可以使用成员运算符访问其成员 3.可以创建指向这种结构的指针
4.指针设置为有效地址后,就可以使用间接成员运算符来访问成员 5.可以创建结构数组 6.使用成员运算符访问元素的成员
P119 对数组的一些概念运用的组合
程序清单4.23 mixtypes.cpp
// mixtypes.cpp -- some type combinations
#include <iostream>
struct antarctica_years_end
{
int year;
};
int main()
{
antarctica_years_end s01, s02, s03; //结构定义了三个变量
s01.year = 1998; //第一个变量的year赋值1998
antarctica_years_end * pa = &s02; //第二个变量地址指向pa
pa ->year = 1999; //pa地址的变量的year赋值1999
antarctica_years_end trio[3]; //结构创建数组trio
trio[0].year = 2003; //数组的第一个变量的year赋值2003
std::cout << trio->year << std::endl; //输出trio的year s03
const antarctica_years_end * arp[3] = {&s01, &s02, &s03}; //赋值一个新的数组
std::cout << arp[1]->year << std::endl; //输出该数组的第二个数 也就是s02
const antarctica_years_end ** ppa = arp;
auto ppb = arp;
std::cout << (*ppa)->year << std::endl;
std::cout << (*(ppb+1))->year << std::endl;
return 0;
}
有问题 跑不出来
4.10 数组的替代品
模板类vector类似于string类,也是一种动态数组,可以在运行阶段设置vector的长度
要用vector,必须包含头文件vector #include <vector>
创建方法 vector<typeName> vt(n_elem);
模板类array 长度固定,使用栈(静态内存分配),需要包含头文件array
声明 array<typeName, n_elem> arr; n_elem不能使变量
// choices.cpp -- array variations 不..不支持??? 11么
#include <iostream>
#include <vector>
#include <array>
int main()
{
using namespace std;
double al[4] = {1.2, 2.4, 3.6, 4.8};
vector<double> a2(4);
a2[0] = 1.0/3.0;
a2[1] = 1.0/5.0;
a2[2] = 1.0/7.0;
a2[3] = 1.0/9.0;
array<double, 4> a3 = {3.14, 2.72, 1.62, 1.41}; //找不到array
array<double, 4> a4;
a4 = a3;
cout << "a1[2]: " << a1[2] << " at " << &a1[2] << endl;
cout << "a2[2]: " << a2[2] << " at " << &a2[2] << endl;
cout << "a3[2]: " << a3[2] << " at " << &a3[2] << endl;
cout << "a4[2]: " << a4[2] << " at " << &a4[2] << endl;
a1[-2] = 20.2;
cout << "a1[-2]: " << a1[-2] << " at " << &a1[-2] << endl;
cout << "a3[2]: " << a3[2] << " at " << &a3[2] << endl;
cout << "a4[2]: " << a4[2] << " at " << &a4[2] << endl;
cin.get();
return 0;
}
4.13 编程练习
1. 编写一个C++程序,如下述输出示例所示的那样请求并显示信息:
What is your first name? Beety Sue
What is your last name? Yewe
What letter grade do you deserve? B
What is your age? 22
Name: Yewe, Betty Sue
Grade: C
Age: 22
注意,该程序应该接受的名字包含多个单词。另外,程序将向下调整成绩,即向上调一个字母。假设用户请求A、B或C,所以不必担心D和F之间的空档 。
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << "What is your first name? ";
string s1;
getline(cin, s1);
cout << "What is your last name? ";
string s2;
getline(cin, s2);
cout << "What letter grade do you deserve? ";
char c;
cin >> c;
cout << "What is your age? ";
int i;
cin >> i;
cout << "Name: " << s2 << ", " << s1 << endl;
cout << "Grade: " << char(c + 1) << endl;
cout << "Age: " << i << endl;
cin.get();
cin.get();
return 0;
}
2. 修改程序清单4.4,使用C++ string类而不是char数组。
#include <iostream>
#include <string>
int main()
{
using namespace std;
string s1, s2;
cout << "Enter your name:" << endl;
getline(cin, s1);
cout << "Enter your favorite dessert:" << endl;
getline(cin, s2);
cout << "I have some delicious " << s2;
cout << " for you, " << s1 << ".\n";
cin.get();
cin.get();
return 0;
}
3. 编写一个程序,它要求用户首先输入其名,然后输入其姓;然后程序使用一个逗号和空格将姓和名组合起来,并存储和显示组合结果。请使用char数组和头文件cstring中的函数。下面是该程序运行时的情形:
Enter your first name: Flip
Enter your last name: Fleming
Here's the information in a single string: Fleming , Flip
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
cout << "Enter your first name: " << endl;
char f_name[20];
gets(f_name);
cout << "Enter your last name: " << endl;
char l_name[20];
gets(l_name);
cout << "Here's the information in a single string: " << f_name
<< ", " << l_name << endl;
cin.get();
cin.get();
return 0;
}
4. 编写一个程序,它要求用户首先输入其名,再输入其姓;然后程序使用一个逗号和空格将姓和名组合起来,并存储和显示组合结果。请使用string对象和头文件string中的函数。下面是该程序运行时的情形:
Enter your first name: Flip
Enter your last name: Fleming
Here's the information in a single string: Fleming, Flip
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << "Enter your first name: " << endl;
string f_name;
getline(cin, f_name);
cout << "Enter your last name: " << endl;
string l_name;
getline(cin, l_name);
cout << "Here's the information in a single string: " << f_name
<< ", " << l_name << endl;
cin.get();
cin.get();
return 0;
}
5. 结构CandyBar包含3个成员。第一个成员存储了糖块的品牌;第二个成员存储糖块的重量(可以有小数);第三个成员存储了糖块的卡路里含量(整数)。请编写一个程序,声明这个结构,创建一个名为snack的CandyBar变量,并将其成员分别初始化为“Mocha Munch"、2.3和350。初始化应在声明snack时进行。最后,程序显示snack变量的内容。
#include <iostream>
#include <string>
using namespace std;
struct CandyBar{
string name;
double weight;
int cal;
};
int main()
{
CandyBar snack = {
"Mocha Munch",
2.3,
350
};
cout << snack.name << endl;
cout << snack.weight << endl;
cout << snack.cal << endl;
cin.get();
return 0;
}