(C++) 子例程:过程和函数 - 1


子程序
子程序是程序的一个独立部分,它有一个名字并解决它自己的独立任务。子程序位于主程序的开头,可以通过指定名称从主程序启动(调用)。

如果您需要在程序的不同位置编写相同的代码,则使用子例程可以避免代码重复。 
导入到程序中的库(例如,数学库 сmath.h)包含已经由某人编译的子例程。程序员不需要考虑他们实现了什么算法,而只是简单地应用它们,只考虑他们到底在做什么。这是一个很大的节省时间。没有必要去写别人已经写好的算法。

每个例程 应该只做一个任务, 要么只是计算一些东西,要么输出一些数据,要么做其他事情。 

子例程有两种类型 - 过程 函数

子程序执行一些动作,例如,将结果以某种形式显示在屏幕上(一个简单的例子,运算符printf() 是一个标准的子程序,将信息打印到屏幕上)

函数子程序返回一个结果(数字、字符串等),我们可以在主程序中使用。

让我们尝试编写一个简单的程序:
假设我们要显示字符串“Error”;每次由于用户的错误(例如,当他输入不正确的数据)而导致代码中出现错误时
这可以通过编写语句来完成 输出 << “错误”; 而现在想象一下,在程序的很多地方都需要插入这样一行。当然,你可以到处写。但是这个解决方案有两个缺点。
1)这个字符串会多次存入内存
2) 如果我们想改变错误的输出,我们将不得不在整个程序中改变这一行,这是相当不方便的

对于这种情况,需要程序。
带有过程的程序可能如下所示: #include; 使用命名空间标准; void printError() // 过程描述 { 输出 << “错误”; // 过程主体 - 过程将执行的命令 } 主要的() { ... printError() // 开始执行程序。我们只需指定要执行的过程的名称。 ... 打印错误() ... } 该过程以单词 void 开头。 过程名称后有空括号。
在过程中执行的所有语句都是缩进的。 

程序写在main函数之前 main()

要执行一个过程,您需要在主程序中调用它按名称并记住写括号
您可以多次调用程序中的过程。

现在让我们想象一下,我们需要显示不同的消息来响应用户的错误,这取决于他犯了什么样的错误。
在这种情况下,您可以为每个错误编写自己的过程:   无效 printErrorZero() { 输出 <<错误。被零除!”; } 无效打印错误输入() { 输出 << “输入错误!”; } 如果有更多可能的错误怎么办?这个解决方案不适合我们!
我们需要学习如何通过告诉程序显示什么错误信息来控制程序。
为此,我们需要将参数写在过程名称后的括号中 无效打印错误(字符串) { 输出 <<年代; } 在此过程中,s 是一个参数 - 一个允许您控制过程的特殊变量。
参数是一个变量,决定子程序如何工作。参数名称在子程序头中以逗号分隔列出。参数类型写在参数前。

现在,在调用该过程时,您需要在括号中指明将分配给我们过程中的参数(变量 s)的实际值 printError("错误!除以零!"); 该值称为参数。
参数是调用子程序时传递给子程序的参数值。
参数不仅可以是常量值,还可以是变量或算术表达式。

局部和全局变量
通常需要使用仅在子程序中使用的附加变量。此类变量称为本地(或本地),只能在创建它们的子例程内进行操作。
 
Local variable scope 是声明它的花括号块

C++中的主程序也是一个子程序,所以在main()中声明的所有变量都是局部变量。
其他子程序对其他子程序的局部变量一无所知。

因此,可以将变量的作用域(scope)限制在真正需要它的子程序中。在编程中,这种技术称为封装  - 隐藏变量不被外部更改。

如果有必要声明一个在程序中任何地方(在任何子程序中)都可见的变量,则此类变量在所有子程序之外声明(参见下表中的程序 3)。
此类变量称为全局

在C++中,当程序启动时,所有全局变量都会自动设置为零(布尔变量取值false)。


分析三个程序: <正文> 显示在屏幕上

1) 在这个程序中,变量 i 是局部变量。在子程序中声明局部变量 2) 这里即使主程序中有变量i(值为7),也会新建一个值为5的局部变量i。 
当你运行这个程序时,屏幕会显示值75
3) 这个程序有一个全局变量i。它的值可以在子程序和主程序中改变
该过程将使用全局变量 i 并为其分配一个等于 2 的新值。值 2
无效测试() {  诠释我= 5; 输出 <<我; } 无效测试() {  诠释我= 5;  输出 <<我; } 主要的() { 诠释我= 7;  输出 <<我;  测试(); } #include ; 使用命名空间标准; 诠释我; 无效测试() {  我 = 2; } 主要的() { 测试(); 输出 <<我; }
任务
编写一个交换两个变量值的程序。

此任务的特点是我们需要在过程中所做的更改才能为调用程序所知。

让我们尝试编写这样的程序: void Swap ( int a, int b ) // 带有这样的过程参数描述, { // 参数(x 和 y)的值将被复制, 诠释 c; // 变量 a 和 b 是与 x 和 y 无关的自变量 c = 一个;一 = b; b=c; } 主要的() { 诠释 x=1, y=2; 交换(x,y); // 变量x和y(参数)的值被复制到参数a和b中 输出 << “x=” << x<< ", y=" <<是; // x=1, y=2 } 如果你运行这个程序,你可以看到变量xy的值没有改变。为了使参数改变参数的值,您必须使用通过引用传递数据。 为此,在数据类型名称之后在子例程的标题中,您必须放置符号 & ("ampersand")。 无效交换 ( int & a, int & b ) // 现在变量 a 和 b 得到变量 x 和 y 在内存中的地址 { 诠释 c; c = 一个;一 = b; b=c; } 用法:如果您通过引用传递参数,那么在调用过程时只有变量名(不是数字也不是算术表达式)可以出现在这个地方!< br />
不要调用这样的过程: 交换(x, 4 ); 交换(5+x, y);