2014秋C++ 第12周项目 C++函数新特征与递归函数

简介: 课程主页在http://blog.csdn.net/sxhelijian/article/details/39152703,课程资源在云学堂“贺老师课堂”同步展示,使用的帐号请到课程主页中查看。 【项目1- 阅读程序】阅读下列程序,写出程序的运行结果。上机时运行程序,与你的预期进行对照、理解。如果对运行结果和其背后的原理仍不理解,请通过单步执行的手段跟踪理解。(1)阅读下面两个有静态局部变量
课程主页在 http://blog.csdn.net/sxhelijian/article/details/39152703,课程资源在 云学堂“贺老师课堂”同步展示,使用的帐号请到课程主页中查看。 


【项目1- 阅读程序】阅读下列程序,写出程序的运行结果。上机时运行程序,与你的预期进行对照、理解。如果对运行结果和其背后的原理仍不理解,请通过单步执行的手段跟踪理解。
(1)阅读下面两个有静态局部变量的程序,阅读中画出其中各变量的变化过程,以掌握静态变量的存储特征,对照实际运行结果检验学习成果。必要时记得看书及课件。

#include <iostream>
using namespace std;
int f(int n);
int main()
{
    cout<<f(5)<<"  ";
    cout<<f(8)<<endl;
    return 0;
}
int f(int n)
{
    static int a=2;
    int b=0;
    a+=n;
    b+=a;
    return b;
}
预计运行结果是:__________________
实际运行结果是:__________________


#include <iostream>
using namespace std;
int func (int a,  int b)
{
    static int m=0, i=2;
    i+=m+1;
    m=i+a+b;
    return m;
}
int main()
{
    int k=4, m=1, p;
    p=func(k, m);
    cout<<p<<endl;
    p=func(k, m);
    cout<<p<<endl;
    return 0;
}
预计运行结果是:__________________
实际运行结果是:__________________


  (2)阅读下面两个有全局变量的程序,阅读中画出其中各变量的变化过程,以掌握全变量的存储特征,对照实际运行结果检验学习成果。必要时记得看书及课件。
#include <iostream>
using namespace std;
int  a=3, b=5;
int max(int a, int b)
{
    int c;
    c=a>b? a:b;
    return  c;
}
int main()
{
    int a=8; //若无这一句,又将如何?
    cout<<max(a,b)<<endl;
    return 0;
}
预计运行结果是:__________________
实际运行结果是:__________________

#include <iostream>
using namespace std;
void cude();
int main()
{
    extern int x;//去掉extern及本行全删除会怎样?
    x=5; //去掉这一句呢?
    cude();
    cout<<x<<endl;
    return 0;
}
int x=10;
void cude()
{
    x=x*x*x;
}
预计运行结果是:__________________
实际运行结果是:__________________

(3)阅读下面两个包含有递归函数的程序,要求按课堂演示,画出调用过程,并列出运行结果。对照实际运行结果检验学习成果。必要时记得看书及课件。
#include <iostream>
using namespace std;
void f(int);
int main()
{
    int i=1234;
    f(i);
    return 0;
}
void f(int n)
{
    if(n==0)
        return;
    else
    {
        f(n/10);
        cout<<n%10;
        return;
    }
}
预计运行结果是:__________________
实际运行结果是:__________________
#include <iostream>
using namespace std;
int sub(int);
int main()
{
   int i=5;
   cout<<sub(i)<<endl;
}
int sub(int n)
{
   int a;
   if (n==1)
	   return 1;
   a=n+sub(n-1);
   return a;
}
预计运行结果是:__________________
实际运行结果是:__________________ 
 
(4)理解函数的默认参数:运行程序,利用调试功能,观察变量和函数参数的值,结合课堂讲解,品味默认参数的作用。
#include <iostream>
using namespace std;
const double pi=3.1415926;
float area(float r=6.5);//指定r的默认值为6.5
float volume(float h,float r=6.5); //指定r的默认值为6.5
int main( )
{
    cout<<area()<<endl; //相当于area(6.5);
    cout<<area(7.5)<<endl; //形参得到的值为7.5,而不是6.5
    cout<<volume(45.6)<<endl; //相当于volume(45.6,6.5)
    cout<<volume(34.2,10.4)<<endl; //h的值为34.2,r的值为10.4
    return 0;
}
float area(float r)
{
    return pi*r*r;
}
float volume(float h,float r)
{
    return pi*r*r*h;
}
① 去掉第4行的“=6.5”试试,出错的原因是____________________;
② 将第14行改为“float area(float r=6.5)”,出错的原因是__________________;
③ 将第5行“float h,float r=6.5”改为“float h=1,float r”,出错的原因是_____________;
④ 将第5行改为“float volume(float h=0,float r=6.5)”,带来的改变将是____________________。

