一、学习新知识
这一讲我们来学些几种普通的复合类型,但是我们要知道,类也是复合类型。
首先来看数组,C语言嚼烂的知识了,我们只看新特性。
几种初始化方数组方法:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
int arr1[4] = {3,6,8,10}; int arr2[] = {1,2,5,8}; int arr3[4] {1,3,6,9}; //可省略等号 int arr4[4] {}; //将所有元素设置为零
我们知道声明数组的一种方式是:
typeName arrayName[arraySize];
其中,表达式arraySize指定元素数目,它必须是整型常数或const值,也可以是常量表达式,即其中所有的值在编译时都是已知的。也就是说,arraySize不能是变量,因为变量的值是在程序运行时设置的。
但使用new运算符将避开这种限制。
假设要编写一个程序,它是否需要数组取决于运行时用户提供的信息。如果通过声明来创建数组,则在程序被编译时将为它分配内存空间,不管程序最终是否使用数组,数组都在那里,它占用了内存。
静态联编:在编译时给数组分配内存,即意味着数组是在编译时加入到程序中的;
动态联编:在运行阶段选择是否创建数组并且可以选择数组的长度。
使用new来创建动态数组:
//创建动态数组只需将数组的元素类型和元素数目告诉new即可 //必须在类型名后加上方括号,其中包含元素数目 int *p = new int[10]; //创建一个包含10个int元素的数组
new运算符返回第一个元素的地址,在这个例子中,该地址被赋给指针p。
p是指向一个int(数组第一个元素)的指针。我们需要跟踪内存块中的元素个数,也就是说,由于编译器不能对p是指向10个整数中的第一个这种情况进行跟踪,因此编写程序时,必须让程序跟踪元素的数目。
使用动态数组:
#include <iostream> using namespace std; int main() { double *p = new double [3]; p[0] = 0.2; p[1] = 0.5; p[2] = 0.8; cout<<"p[1] is "<<p[1]<<". "; p = p + 1; cout<<"Now p[0] is "<<p[0]<<" and p[1] is "<<p[1]<<". "; p = p - 1; delete [] p; //释放new分配的内存 return 0; }
运行结果为:
看完数组,再来看看结构。
结构是一种比数据更灵活的数据格式,因为同一个结构可以存储多种类型的数据,从而能够将数据的表示合并到一起。
我们要知道,结构也是C++OOP堡垒(类)的基石,学习有关结构的知识将使我们离C++的核心OOP更近。
结构是用户定义的类型,而结构声明定义了这种类型的数据属性。定义了类型后,便可以创建这种类型的变量。因此,创建结构包括两步:①定义结构描述;②按描述创建结构变量。
来看一段创建结构的程序:
#include <iostream> using namespace std; //结构声明 struct student{ char name[20]; //name成员是一个字符数组,可以初始化为一个字符串 int score; //将结构成员score看作还是int类型的变量 }; int main() { student stu1 = {"liuyu",98}; //创建结构类型student的变量stu1 student stu2 {"zhouning",18}; cout<<stu1.name<<"的得分是"<<stu1.score<<". "; cout<<stu2.name<<"的得分是"<<stu2.score<<". "; }
哈哈,上面这段程序只是结构的基本操作啊,我们来段猛的:
#include <iostream> using namespace std; //结构声明 struct student{ char name[20]; int score; }stu2; //同时定义结构和创建结构变量 int main() { student stu1 = {"liuyu",98}; stu2 = stu1; //进行结构间的赋值 cout<<stu1.name<<"的得分是"<<stu1.score<<". "; cout<<stu2.name<<"的得分是"<<stu2.score<<". "; //输出和上面一模一样 }
这些特征和我们学C时的结构差不多,但C++结构拥有更多的特性。例如,C++结构除了成员变量之外,还可以有成员函数。但这类高级特性往往被用于类中,而不是结构中。
【枚举】
之前学java也看过枚举了,当时没看懂,今天一定要弄懂!!!
C++的enum工具提供了另一种创建符号常量的方式,这种方式可以代替const。它还允许定义新类型,但必须按严格的限制进行。
使用enum的句法与使用结构相似,请看下面的语句:
enum spectrum{red,orange,yellow,green,blue,violet,indigo,ultraviolet};
这条语句完成两项工作:
- 让spectrum成为新类型的名称;spectrum被称为枚举(enumeration),就像struct变量被称为结构一样。
- 将red、orange、yellow等作为符号常量,它们将对应整数值0~7。这些常量叫作枚举量(enumerator)。
我们要知道,在默认情况下,将整数值赋给枚举量,第一个枚举量的值为0,第二个枚举量的值为1,依次类推。可以通过显式地指定整数值来覆盖默认值。
由上面的语句我们知道spectrum为枚举名,那么我们可以用枚举名来声明这种类型的变量:
specrtum band; //band是spectrum类型的变量
下面来看枚举变量的特性:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
enum spectrum{red,orange,yellow,green,blue,violet,indigo,ultraviolet}; specrtum band; //在不进行强制类型转换的情况下,只能讲定义枚举时使用的枚举量赋给这种枚举的变量 //即band只有8个可能的值 band = blue; band = 2000; //错误,2000不是一个枚举量 //枚举只定义了赋值运算符 band = orange; band = orange + red; //错误 //枚举量是整型,可被提升为int类型,但int类型不能自动转换为枚举类型 band = 3; //错误,虽然3对应的枚举量为green band = green; //正确 int color = blue; //spectrum type promoted to int color = 3 + red; //red被提升为int类型 //如果int值有效,则可以通过强制类型转换,将它赋给枚举变量 band = spectrum(3); //3在0-7之间
我们可以了解到枚举的规则相当严格,所以枚举更常被用来定义相关的符号常量,而不是新类型。
比如,我们可以用枚举来定义switch语句中使用的符号常量。
如果我们只使用常量,我们可以省略枚举类型的名称:
enum {red,orange,yellow,green,blue,violet,indigo,ultraviolet};
我们除了像上面那样由系统帮我们设置枚举量的值,我们也可以自己进行设置:
enum bits{one = 1,two = 2,four = 4,eight =8}; //只定义其中一些枚举量的值 enum bigstep{first,second = 0,third}; //first在默认情况下为0,可以创建多个值相同的枚举量,没有初始化的枚举量值比前面的大1
二、温故而知新
【编写一条语句,显示float数组ideas中的第二个元素的值。】
cout <<(float)ideas[1]<<endl;
【声明一个char数组,将其初始化为字符串“cheeseburger”。】
char a[20]="cheeseburger";
【设计一个描述鱼的结构声明。结构中应当包括品种、重量(整数,单位为盎司)和长度(英寸、包括小数)。】
struct fish{ string pinzhong; //品种名 int angsi; //重量,盎司,整数 double yingcun; //长度,英寸,浮点数 };
【声明一个问题3中定义的结构的变量,并对它进行初始化。】
fish liyu={"鲤鱼",5,2.2};
或
fish liyu; liyu.pinzhong = "鲤鱼"; liyu.angsi = 5; liyu.yingcun = 2.2;
【用enum定义一个名为Response的类型,他包括Yes,No和Maybe等枚举量,其中Yes的值为1,No为0,Maybe为2。】
enmu Response{Yes=1,No=0,Maybe=2};
【编写一段代码,要求用户输入一个正整数,然后创建一个动态的int数组,其中包含的元素数目等于用户输入的值。】
unsigned int a; cin >> a; int *b=new int[a];
【下面的代码是否有效?如果有效,他将打印出什么结果?】
有效。他会打印储存这个字符串常量的内存地址。
【编写一段代码,给问题3中描述的结构动态分配内存,再读取该结构的成员的值。】
fish *a=new fish; cout<<"依次输入鱼类的名字,重量(盎司,整数),长度(英寸,小数),以回车为结束。 " cin >> (*a).string; cin >> a->angsi; cin >> a->yingcun;
三、做做习题
1.编写一个C++程序,如下述输出示例所示的那样请求并显示信息:
What is your first name? Betty 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之间的空档。
答:代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> int main() { using namespace std; char first[20], last[20]; //声明first name和last name char grade; //声明成绩变量grade int age; //声明年龄变量age cout << "What is your first name? "; cin.getline(first, 20); //读取用户输入的一行字符给first cout << "What is your last name? "; cin.getline(last, 20); //读取用户输入的一行字符给last cout << "What letter grade do you deserve? "; cin >> grade; //读取用户输入的grade cout << "What is your age? "; cin >> age; //读取用户输入的年龄 cout << "Name: " << last << ", " << first << endl; //显示名字 cout << "Grade: " << char((int)grade + 1) << endl; //将用户输入的grade转为int类,然后+1就是下调成绩,再转为char类显示 cout << "Age: " << age << endl; //显示用户输入的年龄 cin.get(); //和下面起到暂停作用 cin.get(); return 0; }
2.编写一个程序,它要求用户首先输入其名,然后输入其姓;然后程序使用一个逗号和空格将姓和名组合起来,并存储和显示组合结果。请使用char数组和头文件cstring中的函数。下面是程序运行时的情形:
Enter your first name: Flip
Enter your last name: Fleming
Here's the information in a single string: Fleming, Flip
答:代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstring> int main() { using namespace std; char first[20], last[20]; //创建字符串first和last char middle[3] = ", "; //创建用于连接名字的间隔符,和空格 cout << "Enter your first name: "; cin.getline(first, 20); //要求用户输入名 cout << "Enter your last name: "; cin.getline(last, 20); //要求用户输入姓 const int a=strlen(first); //让常量a等于first的长度 const int b = strlen(last); //让常量b等于last的长度 char *name = new char[43]; //创建指针,用于将first和last还有中间的间隔符组合到一起 strcpy_s(name, b + 1, last); //将last的内容复制到指针name(所指向地址的字符串)中,注意,长度需要给空字符留一个位置 name = name + b; //指针偏移,偏移长度为last的长度,这样的话,就将空字符覆写掉了 strcpy_s(name, 3, middle); //将middle的内容复制到指针name中,同样留一个空字符位置 name = name + 2; //偏移指针,覆写空字符 strcpy_s(name,a+1, first); //将first内容复制到指针name中 name = name - b - 2; //将指针偏移回原来的位置 cout << "Here's the information in a single string: " << name << endl; //输出指针指向的地址 system("pause"); //用2个cin.get()就不会显示最后的 请按任意键继续. . . 但问题是,好像也没法复制输出的内容了 return 0; }
3.结构CandyBar包含3个成员。第一个成员存储了糖块的品牌;第二个成员存储糖块的重量(可以有小数);第三个成员存储了糖块的卡路里含量(整数)。请编写一个程序,声明这个结构,创建一个名为snack的CandyBar变量,并将其成员分别初始化为“Mocha Munch”、2.3和350。初始化应在声明snack时进行。最后,程序显示snack变量的内容。
答:代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<string> struct CandyBar { std::string pinpai; //品牌 double weight; //重量 int kaluli; //卡路里 }; int main() { using namespace std; CandyBar snack = { "Mocha Munch",2.3,350 }; //声明并初始化snack cout << snack.pinpai << "的重量为" << snack.weight << ",卡路里含量为:" << snack.kaluli << endl; system("Pause"); return 0; }
4.结构CandyBar包含3个成员,如编程练习3所示。请编写一个程序,创建一个包含3个元素的CandyBar数组,并将它们初始化为所选择的值,然后显示每个结构的内容。
答:代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<string> struct CandyBar { std::string pinpai; //品牌 double weight; //重量 int kaluli; //卡路里 }; int main() { using namespace std; CandyBar tang[3]; tang[0] = { "大白兔奶糖",3.3,200 }; tang[1] = { "小白兔奶糖",2.2,150 }; tang[2] = { "巧克力糖",4.2,300 }; cout << tang[0].pinpai << "的重量为" << tang[0].weight << ",卡路里含量为:" << tang[0].kaluli << endl; cout << tang[1].pinpai << "的重量为" << tang[1].weight << ",卡路里含量为:" << tang[1].kaluli << endl; cout << tang[2].pinpai << "的重量为" << tang[2].weight << ",卡路里含量为:" << tang[2].kaluli << endl; system("Pause"); return 0; }
5.William Wingate从事比萨饼分析服务。对于每个比萨饼,他都需要记录下列信息:
● 披萨饼公司的名称,可以由多个单词组成。
● 披萨饼的直径。
● 披萨饼的重量。
请设计一个能够储存这些信息的结构,并编写一个使用这种结构变量的程序。程序将请求用户输入上述信息,然后显示这些信息。请使用cin(或它的方法)和cout。
答:代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<string> struct pisa { std::string gs; //公司 double zj; //直径 int zl; //重量 }; int main() { using namespace std; cout << "这里可以帮你储存披萨饼的相关信息。 请输入披萨饼的公司名称: "; pisa a; getline(cin, a.gs); cout << "请输入披萨饼的直径(英寸): "; cin >> a.zj; cout << "请输入披萨饼的重量(克): "; cin >> a.zl; cout << a.gs << "的披萨饼,直径为" << a.zj << "英寸,重量为" << a.zl << "克。" << endl; system("Pause"); return 0; }
6.完成编程练习5,但使用new来为结构分配内存,而不是声明一个结构变量。另外,让程序在请求输入比萨饼公司名称之前输入比萨饼的直径。
答:代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<string> struct pisa { std::string gs; //公司 double zj; //直径 int zl; //重量 }; int main() { using namespace std; pisa *a = new pisa; //使用动态结构数组 cout << "这里可以帮你储存披萨饼的相关信息。" << endl; cout << "请输入披萨饼的直径(英寸): "; cin >> (*a).zj; cout<<"请输入披萨饼的公司名称: "; cin.get(); //读取掉换行符 getline(cin, a->gs); cout << "请输入披萨饼的重量(克): "; cin >> a->zl; cout << a->gs << "的披萨饼,直径为" << a->zj << "英寸,重量为" << a->zl << "克。" << endl; system("Pause"); return 0; }
7.完成编程练习4,但使用new来动态分配数组,而不是声明一个包含3个元素的CandyBar数组。
答:代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<string> struct CandyBar { std::string pinpai; //品牌 double weight; //重量 int kaluli; //卡路里 }; int main() { using namespace std; CandyBar *tang=new CandyBar[3]; tang[0] = { "大白兔奶糖",3.3,200 }; tang[1] = { "小白兔奶糖",2.2,150 }; tang[2] = { "巧克力糖",4.2,300 }; cout << tang[0].pinpai << "的重量为" << tang[0].weight << ",卡路里含量为:" << tang[0].kaluli << endl; cout << tang[1].pinpai << "的重量为" << tang[1].weight << ",卡路里含量为:" << tang[1].kaluli << endl; cout << tang[2].pinpai << "的重量为" << tang[2].weight << ",卡路里含量为:" << tang[2].kaluli << endl; system("Pause"); return 0; }
8.编写一个程序,让用户输入三次40码跑的成绩(如果您愿意,也可让用户输入40米跑的成绩),并显示次数和平均成绩。请使用一个array对象来存储数据(如果编译不支持array类,请使用数组)。
答:代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<array> int main() { using namespace std; const int b = 3; array<double, b>a; cout << "请输入三次四十米跑的成绩。 请输入第一次的成绩(秒): "; cin >> a[0]; cout << "请输入第二次的成绩(秒): "; cin >> a[1]; cout << "请输入第三次的成绩(秒): "; cin >> a[2]; cout << "您" << b << "次的成绩分别为:" << a[0] << "秒、" << a[1] << "秒、" << a[2] << "秒。 平均成绩为:" << (a[0] + a[1] + a[2]) / 3 << "秒。" << endl; system("pause"); return 0; }