子程序:过程和函数 - 1


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

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

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

子例程或方法有两种类型 -  函数(返回工作结果的) 和过程(不返回结果的)。

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

对于这种情况,需要方法和程序。
带有过程的程序可能如下所示:

使用系统;
类程序 {
   静态无效 PrintError() {
        Console.WriteLine("错误");
   
   静态无效主要(){
       打印错误();
   
}

 

程序以单词 void开头。 之后程序名  空括号是写的。
在过程中执行的所有语句都是缩进的。 
Static  修饰符表示给定的字段、方法或属性不属于类的每个对象,而是属于所有对象。
方法和过程写在main方法Main()之前。

要引用一个过程,在主程序中你需要通过名称调用它并且不要忘记写括号。
您可以多次调用程序中的过程。

现在假设我们需要显示不同的消息来响应用户错误,具体取决于是否他究竟犯了什么错误。
在这种情况下,您可以为每个错误编写自己的过程: 

 

无效 printErrorZero() {     Console.WriteLine("错误。除以零!");

 

 

<前> void printErrorInput() { Console.WriteLine("输入错误!"); } 如果有更多可能的错误怎么办?那么这个解决方案将不适合我们。
我们需要学习如何通过告诉程序显示什么错误信息来控制程序。
为此,我们需要将参数写在过程名称后的括号中
<前> void printError(字符串 s) { 控制台.WriteLine(s); } 在这个过程中,s 是一个参数 - 一个特殊的变量允许控制程序。
参数是一个变量,其值是子程序运行所依赖的。参数名称在子程序头中以逗号分隔列出。参数类型写在参数前。

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

局部和全局变量
通常需要使用仅在子程序中使用的附加变量。此类变量称为本地(或本地),只能在创建它们的子程序内进行操作。
 
Local variable scope 是声明它的花括号块。
C#中的主程序也是一个子程序,所以在void Main()中声明的所有变量都是局部变量。其他子程序对其他子程序的局部变量一无所知。

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

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

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

分析三个程序: <正文>

1) 在这个程序中,变量 i 是局部变量。局部变量在子程序中声明。 2) 这里即使主程序中有变量i(值为7),也会新建一个值为5的局部变量i。 
执行该程序时,屏幕上会出现值75。
3) 这个程序有一个全局变量 i。它的值可以在子程序内部和主程序内部更改。
该过程将使用全局变量 i 并将为其分配一个等于 2 的新值。显示值 2。
静态无效测试() {  诠释我= 5; Console.Write(“我”); } 静态无效测试() {  诠释我= 5;   Console.Write(“我”); } 静态无效主要() { 诠释我= 7;   Console.Write(“我”);  测试(); } 使用系统; 课程计划 { 诠释我; 静态无效测试() {  我 = 2; } 静态无效主要() { 测试(); Console.Write(“我”); } }
任务
编写一个交换两个变量值的程序。

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

让我们尝试编写这样的程序: static 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 = 1, y = 2 } 如果你运行这个程序,你可以看到 x 和 y 变量的值没有改变。为了使参数改变参数的值,必须使用按引用传递的数据。 为此,必须在标头中的数据类型名称前写上ref的子程序。 void Swap ( ref int a, ref int b ) // 现在变量 a 和 b 得到变量 x 和 y 在内存中的地址 { 诠释 c; c = 一个;一 = b; b=c; } 静态无效主要() {  诠释 x=1, y=2;  交换(参考 x,参考 y); 应用:如果你通过引用传递参数,那么在调用过程时只有变量的名称(不是数字也不是算术表达式)可以站在这个地方。

您不能调用这样的过程: <前> 交换(x,4); 交换(5+x,y);