4.4  从语句到程序

了解了各种表达式和语句之后,就相当于掌握了写作文要用到的词语和句子,但是,仅有词语和句子是无法构成一篇有意义的文章的。要完成一篇文章,先需要确定这篇文章的结构,是先分述再总述,还是逐层递进论述。定好结构后再按照结构的要求将词语和句子安排到合适的位置,这样才能写出一篇有意义的词句通顺的文章。编写程序就像写文章一样,也同样需要先根据需要处理的事务确定程序的流程控制结构,然后再将那些零散的语句串联起来描述一个完整的处理事务的过程,从而将多条零散的语句组织成可以完成一定功能的完整程序。

4.4.1  用三种流程控制结构将多条语句串联成程序

按照处理事务的流程的不同,C++中主要有下面三种程序流程控制结构:

1. 顺序结构

顺序结构是C++中最简单也最常用的一种流程控制结构。这种结构在执行的时候,它按照从上往下的顺序,依次逐条执行程序的语句。在整个过程中,执行顺序不会发生改变。所以,它通常被用来组织那些只需要一步步顺序执行就可以完成任务的语句。比如,一个简单的加法计算过程,从输入到计算再到输出,只需要依次顺序执行就可以完成,所以我们使用顺序结构来将那些分别负责输入(cin>>a>>b;)、计算(int c = a + b;)和输出(cout<<a<<" + "<<b<<" = "<<c<<endl;)的语句组织起来,就成了一个简单的加法计算程序:

// 顺序结构组织的加法计算程序
int main()
{ cout<<"请输入两个整数:"<<endl; int a,b;
cin>>a>>b; // 输入
int c = a + b; // 计算
cout<<a<<" + "<<b<<" = "<<c<<endl; // 输出 return ;
}

在执行的时候,从进入main()函数开始,首先执行输入语句(cin>>a>>b;),获得用户输入的两个数值a和b,然后依次往下执行计算语句(int c = a + b;),获得计算结果并保存到变量c,接下来执行输出语句(cout<<a<<" + "<<b<<" = "<<c<<endl;),将计算结果输出。这样,使用顺序结构组织的各条语句,只需要顺序执行就可以完成任务。

2. 选择结构

现实世界是复杂的,很多问题并不是只用顺序步骤就可以解决。还是以上面的求两个数之和的程序为例,如果要求输入的数必须大于0,也就是只有大于0的两个数才能计算它们的和。这时就需要先判断输入的数是否大于0,如果满足条件,就计算两个数的和;如果不满足,就提示用户输入的数不满足条件,无法计算。为了表达这种根据不同条件拥有不同处理方法的过程,C++提供了选择结构。选择结构依靠if等条件语句来实现,它可以根据不同条件做出判断,选择不同的执行路径,实现不同的处理过程。例如:

// 用选择结构实现的加法计算程序
int a,b;
cin>>a>>b; // 选择结构,根据条件不同,执行的路径也不同
if( a > && b > )
{
// 如果用户输入的数据满足条件,
// 则计算结果并输出
int c = a + b;
cout<<a<<" + "<<b<<" = "<<c<<endl;
}
else
{
// 如果用户输入的数据不满足条件,
// 则提示用户输入错误
cout<<"请输入两个大于0的数。"<<endl;
}

利用选择结构,我们将对满足条件的情况进行处理的语句组织到if分支,将对不满足条件的情况进行处理的语句组织到else分支,这样程序在执行的时候,就会根据满足条件与否而执行不同的代码,实现了对“根据不同条件拥有不同处理方法”的表达。

3. 循环结构

再来看另外一种更复杂的情形:要求输入100个数后计算它们的总和。如果采用前面介绍的顺序结构,那么就要定义100个变量,用到100个输入语句来接收数据,同时也需要100个加和语句来将它们加到总和中。这么繁琐的计算过程显然是无法接受的,那么有什么方法可以简化一下这个计算过程呢?

人们发现这类计算过程有一个规律:这个计算过程中的多次输入和加和计算的代码是相似的,输入都是从cin获取输入数据到某个变量,而加和计算也都是将输入的数据累加到一个表示总和的变量上。正因为如此,在完成一次输入和加和计算后,可以利用相同的代码完成第二次输入和加和计算。这样,整个计算过程就成了一个输入和加和计算不断重复循环往复的过程。为了表达这一类的计算过程,C++提供了循环结构。循环结构依靠for等循环语句来实现,我们将那些需要重复多次执行的语句作为循环体语句,从而可以在循环过程中得到重复多次执行,以此来表达那些同一动作需要反复执行的计算过程。 在这里,负责输入(cin>>n;)和加和计算(nTotal += n;)的语句是需要重复多次执行的,所以我们将它作为for循环的循环体语句,然后在for循环中确定循环的起点和终点,以此串联成一个可以输入并计算100个数之和的程序:

// 用循环结构实现的连续加法计算程序
// 表示总和的变量
int nTotal = ; // for循环实现的循环结构
for(int i = ; i < ; ++i)
{
int n = ;
cin>>n; // 输入语句
nTotal += n; // 加和计算语句
} // 输出结果
cout<<"你输入的100个数的总和是:"<<nTotal<<endl;

在执行for循环的时候,会连续100次地执行循环体中的输入语句和加和计算语句,这样就省掉了使用顺序结构可能带来的繁琐,很好地表达了“某个动作需要反复多次执行”的计算过程。

顺序结构、选择结构和循环结构是三种最基本的程序控制结构。这三种结构不仅可以单独使用,更多时候,我们是将多种控制结构组合使用,以此来表达那些更加复杂的计算过程。例如在上面的例子中,如果我们只想要计算输入的所有正数的和,我们就可以在循环结构中嵌入一个选择结构,用循环结构来组织那些需要反复多次执行的动作,而每次循环执行的时候,都先用选择结构对数据进行筛选,只有符合条件的数才进行加和计算。循环结构和选择结构的嵌套就可以表达这一更加复杂的计算过程:

// 循环结构和选择结构的嵌套使用
// 循环结构,执行重复动作
for(int i = ; i < ; ++i)
{
int n = ;
cin>>n;
// 选择结构,筛选数据,对符合条件的数据进行计算
if( n > )
{
nTotal += n;
}
}

通过这三种控制结构的组合,几乎可以描述任何复杂的程序执行流程。换句话说,也就是无论什么样的程序执行流程,无外乎是这三种结构或这三种结构的组合。而正是这三种控制结构将零散的实现简单操作的语句组织起来,表达一定的运算过程,最终才形成了实现一定功能的程序。

4.4.2 工资程序成长记:用数组处理批量数据,用循环结构执行重复动作

刚看过《你好,C++!》的前面几个章节,我们的“程序员”小陈就觉得自己的C++已经掌握得很不错了。很快,他就应聘到了一家软件公司做了一名程序员。

上班第一天,老板就给他分配了一个“大”任务:

“小陈啊,今天虽然是你上班的第一天,但公司现在有个大任务需要你去完成。你知道的,我们公司也是一个拥有近100000名员工的大公司。现在需要一个程序来对员工的工资进行统计和查询。统计就是需要知道所有员工的最低工资、最高工资和平均工资。查询就是需要可以根据员工的序号查询得到员工的工资。你的C++水平那么高,完成这样一个工资程序应该没有问题吧?”

“没,没,一点问题都没。”

小陈越听越心惊,到目前为止,虽然看过几天《你好,C++!》,但他还从来没有写过如此复杂的C++程序,心中实在没底,只好先答应下来,然后再回去看书想办法。等到小陈将《你好,C++!》再次仔细地看过一遍后,他惊喜地发现,要完成这个工资程序所需要的知识在书中早有论述:要对多个相同性质的批量数据(将近100000个工资数据)进行管理,可以采用数组;要多次重复执行某个动作(输入和查询工资数据),可以使用循环结构来组织语句;要根据不同条件执行不同的动作(如果输入特殊的数值-1,表示工资查询结束;如果输入的序号超出序号范围,提示用户重新输入;如果输入的序号在序号范围内,输出相应序号员工的工资),可以使用选择结构来实现不同的程序执行路径。经过简单的分析,小陈发现这个程序从整体而言是一个顺序结构:先输入数据,然后对数据进行查询;而每一个步骤又是一个循环结构:利用for循环多次输入数据,利用while循环多次查询数据;同时在循环结构中,又会嵌套选择结构,根据用户输入的不同执行不同的动作。按照这样的分析结果,小陈很快有了下面的工资程序:

