C++流程控制语句中主要分两大块:选择语句(if语句和switch语句)和循环语句(while语句、do-while语句和for语句)。
if语句和循环语句太简单,就不啰嗦了。直接进入switch语句,在进行判断选择的时候,有可能每次都是对同一个表达式的值进行判断,那么就没有必要在每一个嵌套的if语句里都计算一下它的值,而是使用switch来解决这个问题。语法形式为:
switch (表达式)
{
case 常量表达式1: 语句1
case 常量表达式2: 语句2
……
case 常量表达式n: 语句n
default: 语句n+1
}
此类语句的执行顺序是,先计算表达式的值,然后在case语句中寻找与之相等的常量表达式,跳到此处开始执行,若没有与之相等的则跳到default开始执行。使用switch语句时要注意以下几点:这些常量表达式的值不能相同,顺序可以随便;每个case语句的最后最好加break语句,不然会一直把下面所有的语句执行完;switch括号里的表达式必须是整型、字符型和枚举型的一种;每个case下的语句不需要加{};如果多个case下执行一样的操作,则多个case可以共用一组语句,比如
case 1:
case 2:
case3: a++;
break;
虽然说每个case语句之后加上一句break;比较好,但是也有例外的时候,如下案例指导
案例指导:根据输入的月份计算出从年初到本月底的天数
代码注解
#include
<iostream>
using
namespace std;
int main()
{
int year,month,days = 0;
cout <<"Input year and month:";
cin>>year>>month;
switch(month)
{
case 12 : days += 31;
case 11 : days += 30;
case 10 : days += 31;
case 9 : days += 30;
case 8 : days += 31;
case 7 : days += 31;
case 6 : days += 30;
case 5 : days += 31;
case 4 : days += 30;
case 3 : days += 31;
case 2 :
if(((0 == (year%4))&&(0 != year%100))||(0 ==year%400))
days += 29;
else
days += 28;
case 1 : days += 31;
}
if(0 == days)
cout<<"Wrong month "<<endl;
else
cout<<"Total days is :"<<days<<endl;
return (0);
}
思考与提高
这里使用不带break的case语句,刚好依次累加各月的天数。case分支中的if语句是用来判断用户输入的年份是否是闰年。某年是闰年的条件是:该年能够被4整除但是不能被100整除,或者能够被400整除。所以是否需要加入break语句 还是按具体情况来分析,不要不加分析地直接加上break语句。另外在循环中经常用过两个函数exit()函数和abort()函数。exit()函数和abort()函数是C++语言中的库函数,作用都是终止整个程序的运行,将控制权返还给系统。为了能够使用这两个函数,必须在程序头添加头文件<cstdlib>.
像char、int、float等数据类型,这些都是C++内置的基本数据类型,但这些数据类型还不能完全满足实际编程的需求,需要我们自己定义一些数据类型使用。自定义数据类型有:枚举类型、结构类型、联合类型、数组类型和类类型等。
类型定义语句typedef的语法形式
typedef 已有类型名
新类型名表
[注]使用类型定义语句typedef并不能创建一种新的数据类型,只是为一个已经存在的类型定义一个新的名字。类型定义主要是为了改善程序的可读性和简化程序的书写。
枚举类型的声明形式
enum 枚举类型名{变量值列表};
结构体声明形式
struct 结构体名
{
数据类型 成员名 1;
数据类型 成员名 2;
……
数据类型 成员名 n;
};
结构体类型变量声明的语法形式
结构名 结构体变量名;
结构体成员的引用形式
结构体变量名.成员名
联合体声明的语法形式
union 联合名
{
数据类型 成员名 1;
数据类型 成员名 2;
……
数据类型
成员名 n;
};
联合体的变量声明和成员的引用和结构体一样。
下面来深入理解枚举类型、结构体类型和联合类型
1.枚举类型
在现实当中经常遇到这种情况,描述一件事情时只能取几个有限的值,比如,一周只有星期一、星期二...星期日七天,比赛结果只有胜、负、平和比赛取消等四种结果。我们可以用0到6的整数表示星期一到星期日,7,8,9等都不是合法数据,如果我们用整数来表示星期几那就需要专门判断下是不是在0到6之间,但是如果用枚举类型定义就没有这种问题,因为枚举类型就那几个可能的值。
枚举类型的声明形式为: enum
枚举类型名 {
变量值列表 };
变量值列表里都是整型变量,另外不要忘记最后面的分号!
比如,enum weekday { sun,mon,tue,wed,thu,fri,sat };
这里的枚举元素sun、mon...都没有指定值,它们就使用默认值,依次为0,1,2...。即sun就是0,mon就是1,...sat是6。也可以在声明枚举类型时指定枚举元素的值,比如enum
weekday { sun=7, mon=1,tue, wed, thu, fri, sat };
这里sun就是7,mon是1,后面的值在mon的基础上依次加1,即tue等于2,wed为3...sat是6。枚举元素按常量处理,不能对它们赋值除了声明的时候,像sun=0;这样的语句就是非法的。
枚举类型我们声明了以后就能像int、float等类型那样用了,可以定义枚举类型的变量。整数值需要赋给枚举变量时,应进行强制类型转换。
例如:设某次体育比赛的结果有四种可能:胜(win)、负(lose)、平局(tie)、比赛取消(cancel),编写程序顺序输出这四种情况。分析:由于比赛结果只有四种可能,所以可以声明一个枚举类型,声明一个枚举类型的变量来存放比赛结果。
#include<iostream>
using namespace std;
enum game_result {WIN, LOSE, TIE, CANCEL};
int _tmain(int argc, _TCHAR* argv[])
{
game_result result; //
声明变量时,可以不写关键字enum
enum game_result omit =CANCEL; //
也可以在类型名前写上关键字enum
int count;
for (count = WIN ; count <= CANCEL ; count++)
{
result = (game_result)count;
if (result == omit)
{
cout << "The game was cancelled\n";
}
else
{
cout<< "The game was played ";
if(result == WIN)
cout << "and we won!";
if (result == LOSE)
cout << "and we lost.";
cout << "\n";
}
}
return 0;
}
运行结果是:
The game was played and we won!
The game was played and we lost.
Thegame was played
The game was cancelled
2.结构体
有时候我们需要将一些不同类型的数据组合成一个整体,例如,一个学生的学号、姓名、年龄和成绩等,它们数据类型不同,但都属于一个人。这就要用到结构体。一个学生的结构体可以定义成如下形式:
structstudent //学生信息结构体
{
int num; //学号
char name[20]; //姓名
char sex; //性别
int age; //年龄
float score; //成绩
char addr[30]; //住址
};
定义了结构体类型,我们就可以用它来定义结构体变量,就像int a;那样。结构体型变量的定义形式也类似int等类型:
结构体类型名
结构体变量名;。比如,定义一个上面的那个结构体变量,student s;。可以像这样声明了结构体类型以后再定义结构体变量,也可以把它们放在一起。结构体变量占用内存的大小可以用sizeof(结构体类型名或变量名)计算。在定义结构体变量时可以直接赋初值。结构体成员的使用形式是:结构体变量名.成员名。
3.联合体
有的时候需要几个不同类型的变量共用一组内存单元,这时就需要用联合体。
例如:
union uarea
{
char c_data;
short s_data;
long l_data;
}
联合体类型在内存中是怎样占用内存单元的呢?联合体占用的内存大小是其占内存最大的成员需要的内存大小,就像上边的uarea,它占用的内存大小就是最大成员long需要的4个字节。联合体里同时只能放一个成员的值。uarea放c_data时c_data占用第一个字节,放s_data时s_data占用前两个字节,放l_data时l_data占用全部的4个字节。
联合体也可以没有名称,叫做无名联合体。无名联合体只是声明一个成员项的集合,这些成员有相同的内存地址,可以用成员项的名字直接访问。
例如:
union
{
int i;
float f;
}
在程序中可以直接用成员项i和f的名字访问i和f,比如i=2;
f=3.2;
例如:
#include <iostream>
using namespace std;
unionmyun
{
int k;
struct { int x; int y; int z; }u;
}a;
int _tmain(int argc, _TCHAR* argv[])
{
a.u.x=4;
a.u.y=5;
a.u.z =6;
a.k = 0;
cout<<a.u.x<<" "<<a.u.y<<""<<a.u.z<<" ";
return 0;
}
这个程序输出0 56。为什么呢?不应该是4,5,6吗?
因为联合体的成员共用内存,所以a.u.x占用的内存里的4被后来的a.k覆盖了,变成了0。
综合案例指导:百钱买百鸡
案例说明
公鸡一只值5钱,母鸡一只值3钱,三只小鸡值1钱,现有100钱,需买100鸡,问公鸡,母鸡和小鸡各多少只?
案例解析
分别用i ,j ,k 表示公鸡、母鸡和小鸡的数量,采用穷举法找出满足条件
(n == 5*i +3*j + k / 3)&&(0 == k % 3)&&(n== i + j + k)的所有组合。
代码解析
#include
<iostream>
#include
<iomanip>
using
namespace std;
int main()
{
int n = 100;
cout<<setw(3)<<"公鸡"<<setw(6)<<"母鸡"<<setw(6)<<"小鸡"<<endl;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
for(int k = 1; k <= n; k++)
if((n == 5*i + 3*j + k /3)&&(0 == k%3)&&(n== i + j + k))
cout<<setw(3)<<i<<setw(5)<<j<<setw(5)<<k<<endl;
return (0);
}
运行与调试
公鸡
母鸡
小鸡
4 18 78
8 11 81
12 4 84