题解:ybt1207:求最大公约数问题
1207:求最大公约数问题
时间限制: 1000 ms 内存限制: 65536 KB
【题目描述】
给定两个正整数,求它们的最大公约数。
【输入】
输入一行,包含两个正整数(<1,000,000,000)。
【输出】
输出一个正整数,即这两个正整数的最大公约数。
【输入样例】
6 9
【输出样例】
3
【来源】
ybt1207
这道题的一般解法是在main()函数里面用while循环来解决,代码一般是这样的:
#include <iostream> using namespace std; int main() { int m,n,c,r; cin>>m>>n; r=m%n; while(r!=0) { m=n; n=r; r=m%n; } cout<<n; return 0; }
但这种方法,唯一的缺点是:不能重复使用。如果在好几处地方都要用到最大公约数,我们要在每一处都复制粘贴吗?那未免也太麻烦了,
十分降低程序的效率,所以我们要用一种全新的方式来编写,那就是"函数"。
函数这种功能,我们先来介绍一下:
main就是一个函数,它是C++程序的主函数。一个C++程序可以由一个主函数和若干子函数组成。主函数是程序执行的开始点。由主函数调用子函数,子函数还可以再调用其它子函数。
调用其它函数的函数称为主调函数。被其他函数调用的函数称为被调函数。一个函数很可能既调用别的函数又被其它函数调用。
1.函数的定义
1.1函数定义的语法形式
类型说明符 函数名(含类型说明的形式参数表)
{
语句序列
}
1.2形式参数
类型标识符1 形参名1,类型标识符2 形参名2,···,类型标识符n 形参名n
形参的作用是实现主调函数与被调函数之间的联系。通常将函数所处理的数据、影响函数功能的因素或者函数的处理结果作为形参。
如果一个函数的形参表为空,则表示它没有任何形参。main函数可以没有形参,也可以有形参,其形参也称命令行参数,由操作系统在启动程序时初始化。
函数在没有被调用时是静止的,此时的形参只是一个符号,它标志着在形参出现的位置应该有一个什么类型的数据。
函数在被调用时才执行,也就是在被调用时才由主调函数将实际参数赋予形参。
1.3函数的返回值和返回值类型
函数可以有一个返回值,函数的返回值是需要返回给主调函数的处理结果。类型说明符规定了函数返回值的类型,函数的返回值由return语句给出,格式如下:
return 表达式;
除了指定函数的返回值外,return语句还有一个作用,就是结束当前函数的执行。
一个函数也可以不讲任何值返回给主调函数,这时它的类型标识符为void,可以不写return语句,但也可以写一个不带表达式的return语句,用于结束当前函数的调用,格式如下:
return;
2.1函数的调用形式
变量在使用之前需要首先声明,类似的,函数在调用之前也需要声明。函数的定义就属于函数的声明,因此,在定义了一个函数之后,可以直接调用这个函数。但如果希望在定义一个函数之前调用它,则需要在调用函数之前添加该函数的函数原型声明。函数原型声明的形式如下:
类型说明符 函数名(含类型说明的形参表);
与变量的声明和定义类似,声明一个函数只是将函数的有关信息告诉编译器,此时并不产生任何代码;定义一个函数是除了同样要给出函数的有关信息外,主要是要写出函数的代码。
声明了函数原型之后,便可以按如下形式调用子函数:
函数名(实参列表);
实参列表应该给出与函数原型形参个数相同、类型相符的实参,每个实参都是一个表达式。函数调用可以作为一条语句,这时函数可以没有返回值。函数调用也可以出现在表达式中,这时就必须有一个明确的返回值。
2.2嵌套调用
函数允许嵌套调用。如果函数1调用了函数2,函数2再调用函数3,便形成了函数的嵌套调用
2.3递归调用
函数可以直接或间接地调用自身,称为递归调用。
所谓直接调用自身,就是指在一个函数的函数体中出现了对自身的调用表达式。
递归算法的实质是将原有的问题分解成新的问题,而解决新问题时又用到了原有问题的解法。按照这一原则分解下去,每次出现的新问题都是原有问题的简化的子集,而最终分解出来的问题,是一个已知解的问题。这便是有限的递归调用。只有有限的递归调用才是有意义的,无限的递归调用永远得不到解,没有实际意义。
递归的过程有如下两个阶段。
第一阶段:递推。将原问题不断分解为新的子问题,逐渐从未知向已知推进,最终达到已知的条件,即递归结束的条件,这时递推阶段结束。
第二阶段:回归。从已知的条件出发,按照递推的逆过程,逐一求值回归,最后达到递推的开始处,结束回归阶段,完成递归调用。
3.函数的参数传递
在函数未被调用时,函数的形参并不占有实际的内存空间,也没有实际的值。只有在函数被调用时才为形参分配存储单元,并将实参与形参结合。每个实参都是一个表达式,其类型必须与形参相符。函数的参数传递指的就是形参与实参结合(简称形实结合)的过程,形实结合的方式有值传递和引用传递。
3.1值传递
值传递是指当发生函数调用时,给形参分配内存空间,并用实参来初始化形参(直接将实参的值传递给形参)。这一过程是参数值的单项传递过程,一旦形参获得了值便与实参脱离关系,此后无论形参发生了怎样的改变,都不会影响到实参。
2.引用传递
值传递时参数是单向传递。
引用是一种特殊类型的变量,可以被认为是另一个变量的别名,通过引用名与通过被引用的变量名访问变量的效果是一样的。
使用引用时必须注意以下问题:
·声明一个引用时,必须同时对它进行初始化,使它指向一个已存在的对象。44
·一旦一个引用被初始化后,就不能改为指向其它对象。
也就是说,一个引用,从它诞生时,就必须确定是哪个变量的别名,而且始终只能作为作为这一个变量的别名,不能另作他用。
引用也可以作为形参,如果将引用作为形参,情况便稍有不同。这是因为,形参的初始化不在类型说明时进行,而是在执行主调函数中的调用表达式时,才为形参分配内存空间,同时用实参初始化形参。这样引用类型的形参就通过形实结合,成为了实参的一个别名,对形参的任何操作也就会直接作用于实参。
用引用作为形参,在函数调用时发生的参数传递,称为引用传递。
回到题目,使用函数和不使用函数的求最大公约数的方法是一样的,只不过添加了实参和形参
#include <iostream> using namespace std; int gcd(int x,int y); int main() { int m,n; cin>>m>>n; cout<<gcd(m,n); return 0; } int gcd(int x,int y) { int r; r=x%y; while(r!=0) { x=y; y=r; r=x%y; } return y; }
再次提醒:如果把函数定义在main()函数后面,前面需要先声明函数,如果不声明,会编译错误!!!!