// 工资程序 V1.0
#include <iostream>
#include <climits> // 为了使用整数最值宏INT_MAX,INT_MIN using namespace std; int main()
{
// 定义数组的最大数据元素量,
// 表示这个程序最多可以处理100000个工资数据
const int MAX = ;
// 定义数组并初始化,这个数组可以包含100000个int类型工资数据
int arrSalary[MAX] = {}; // 定义记录工资总值、最小值和最大值的变量
// 因为min和max用于记录最小值和最大值,
// 所以我们分别将其初始化为int类型数据的最大值和最小值
int nTotal = ;
int min = INT_MAX;
int max = INT_MIN; // 输入的有效工资数据个数,计算平均工资和查询工资时需要
int nCount = ;
// 利用for循环结构,重复执行输入动作,完成多个工资数据的输入
for(int i = ; i < MAX; ++i)
{
// 提示用户输入
cout<<"请输入"<<i<<"号员工的工资(-1表示输入结束):"<<endl;
// 将输入的数据保存到arrSalary数组的第i个数据元素
cin>>arrSalary[i]; // 利用条件结构,检查是否输入了表示结束的特殊值
if(- == arrSalary[i] )
{
// 输入结束,输出统计结果
cout<<"工资输入结束,一共输入了"<<nCount<<"个工资数据。"<<endl;
// 如果输入的数据个数不为0,输出统计信息
if( != nCount)
{
cout<<"其中,"<<endl;
cout<<"最大值是"<<max<<endl;
cout<<"最小值是"<<min<<endl;
// 计算平均工资
float fAver = (float)nTotal/nCount;
cout<<"平均工资是"<<fAver<<endl;
}
// 输入结束,用break关键字结束整个输入循环
break;
} // 如果是正常输入,则进行常规处理
++nCount; // 工资数据个数加1
// 累加工资总额
nTotal += arrSalary[i];
// 更新工资的最大值和最小值
if(arrSalary[i] < min) // 如果新输入的数值比已知的最小值min小
min = arrSalary[i];// 用新输入的值取代旧的最小值
if(arrSalary[i] > max) // 最大值相似处理
max = arrSalary[i];
} // 输入过程结束,开始查询过程
// 如果数据个数为0,表示没有输入数据,不再进行查询而直接结束
if( == nCount)
{
cout<<"没有工资数据,无法进行查询。感谢使用!"<<endl;
return ; // 直接结束程序
} // 拥有工资数据,构造无限循环进行工资查询,在循环中根据条件退出循环
while(true)
{
// 输入的员工序号
int n = ;
// 提示用户输入
cout<<"请输入要查询的员工序号(0-"<<nCount-
<<",-1表示结束查询):"<<endl; // 获取用户输入的员工序号并保存到n
cin>>n;
// 对用户输入进行检查
if(- == n) // 是否输入了表示结束的特殊值
{
// 查询结束,用break关键字结束整个查询循环
cout<<"查询完毕,感谢使用!"<<endl;
break;
}
else if(n < || n >= nCount) // 是否超出序号范围
{
// 提示用户输入错误
cout<<"输入的序号"<<n<<"超出了序号范围0-"
<<nCount-<<",请重新输入。"<<endl;
// 输入的序号超出范围, 用continue结束本次循环,开始下一次循环
continue;
} // 输入合法,输出用户查询的员工工资
cout<<"员工序号:"<<n<<endl;
// 这里用输入的员工序号作为数组下标,直接得到对应位置上的工资数据
cout<<"员工工资:"<<arrSalary[n]<<endl;
} return ;
}

在简单试用几次之后,小陈对这个工资程序还算满意。于是他赶紧把这个程序拿去向老板交差。老板试了试发现,这个工资程序不仅能够处理足够多的工资数据,能够对工资数据进行统计和查询,同时还有非常好的用户操作提示,连三岁小孩子都会用。老板非常高兴,喜笑颜开地对小陈说:“干得不错,下个月,涨工资,啊哈哈哈…… ”听到这句话,小陈在心里乐开了花,心中暗想,辛亏手头有一本《你好,C++!》,问题才能够如此顺利地被解决。看来这真是一本好学又好用的C++参考书,下班回去之后一定接着往下看……