(5)理解函数模板:运行程序,结合课堂讲解,品味函数模板的意义。利用codeBlocks中的Debug功能,Step Into到函数内部,观察每次调用时函数的参数值,体会类型参数T每次调用时被不同实际类型替代。
#include <iostream>
using namespace std;
template<typename T>        //模板声明,其中T为类型参数
T max(T a,T b,T c)          //定义一个通用函数,用T作虚拟的类型名
{
    if(b>a) a=b;
    if(c>a) a=c;
    return a;
}
int main( )
{
    int i1=185,i2=-76,i3=567;
    double d1=56.87,d2=90.23,d3=-3214.78;
    long g1=67854,g2=-912456,g3=673456;
    cout<<"i_max="<<max(i1,i2,i3)<<endl; //调用模板函数,此时T被int取代
    cout<<"f_max="<<max(d1,d2,d3)<<endl; //调用模板函数,此时T被double取代
    cout<<"g_max="<<max(g1,g2,g3)<<endl; //调用模板函数,此时T被long取代
    cout<<"c_max="<<max('1','a','A')<<endl; //调用模板函数,此时T被long取代
    return 0;
}

提示1:在单步执行中,采用step into后,可以将T像待观察的变量一样,放在watch窗口中进行察看,如图所示,可以发现T取不同的类型。


提示2:若这个程序编译时出错,原因是命名空间std中已经定义过了max,从而产生了冲突。修改的方法有两种:(1)将程序中的max函数名改为mymax,避免这种冲突;或者(2)取消using namespace std;一行,但需要在程序中,将cout、cin、endl前加上std::,如std::cout<<...<<....<<std::endl;


【项目2-OJ平台题目中多种输入形式的处理】
看教学视频或“OJ平台题目中不同形式输入的处理”,完成平台中的一组题目,分别对应不同输入的形式的问题。

A: N组数的最大公约数

Description

计算一组数的最大公约数

Input

第一行是数据的组数N,从第二行是N组由两个整数(ab)构成的输入,ab之间用空格隔开,每组输入单独占一行

Output

每组的两个整数(ab)的最大 公约数,每个结果独占一行

Sample Input

3

98 72

80 36

12 144

Sample Output

2

4

12

  

B:分离正整数中的各位数

Description

输出正整数的各位数

Input

若干个用空格隔开的正整数(输入个数不确定,键盘输入时,以CTRL-Z结束)

Output

每个正整数的各位数字,个位数在前,十位数紧随,最高位在最后,每位数后面有一个空格。每个正整数对应的输出占一行。

Sample Input

123 9523 89

Sample Output

3 2 1 

3 2 5 9 

9 8

 

C:刑警的射击成绩

Description

刑警培训结束,进行了射击科检验。教官要对学员射击的成绩进行分析,得出各分数段人数统计。

Input

输入若干个0-10间的整数(最高10环,脱靶为0)表示成绩,人数不确定,输入以一个0-10以外的数作为。

Output

各分数段(A:9环以上,B:7环以上,C:5环以上,D:不足5环)的人数,每项成绩占一行

Sample Input

9 7 3 5 8 5 6 7 9 10 0 6 99

Sample Output

A:3

B:3

C:4

D:2


【项目3-用递归方法求解】
(1)编写递归函数求出n的阶乘(自定义main函数,调用定义的递归函数)
(2)写出求1*3*...*n的递归式,并编写出递归函数求解。
(3)编程序,用递归函数求出两个数的最大公约数。(包括编main函数,调用定义的递归函数)
(4)编制递归函数fib(int n)返回第n个Fibnacci数,以此输出Fibnacci序列的第20个数。
#include <iostream>
using namespace std;
int fib(int n);
int main(){
   cout<<fib(20)<<endl; //输出
   return 0;      
}
//返回Fibnacci序列中的第n个数
int fib(int n)
{ }
(5)输入一个整数n,要求输出对应的二进制形式,请用递归函数实现。
#include <iostream>
using namespace std;
int main()
{ 
 	int n;
	cout<<"请输入一个整数:";
	cin>>n;
	cout<<n<<"对应的二进制形式为:";
	dec2bin(n);  //输出n对应的二进制串
	cout<<endl;
	return 0;      
}
void dec2bin(int n)
{ }
提示:二进制整数n转换为二进制的方法是“除2取余法”,即将n除以2后得到的余数,由后到前“串”起来,得到对应的二进制数,如图。


