第3章 基本控制结构
在程序设计语言中控制结构用于指明程序的执行流程。C++语言提供的基本控制结构包括\(3\)种类型:
(1)顺序结构:按照先后顺序依次执行程序中的语句。
(2)选择结构:按照给定条件有选择地执行程序中的语句。
(3)循环结构:按照给定规则重复地执行程序中的语句。
本章对实现C++程序基本控制结构的各种相关语句进行详细的介绍。
C++语句
语句是C++程序中的基本功能单元。任何一条C++语句都会为完成某项任务而进行相关操作。就像自然语言中的句子以句号结束一样,C++语句通常以分号作为结束标志。例如,在表达式i+5
的后面添加分号,使其变为
i+5;
就构成了一条合法的C++语句。
C++语句按照不同功能大体分为\(6\)种类型,它们是:
(1)声明语句:用于对程序中的各种实体进行声明、定义及初始化。只中面
(2)表达式语句:用于对程序中的数据进行具体操作和处理。
(3)选择语句:用于实现程序的选择结构。
(4)循环语句:用于实现程序的循环结构。
(5)跳转语句:用于实现程序执行流程的转移。
(6)复合语句:用于表示程序中的语句块。
应当指出的是,C++中并不存在赋值语句和函数调用语句,赋值和函数调用都属于表达式而不是语句。
顺序结构
顺序结构是C++程序中执行流程的默认结构。在一个没有选择和循环结构的程序中,语句将按照书写的先后顺序,从左向右,自上而下依次执行。除了选择、循环和跳转语句外,其他C++语句都可以看作实现程序顺序结构的语句。
声明语句
声明语句又称为说明语句,它可以用来对程序中出现的各种名称进行声明。这些名称通常是表示变量、常量、函数、结构、类、对象等实体的标识符。在C++程序中,一个名称在使用之前必须先被声明。声明的目的是告诉编译器某个名称所指代的实体类型。使用声明语句能够在程序中进行如下操作:
(1)变量声明,例如:
char ch; //声明和定义char型变量
int count=1; //声明、定义和初始化int型变量
extern int error_num; //声明int型变量
(2)常量声明,例如:
const int MAX_LEN =128; //声明、定义和初始化int型常量
const double pi = 3.14159; //声明、定义和初始化 double型常量
(3)函数声明,例如:
double sqrt(double); //声明函数
int max(int a,int b){ return a>b?a:b; } //声明和定义函数
(4)类型声明,例如:
typedef unsigned int ID; //声明和定义类型
enum Color{ RED,GREEN,BLUE }; //声明和定义枚举
struct Date{ int y,m,d; }; //声明和定义结构
class Employee; //声明类
声明语句可以完成的工作不仅仅局限于为名称指定类型,上述大多数声明语句同时也是定义语句。所谓定义,就是对某个名称所指代的实体进行具体描述。例如,与变量ch
对应的实体是内存中用来存储一个字符型数据的空间;与常量pi
对应的实体是一个double
型数值\(3.14159\);与函数max
对应的实体是函数体内的代码;与结构Date
对应的实体是一个新的结构类型。在上面的声明语句中只有
extern int error_num;
double sqrt(double);
class Employee;
是单纯的名称声明而没有进行实体定义工作。因此,与名称error_num
,sqrt
和Employee
对应的实体必须在程序中其他地方被定义,即int
型变量error_num
的内存空间必须由另外的声明语句分配;函数sqrt
的代码必须由另外的声明语句给出;类Employee
的具体结构也必须由另外的声明语句描述。例如:
int error_num = 1; //int型变量 error_num的定义
double sqrt(double){ /*函数 sqrt的代码 */ }
class Employee { /* 类 Employee的具体定义 */ };
C++语言规定:一个实体的定义只能出现一次,而其声明却可以出现多次。同一实体的多个声明必须在类型上保持一致。下面的声明语句中含有两处错误:
int count;
int count; //错误:count被重复定义
extern int error_num;
extern long error_num; //错误:error_num两次声明类型不一致
而在下面的声明语句则没有错误:
extern int error_num;
extern int error_num; //对error_num声明两次且类型一致
另外,使用声明语句还可以在定义变量时对其进行初始化。例如,声明语句int count=1;
不仅为int
型变量count
分配了合适的内存空间,而且还将这块空间所表示的数值初始化为\(1\)。
将声明(包括定义)作为一种语句处理是C++对C语言的语法进行的扩充。在C++中,声明语句可以出现在任何其他语句能够出现的地方,因此能做到在需要使用某个变量的恰当位置对其进行声明、定义及初始化,给程序员带来了很大的方便。
表达式语句
C++中所有对数据的操作和处理工作都是通过表达式语句来完成的。表达式语句的语法格式为:
<表达式>;
也就是说,在任何合法的C++表达式后面添加一个分号便构成了一条表达式语句。
使用表达式语句可以进行的操作通常包括:
(1)赋值操作。例如:
count=5; //将count赋值为5
i=1,j=2;//将i,j分别赋值为1,2
a=b+c; //将b+c的值赋给a
a=b=c; //先将c的值赋给b,再将b的值赋给a
(2)复合赋值操作。例如:
a+=9; //将a+9的值赋给a
b*=c; //将b*c的值赋给b
(3)增量、减量操作。例如:
i++; //将i增1
--j; //将j减1
(4)函数调用操作。例如:
abs(x); //调用函数 abs
sqrt(9); //调用函数 sqrt
fun(a,b); //调用函数 fun
(5)输入输出操作。例如:
cout<<a+b; //输出a+b的值
cin>>i>>j; //输入数据到i,j
基本输入输出
一个程序通常会向用户输出一些信息,一般也会要求用户输入一些信息。c++程序的输入输出操作是通过标准库中的输入/输出流对象来完成的。
在头文件iostream
中定义了代表屏幕的标准输出流对象cout
和代表键盘的标准输入流对象cin
。cin
和cout
具有强大的输入输出功能和极为灵活的用法。在程序中使用cin
和 cout
之前,应首先加入预处理命令:#include<iostream>
,以包含标准头文件iostream
。
使用cout
进行数据输出操作的一般格式为:
cout << Expr;
这是一条表达式语句。其中,Expr
代表一个表达式;<<
称为插入运算符。整条语句的含义是:将表达式Expr
的值输出(显示)到屏幕上当前光标所在位置。例如,下面语句的执行结果是在屏幕的当前光标处显示数值\(5\)。
int a=5;
cout << a;
cout
在用法上的灵活性主要表现为:它可以用来对C++中所有的常用数据类型进行输出操作。例如:
long lvar=1000;
cout << lvar; //输出long型变量
double dvar=0.5;
cout << dvar; //输出 double型变量
cout<<10; //输出整型常量
cout<<'c'; //输出字符型常量
cout<<"This is a string.\n"; //输出字符串常量
cout
还允许在一条语句中连续使用插入运算符来输出多项数据。例如:
int i=5,j=10;
cout<<i<<j;
将变量i
和j
的值依次显示在屏幕上。应该注意的是,cout
并不会在数据项i
和j
之间加入任何分隔字符。这样,上述语句的输出结果将成为:
510
因此,为了方便用户阅读,程序员在使用cout
进行多项数据的输出时有必要加入一些分隔字符。常用的分隔字符有空格(字符常量)和水平制表(字符常量\t
)。例如,将上面的输出语句改为:
cout<<i<<' '<<j; //在i,j之间输出空格
则输出结果将变成:
5 10
使用水平制表符\t
可以将多项数据对齐显示到屏幕的不同区域(每个区域之间的距离通常为\(8\)个字符),例如:
cout<<"No.1"<<'\t'<<"No.2"<<'\t'<<"No.3"<<'\n';
cout<<"111"<<'\t'<<"222"<<'\t'<<"333"<<'\n';
将输出下面的结果:
No.1 No.2 No.3
111 222 333
C++中提供了两种进行换行输出的方法:
(1)使用换行字符\n
。
(2)使用输入/输出操作符endl
。
两者实现的功能完全相同,都是使随后的输出内容从新的一行开始显示。例如,语句
cout<<"My name is Jone.\n" //使用换行字符'\n'
<<"The ID is"<<endl<<2; //使用操作符 endl
的输出结果为:
My name is Jone.
The ID is
2
使用cin
进行数据输入操作的一般格式为:
cin>>Var;
这也是一条表达式语句。其中,Var
代表一个变量;>>
称为提取运算符。整条语句的含义是:程序将暂时中止执行,等待用户从键盘上输入一个数据。如果用户键人了一个有效的数据并按下了回车键,程序就将此数据保存到变量Var
中,并继续执行后续语句。例如,下面的语句要求用户为变量a
输入一个int
型数值:
int a;
cin >> a;
与cout
相同,cin
也可以用来对C++中所有的常用数据类型进行输入操作。例如:
long lvar;
cin >> lvar; //输入long型变量
double dvar;
cin >> dvar; //输入 double型变量
char ch;
cin >> ch; //输入字符型变量
char str[128]; //输入字符串(即字符数组)
cin >> str;
同样,cin
也允许在一条语句中连续使用提取运算符来输入多项数据。例如,语句
int i,j;
cin >> i >> j;
要求用户连续输入两个int
型数值,并将它们分别保存到变量i
和j
中。在进行多项数据的连续输入时,应键入空白字符(包括空格键,回车键和Tab键)将相邻的两项数据分隔开。例如,假设用户要为变量i
输入5
,为变量j
输入10
,则应该键入:
5<SP>10<CR>
其中,<SP>
表示空格键,<CR>
表示回车键。
注意:用户输入数据的类型必须与保存该数据的变量类型相匹配,否则将得到错误的结果。
例3.1
下面用一个完整的程序来演示 cin
和cout
的用法:
习题3
选择题
1.下列选项中属于C++语句的是____。
A);
B)a=17
C)i+5
D)cout<<'\n'
2.下列声明语句中没有起到定义作用的是____。
A)int count;
B)const double pi=3.14159;
C)in max(int a,int b){ return a>b ? a : b; }
D)extern long index;
3.下面程序的输出结果是____。
#include<iostream>
using namespace std;
int main()
{
int a=2,b=-1,c=2;
if(a<b)
if(b<0) c=0;
else c+=1;
cout<<c<<endl;
}
A)0
B)1
C)2
D)3
4.下列for
语句的循环次数为____。
for(int i=0,x=0;!x&&i<=5;++i);
A)\(5\)次
B)\(6\)次
C)\(7\)次
D)无穷次
5.下列语句段将输出字符'*'
的个数为____。
int i=100;
while(1)
{
i--;
if(i==0) break;
cout<<'*';
}
A)\(98\)个
B)\(99\)个
C)\(100\)个
D)\(101\)个
6.下面程序的输出结果是____。
#include<iostream>
using namespace std;
int main()
{
int s;
for(int k=2;k<6;k+=2)
{
s=1;
for(int j=k;j<6;++j) s+=j;
}
cout<<s<<endl;
return 0;
}
A)9
B)1
C)11
D)10
7.下面程序的输出结果是____。
#include<iostream>
using namespace std;
int main()
{
int n=10;
while(n>7)
{
n--;
cout<<n<<',';
}
cout<<endl;
return 0;
}
A)10,9,8,
B)9,8,7,
C)10,9,8,7,
D)9,8,7,6,
8.下列关于do...while
语句的叙述中,正确的是____。
A)do...while
语句所构成的循环不能用其他语句构成的循环来代替
B)do...while
语句所构成的循环只能用break
语句跳出
C)do...while
语句所构成的循环只有在while
后面的表达式非零时才结束
D)do...while
语句所构成的循环只有在while
后面的表达式为零时才结束
9.下面程序的输出结果是____。
#include<iostream>
using namespace std;
int main()
{
int x;
for(int i=1;i<=100;++i)
{
x=i;
if(++x%2==0)
if(++x%3==0)
if(++x%7==0)
cout<<x<<',';
}
cout<<endl;
return 0;
}
A)39,81,
B)42,84,
C)26,68,
D)28,70,
10.下列关于break
语句的叙述中,不正确的是____。
A)break
语句可用在循环体中,它将使执行流程跳出本层循环体
B)break
语句可用在switch
语句中,它将使执行流程跳出当前switch
语句
C)break
语句可用在if
语句中,它将使执行流程跳出当前if
语句
D)break
语句在一层循环体中可以出现多次
填空题
1.C++语言中用于控制程序执行流程的三种基本结构是 ____ 、 ____ 、 ____ 。
2.下面语句段的输出结果是____。
int x=0,y=2,z=3;
switch(x)
{
case 0: switch(y)
{
case 1: cout<<'*'; break;
case 2: cout<<'%'; break;
}
case 1: switch(z)
{
case 1: cout<<'$'; break;
case 2: cout<<'*'; break;
default: cout<<'#';
}
}
3.下面语句段的输出结果是____。
int k=1,n=10,m=1;
while(k<=n)
{
m*=2;
n--;
}
cout<<m<<endl;
4.当执行完下面语句段后,i
的值是 ____ 、j
的值是 ____ 、k
的值是 ____。
int a=10,b,c,d,i,j,k;
b=c=d=5;
i=j=k=0;
for(;a>b;++b) i++;
while(a>++c) j++;
do { k++; } while(a>d++);
5.将下面的语句断(a)补充完整,使其和语句段(b)在功能上完全等价:
(a)
double s=0.0;
________;
int k=0;
do
{
s+=d;
________;
d=1.0/(k*(k+1));
}while(________);
(b)
double s=1.0;
for(int k=1;k<=10;++k) s+=1.0(k*(k+1));
编程题
1.编写程序,实现输入一个整数,判断其能否被\(3,5,7\)整除,并输出以下信息之一:
(a)能同时被\(3,5,7\)整除;
(b)能被其中两个数(要输出是哪两个数)整除;
(c)不能被\(3,5,7\)中的任一个数整除。
2.编写程序,要求由用户输入任意三个实数,然后求出其中的最大值和最小值。
3.编写摄氏温度与华氏温度的换算程序。要求用户输入温度数值并指明该数值表示摄氏温度(C)还是华氏温度(F),程序将根据不同的输入(摄氏或华氏)进行不同的换算。例如,用户输入40.2C
,程序输出104.36F
,或用户输入104.36F
,程序输出40.2C
。
已知,换算公式为:摄氏温度\(=\frac{5}{9}(\)华氏温度\(-32)\)。
4.编写程序,求\(1-3+5-7+\cdots-99+101\)的值
5.编写程序,根据公式\(e=1+\frac{1}{1!}+\frac{1}{2!}+\frac{1}{3!}+\frac{1}{4!}+\cdots\)计算\(e\)的值。要求:
(a)使用for
循环,计算到公式的前\(50\)项。
(b)使用while
循环,直到公式最后一项的值小于\(10^{-4}\)为止。
6.编写程序,输出从公元\(1600\)年到公元\(2000\)年中所有闰年的年份。要求每行输出\(5\)个年份。判断公元年份是否为闰年的条件是:
(a)年份如能被\(4\)整除,而不能被\(100\)整除,则为闰年。
(b)年份如能被\(400\)整除也是闰年。
7.编写程序,求“水仙花数”。所谓“水仙花数”是指一个三位数,其各位数字的立方和等于该数本身。例如,\(153\)是水仙花数,因为\(1^3+5^3+3^3=153\)。
8.编写程序,求\(1000\)之内的所有“完全数”。所谓“完全数”是指一个数恰好等于其因子之和。例如,\(6\)是完全数,因为\(1+2+3=6\)。
9.使用迭代法变成求\(x=\sqrt a\)。求平方根的迭代公式为:
10.编写程序,使用循环语句打印如下图案:
*
***
*****
*******
*****
***
*
习题参考答案
选择题
1.A
2.D
3.C
4.B
5.B
6.D
7.B
8.D
9.D
10.C
填空题
1.顺序结构、选择结构、循环结构
2.%#
3.1024
4.5
、4
、6
5.
double d=1.0
++k
k<=10
编程题
1.完整代码如下:
#include<iostream>
using namespace std;
int main(){
bool f3=0,f5=0,f7=0;
int x; scanf("%d",&x);
if(x%3==0) f3=1;
if(x%5==0) f5=1;
if(x%7==0) f7=1;
if(f3&&f5&&f7)
printf("%d能同时被3,5,7整除\n",x);
else if(!f3&&!f5&&!f7)
printf("%d不能被3,5,7中的任一个数整除\n",x);
else {
if(f3&&f5) printf("%d能被其中两个数(3,5)整除\n",x);
if(f3&&f7) printf("%d能被其中两个数(3,7)整除\n",x);
if(f5&&f7) printf("%d能被其中两个数(5,7)整除\n",x);
}
return 0;
}
2.完整代码如下:
#include<iostream>
using namespace std;
int main(){
double x,y,z;
scanf("%lf %lf %lf",&x,&y,&z);
printf("%lf\n",max(x,max(y,z)));
printf("%lf\n",min(x,min(y,z)));
return 0;
}
3.完整代码如下:
#include<iostream>
using namespace std;
int main(){
double x; char ch;
scanf("%lf%c",&x,&ch);
if(ch=='C')
cout<<9.0*x/5.0+32<<'F'<<endl;
if(ch=='F')
cout<<5.0/9.0*(x-32)<<'C'<<endl;
return 0;
}
4.完整代码如下:
#include<iostream>
using namespace std;
int main(){
int f=1,ans=0;
for(int i=1;i<=101;i+=2){
ans+=i*f;
f*=-1;
}
printf("%d",ans);
return 0;
}
5.完整代码如下:
(a)
#include<iostream>
using namespace std;
int main(){
double e=1,res=1;
for(int i=1;i<=50;++i){
res*=i;
e+=1.0/res;
}
cout<<e;
return 0;
}
(b)
#include<iostream>
using namespace std;
int main(){
double e=1,x=1;
int cnt=1;
while((1.0/x)>=0.0001){
e+=1.0/x;
x*=++cnt;
}
cout<<e;
return 0;
}
6.完整代码如下:
#include<iostream>
using namespace std;
int main(){
int cnt=0;
for(int i=1600;i<=2000;++i)
if((i%4==0 && i%100!=0) || (i%400==0)){
printf("%d ",i);
if(++cnt==5){ cnt=0; puts(""); }
}
return 0;
}
7.完整代码如下:
#include<iostream>
using namespace std;
int main(){
for(int i=1;i<=9;++i)
for(int j=0;j<=9;++j)
for(int k=0;k<=9;++k)
if(i*i*i+j*j*j+k*k*k == i*100+j*10+k)
printf("%d\n",i*100+j*10+k);
return 0;
}
8.完整代码如下:
#include<iostream>
using namespace std;
int main(){
for(int i=1;i<=1000;++i){
int res=0;
for(int j=1;j<i;++j)
if(i%j==0) res+=j;
if(res==i) printf("%d\n",i);
}
return 0;
}
9.前后两次求出的x
的差的绝对值小于\(10^{-5}\),完整代码如下:
#include<iostream>
#include<cmath>
using namespace std;
int main(){
double a,xnow,xpre=0;
scanf("%lf",&a);
xnow=a/2.0;
while(fabs(xnow-xpre)>=0.00001){
xpre=xnow;
xnow=1.0/2.0*(xnow+a/xnow);
}
cout<<xnow;
return 0;
}
10.完整代码如下:
#include<iostream>
using namespace std;
int main(){
for(int i=1;i<=4;++i){
for(int j=4-i;j;--j) printf(" ");
for(int j=1;j<=i*2-1;++j) printf("*");
puts("");
}
for(int i=1;i<=3;++i){
for(int j=1;j<=i;++j) printf(" ");
for(int j=1;j<=(4-i)*2-1;++j) printf("*");
puts("");
}
return 0;
}