你好,C++(23) 4.4.2 工资程序成长记:用数组处理批量数据,用循环结构执行重复动作的更多相关文章

  1. 你好,C++(38)从问题描述中发现对象的属性和行为 6.4 工资程序成长记:类与对象(上)

    6.4  工资程序成长记:类与对象 “夜半三更哟,盼天明:寒冬腊月哟,盼春风.若要盼得哟,涨工资,岭上……”自从上次老板许诺给小陈涨工资以后,一转眼又过去几个月了,可是涨工资的事一点动静都没有.小陈只 ...

  2. 你好,C++(30)“大事化小,小事化了”5.4.3 工资程序成长记:函数

    5.4.3 工资程序成长记:函数 自从上次小陈“程序员”的工资程序得到老板的夸奖,口头许诺给他涨工资以后,老板再也没有找过他,涨工资的事自然也就没有下文了.这天,老板又突然召他去办公室.这下可把小陈高 ...

  3. 微信小程序 setData动态设置数组中的数据

    setdata传递动态数据值必须为对象(只能是key:value) 语法如下 this.setData({ filter: 1212 }) 如果setdata要传递数组呢? 首先相到的是 this.s ...

  4. 使用程序获取整型数据和浮点型数据在内存中的表示---gyy整理

    使用程序获取整型数据和浮点型数据在内存中的表示. C++中整型(int).短整型(short int).单精度浮点数(float).双精度浮点数(double)在内存中所占字节数不同,因此取值范围也不 ...

  5. LINQ To SQL在N层应用程序中的CUD操作、批量删除、批量更新

    原文:LINQ To SQL在N层应用程序中的CUD操作.批量删除.批量更新 0. 说明 Linq to Sql,以下简称L2S.    以下文中所指的两层和三层结构,分别如下图所示: 准确的说,这里 ...

  6. 微信小程序-展示后台传来的json格式数据

    昨天粗粗的写了下后台数据传到微信小程序显示,用来熟悉这个过程,适合刚入门学习案例: 需了解的技术:javaSE,C3p0,jdbcTemplate,fastjson,html,javaScript,c ...

  7. java里的分支语句--程序运行流程的分类(顺序结构,分支结构,循环结构)

    JAVA里面的程序运行流程分三大类: 1,顺序结构:顺序结构就是依次执行每一行代码 2,分支结构:分支结构就是按不同的条件进行分支 3,循环结构:一段代码依条件进行循环执行. 其中,分支结构有两大类: ...

  8. 黑马程序员——JAVA基础之程序控制流结构之循环结构,循环嵌套

    ------- android培训.java培训.期待与您交流! ---------- 循环结构: 代表语句:while ,do while ,for while语句格式 : while(条件表达式) ...

  9. 与众不同 windows phone (28) - Feature(特性)之手机方向, 本地化, 应用程序的试用体验, 系统主题资源, 本地数据的加密解密

    原文:与众不同 windows phone (28) - Feature(特性)之手机方向, 本地化, 应用程序的试用体验, 系统主题资源, 本地数据的加密解密 [索引页][源码下载] 与众不同 wi ...

随机推荐

  1. spring获取properties

    实际项目中,通常将一些可配置的定制信息放到属性文件中(如数据库连接信息,邮件发送配置信息等),便于统一配置管理.例中将需配置的属性信息放在属性文件/WEB-INF/configInfo.propert ...

  2. HTTP 代理原理及实现

    本文转载自 https://imququ.com/post/web-proxy.html HTTP 代理原理及实现(一) 文章目录 普通代理 隧道代理 Web 代理是一种存在于网络中间的实体,提供各式 ...

  3. Win7主题被禁用

    今天早上干了一件傻缺的事,打开电脑的时候,某卫士提醒开机速度击败全国0.2%的电脑,之后点了优化...随后就发生了接下来的一幕: win7下面的主题都不能使用了,只能使用那种复古(很丑的样式,看着很不 ...

  4. 【java】基于Tomcat的WebSocket转帖 + 自己理解

    网址:http://redstarofsleep.iteye.com/blog/1488639 原帖时间是2012-5-8,自己书写时间是2013年6月21日10:39:06 Java代码 packa ...

  5. fpdf使用標楷體

    <? require('chinese-unicode.php'); $pdf=new PDF_Unicode(); $pdf->Open(); $pdf->AddPage(); $ ...

  6. activitie用户手册

    最近公司开发流程,学习流程开发,不停看api学习.这是做软件的额...不停的学习学习!!!天天进步中! 用户手册地址:http://www.mossle.com/docs/activiti/#acti ...

  7. Centos6.5 qt 安装

    1,centos linux系统必须预先以安装x Server(KDE or GNOME) 2,wget http://download.qt-project.org/official_release ...

  8. bzoj3574[Hnoi2014]抄卡组

    http://www.lydsy.com/JudgeOnline/problem.php?id=3574 我们发现如果所有的字符串都有*,那么只需要比较他们的“前缀”和“后缀”相同即可.“前缀”指第一 ...

  9. 将多个图片整合到一张图片中再用CSS 进行网页背景定位

    原文地址:http://wenku.baidu.com/link?url=hj_qM9kmdMrg8KWXFD2bCF_uuJCxKJRvG97CkWk3itsPq3izMzfrKvSZYBzDGyP ...

  10. freemarker对数字的处理

    freemark会默认对数字进行格式化处理,例如price = 12000,  通过${price}显示为12,000,  但其实有些场景会有问题: 比如编辑一条记录, 再保存,容易将12,000传到 ...