(6)汉诺塔
汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。古代有一个梵塔,塔内有三个座A、B、C,A座上有64个盘子,盘子大小不等,大的在下,小的在上。有一个和尚想把这64个盘子从A座移到C座,但每次只能允许移动一个盘子,并且在移动过程中,3个座上的盘子始终保持大盘在下,小盘在上。在移动过程中可以利用B座,下面左图给出了移动方法的提示。请编制递归函数输出盘子数为4时(程序调试后,试试15个、20个,直至64个,看看会如何),移动的方案。图为盘子数为3时的输出供参考。

参考代码如下:
int main()
{ 
	move(4,'A','B','C');
	return 0;
}
//有n个盘子,
void move(int n, char A, char B,char C)
{
}

【项目4 - 银行系统】
这是我们要做的一个真正的项目!涉及到的技术都用过了,只不过,程序真的要长得多了。
  在学习中,总是想要些成就感的。当你没有做过一些事情的时候,总是不能知道所学知识究竟能干些什么。在学习过程中,完成一个像样的项目,那是一件很酷的事情,也让我们更有激情。做好思想准备,中间可能会有些困难,但相信沉下心来还是可以完成的。
  要做项目的需求最好能和大家的生活实践联系起来,我们想得到。另外,还能和我们的课程同步上。两厢结合,我们就开个银行,做个自动取款机吧。
  如果没有用过自动取款机,先用你的银行卡取一次钱去吧,权当作调研。
  我们首先插卡,输密码。做纯软件模拟,我们没有读卡机,好吧,认为卡已经插好了。
  为了让大家一点一点地做出来,我试图分解其中的工作,我们逐渐完善,“增量式”地完成工作。你可以每做完一个任务,就发一篇博文,将这样一个成长的阶段记录下来。
任务1——搭一个框架
  你的程序运行后的界面如图:
  
  • 用const定义全局的常变量PASSWORD,作为银行卡的密码(真银行卡的密码可不是这样,它要分别记住各个帐户的密码,我们现在认为所有卡都这个密码)。
  • 判断输入的密码是否正确,如果不正确,提示:“你这个笨脑瓜!”并退出程序,(注意,真银行可不敢骂人,你的银行这样写写无妨。)否则,继续下面的工作。
  • 用户如图输入功能选择,根据给出的答复,用switch多分支完成下面的显示:
    • a. 输入1,显示“您的余额是xxxx.xx元。”(想过瘾,用你觉得足够大的数当余额)
    • b. 输入2-4的提示自编;
    • c. 输入0,显示“谢谢,欢迎下次再来!”(好有礼貌)
    • d. 输入不是0-4,提示“输错,不要急!”
  只要输入不是0,循环处理业务。
  写完程序后,请将之发布为博文(程序中的注释自己加,程序前要有,中间也来些必要的)。


任务2——引入函数改善程序结构
  1、数据
  仍然只支持一位用户,所以用户帐号不必存储。
  要用全局变量存储:(1)用户密码(由于支持改密码功能,所以用变量,暂先用整型,声明时赋初值);(2)帐户余额(用浮点数表示,声明时赋初值)
  2、在输入密码环节,实现有限次密码输入的限制,如果三次都没有输入正确,程序将直接退出,不允许用户继续操作。
查验密码功能做成一个函数。例如:

bool pass()
{
  int 次数=0;
  bool 是否密码正确=false;   //先假设密码不正确,以便能进入do-while循环
  do{
    输入密码;
    次数++;
    if(相符)是否密码正确=true;
  }while(密码不正确且尝试次数不足3次);
  return 是否密码正确;  //上面密码正确为true,反之……
}
  3、main()函数的结构将如下所示,work函数用于处理业务。
main()
{
  ……
    if(pass())
        work();
    else
        输出“请到柜台办理密码查询后再来”。
    return 0;
}    
  4、办理业务的函数work的结构如下:
void work()
{
  //循环显示功能菜单:1.查询、2.取款、3.存款、4.转帐、5.改密、0.退出
  //选择后办理各种业务,再显示菜单,直到选择了0。
 
}
  其中,各项业务分别编制一个函数完成。提示功能菜单(1.查询、2.取款、3.存款、4.转帐、5.改密、0.退出)后,由用户输入功能选择,用switch多分支完成对应的功能(有的功能依然只输出一句话提示即可)。图示给出建议(鼓励在合理范围内别出心裁):

  • 输入1(查询),调用函数showbalance(),显示“您的余额是xxxx.xx元。”
  • 输入2(取款),调用drawmoney(),完成取款。要求输入取款金额,若余额不够,提示不能取款,否则,帐户余额减少。取款后给出提示:“你的余额还有XXX.XX元”。
    在实际业务中,还涉及到计算的问题。本题暂不考虑,作为拓展建议,可以在此处考虑计息。
  • 输入3(存款):调用deposit(),完成存款,余额增加(过瘾吧,想存多少存多少)。存款后给出提示:“你的余额是XXX.XX元”。
  • 输入4(转帐):调用transferAccounts(),完成转帐,只支持转出功能。要求输入对方帐号和转帐金额,若金额充足,完成转帐,当前帐户的余额减少,对方帐户余额增加。由于本题只有一个帐号,故对方帐户增加的操作先不做了。
  • 输入5(改密):调用updatePassword()改变密码。要求先输入旧密码,对了以后才能改密。新密码要输入两次,只有两次完全相同时才可以完成修改。
  • 输入0,显示“谢谢,欢迎下次再来!”退出循环,返回调用函数。
  • 输入不是0-5,提示“输错了,不要急!”
  以后我们再做支持多个帐户的银行系统。


任务3——将程序用多文件组织
  将任务2中的代码,涉及密码、帐户的函数放在一个文件中,完成各项功能的函数放在另一个文件中,main函放也单独一个文件。






============== 迂者 贺利坚 CSDN博客专栏=================

|== IT学子成长指导专栏 专栏文章的分类目录(不定期更新) ==|

|== C++ 课堂在线专栏  贺利坚课程教学链接(分课程年级) ==|
|== 我写的书——《逆袭大学——传给IT学子的正能量》    ==|
===== 为IT菜鸟起飞铺跑道,和学生一起享受快乐和激情的大学 =====
 
目录
相关文章
|
29天前
|
存储 并行计算 前端开发
【C++ 函数 基础教程 第五篇】C++深度解析:函数包裹与异步计算的艺术(二)
【C++ 函数 基础教程 第五篇】C++深度解析:函数包裹与异步计算的艺术
39 1
|
29天前
|
数据安全/隐私保护 C++ 容器
【C++ 函数 基础教程 第五篇】C++深度解析:函数包裹与异步计算的艺术(一)
【C++ 函数 基础教程 第五篇】C++深度解析:函数包裹与异步计算的艺术
46 0
|
12天前
|
存储 算法 Linux
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
32 6
|
11天前
|
编译器 C语言 C++
【C++初阶(九)】C++模版(初阶)----函数模版与类模版
【C++初阶(九)】C++模版(初阶)----函数模版与类模版
18 0
|
21天前
C/C++test两步完成CMake项目静态分析
通过将C/C++test集成到CMake项目中,并根据项目的需要进行配置,可以在两步内完成CMake项目的静态分析。这样可以帮助开发人员及时发现并修复潜在的代码问题,提高代码质量和可靠性。
8 0
|
22天前
|
存储 缓存 C++
C++链表常用的函数编写(增查删改)内附完整程序
C++链表常用的函数编写(增查删改)内附完整程序
|
24天前
|
存储 安全 编译器
【C++】类的六大默认成员函数及其特性(万字详解)
【C++】类的六大默认成员函数及其特性(万字详解)
35 3
|
26天前
|
安全 程序员 C++
【C++ 基本知识】现代C++内存管理:探究std::make_系列函数的力量
【C++ 基本知识】现代C++内存管理:探究std::make_系列函数的力量
101 0
|
27天前
|
设计模式 安全 C++
【C++ const 函数 的使用】C++ 中 const 成员函数与线程安全性:原理、案例与最佳实践
【C++ const 函数 的使用】C++ 中 const 成员函数与线程安全性:原理、案例与最佳实践
70 2
|
27天前
|
IDE 算法 编译器
快速掌握陌生C++项目的科学与心理学策略
快速掌握陌生C++项目的科学与心理学策略
57 0

热门文章

最新文章