Subroutines: procedures and functions - 1


A subroutine is a separate part of a program that has a name and solves its own separate task. The subroutine is located at the beginning of the main program and can be launched (called) from the main program by specifying the name.

Using subroutines allows you to avoid code duplication if you need to write the same code in different places programs. 
Libraries that are imported into a program (for example, System) consist of routines that have already been compiled by someone. Programmers don't have to think about what algorithms are implemented in them, they just apply them, thinking only about what exactly they are doing. This is a big time saver. There is no need to write an algorithm that has already been written by someone else.

Each subroutine should only do one task, either calculate something, or output some data, or do something else. 

Subroutines, or methods, are of two types -  functions (those that return the result of work) and procedures (those that do not).

Let's start with the second type. Let's try to write a simple example.
Suppose we need to display the string "Error" on the screen every time an error can occur in the code due to the fault of the user (for example, when he enters incorrect data).
This can be done by writing the statement
Console.WriteLine("Error");
Now let's imagine that this line needs to be inserted in many places in the program. Of course, you can just write it everywhere. But this solution has two drawbacks.
1) this string will be stored in memory many times;
2) if we want to change the output on error, we will have to change this line throughout the program, which is rather inconvenient.

For such cases, methods and procedures are needed.
A program with a procedure might look like this:

using System;
classProgram {
    static void PrintError() {
        Console.WriteLine("Error");
    }
    static void Main() {
        PrintError();
    }
}

 

A procedure starts with the word void. After the procedure name  empty brackets are written.
All statements that are executed in a procedure are indented. 
The Static  modifier means that the given field, method or property will not belong to each object of the class, but to all of them together.
Methods and procedures are written before the main method Main().

To refer to a procedure, in the main program you need to call it by name and do not forget to write parentheses.
You can call a procedure in a program any number of times.

Now let's imagine that we need to display different messages in response to a user error, depending on whether exactly what mistake he made.
In this case, you can write your own procedure for each error: 

 

void printErrorZero() {     Console.WriteLine("Error. Division by zero!"); }

 

 

void printErrorInput()
{
    Console.WriteLine("Error in input!");
}

What if there are many more possible errors? Then this solution will not suit us.
We need to learn how to control the procedure by telling it what error message to display.
To do this, we need parameters that we will write in parentheses after the procedure name
void printError(string s)
{
    Console.WriteLine(s);
}
In this procedure, s is a parameter - a special variable that allows control the procedure.
The parameter is a variable whose value the operation of the subroutine depends on. Parameter names are listed separated by commas in the subprogram header. The parameter type is written before the parameter.

Now, when calling the procedure, you need to specify the actual value in parentheses that will be assigned to the parameter (the variable s) inside our procedure
printError("Error! Division by zero!");
This value is called an argument.
The argument is the parameter value that is passed to the subroutine when it is called.
The argument can be not only a constant value, but also a variable or an arithmetic expression.< /span>

Local and global variables
It is often necessary to use additional variables that will only be used in the subroutine. Such variables are called local (or local) and can only be manipulated within the subroutine in which they are created.
 
Local variable scope is the curly bracketed block within which it is declared.
The main program in C# is also a subroutine, so all variables declared inside void Main() are local variables. Other subroutines don't "know" anything about the local variables of other subroutines.

Thus, it is possible to limit the scope (scope) of a variable only to the subroutine where it is really needed. In programming, this technique is called encapsulation  - hiding the variable from changing it from the outside.

If it is necessary to declare a variable that would be visible anywhere in the program (in any subroutine), then such variables are declared outside of all subroutines (see program 3 from the table below).
Such variables are called global.

In C#, when the program starts, all global variables are automatically set to zero (boolean variables take the value false).

Analyze three programs:
1) In this program, the variable i is local. A local variable is declared inside a subroutine. 2) Here, even if there is a variable i in the main program (with value 7), a new local variable i with value 5 will be created. 
When this program is executed, the value 75 will appear on the screen.
3) This program has a global variable i. Its value can be changed inside the subroutine, and inside the main program.
The procedure will work with the global variable i and it will be assigned a new value equal to 2. The value 2 is displayed.
static void test() {   int i = 5; Console.Write("i"); } static void test() {   int i = 5;   Console.Write("i"); } static void Main() { int i = 7;   Console.Write("i");   test(); } using System; class Program { int i; static void test() {   i = 2; } static void Main() { test(); Console.Write("i"); } }

Task
Write a procedure that swaps the values ​​of two variables.

The peculiarity of this task is that we need the changes made in the procedure to become known to the calling program.

Let's try to write the procedure like this: static void Swap (int a, int b) // with such a description of the procedure parameters, { // will copy the values ​​of the arguments (x and y) int c; // variables a and b are independent variables not related to x and y c = a; a = b; b=c; } static void Main() { int x=1, y=2; Swap(x, y); //values ​​of variables x and y (arguments) are copied into parameters a and b, x = 1, y = 2 } If you run this program, you can see that the values ​​of the x and y variables have not changed. In order for the parameters to change the values ​​of the arguments, you must use data passing by reference. To do this, you must write ref before the name of the data type in the header of the subroutine. void Swap ( ref int a, ref int b ) // now variables a and b get addresses of variables x and y in memory { int c; c = a; a = b; b=c; } static void Main() {   int x=1, y=2;   Swap(ref x, ref y); Application: if you pass an argument by reference, then only the name of the variable (NOT a number and NOT an arithmetic expression) can stand in this place when calling the procedure.

You can't call a procedure like this:
Swap(x, 4);
Swap(5+x, y);