C language beginner level - 2 function

In the last blog, we mentioned the branches and loops of C language. In this blog, I'll share the relevant knowledge of C language functions. Please open your eyes and have a good look (HA HA).

When it comes to functions, the first thing we think of is mathematical functions. This very interesting and practical knowledge in the field of mathematics can also be said to be tools. Will it have the same effect in the programming world? The answer was: Yes. Not only in mathematics, but also in programming, it is also a very useful tool. That's nonsense. Let's start our next content.

catalogue

1, What are the functions in C language

2, Classification of C language functions

2.1 library functions

2.2 user defined functions

3, Parameters of function

3.1 actual parameters (actual parameters):

2.2 formal parameters (formal parameters):

4, Function call

4.1 value transfer call

4.2 address calling

5, Nested calls and chained access to functions

5.1 nested calls to functions

5.2 chain access

6, Declaration and definition of functions

6.1 function declaration

6.2 definition of function

VII. Function recursion

7.1 two necessities of recursion

7.2 recursion and iteration

Conclusion:

1, What are the functions in C language

The following passage comes from Baidu:

        "A function defined in c language is a piece of code that can be reused to complete a function independently. It can receive or not receive the data passed by the user. When defining a function that receives user data, it needs to specify parameters. If it does not receive user data, it does not need to specify parameters. According to this point, the function can be divided into parametric function and nonparametric function. A function is an encapsulated function that can be used With reusable code, it makes our program more modular and does not need to write a lot of repetitive code. The function can be saved in advance and given a unique name. As long as you know its name, you can use this code. "

The following code simply uses the function to print a menu. Here is just a brief description. How to use the function and its form will be discussed later. (the above paragraph is relatively long, which is not easy to understand. I will introduce it in detail below according to my understanding)

II. Classification of C language functions

2.1 library functions

First, let's start with a few library functions we've used

For example:

1) Print a "Hello World!" on the screen, We'll use (printf)

2) We need to enter "Hello World!", To use (scanf)

3) When we want to calculate the k-th power of n, we use (pow)

These are our common library functions. C language provides us with a series of library functions for our convenience.

How many library functions are there? Here's a website. You can understand it.

http://www.cplusplus.com/reference/http://www.cplusplus.com/reference/

There are many library functions we will use, so it is a very easy to use website.

Common library functions in C language include:
IO function, input / output function;
String operation function;
Character operation function;
Memory operation function;
Time / date function, such as timestamp;
Mathematical functions, such as power, square, absolute value;
Other library functions, etc.

be careful:

To use library functions, you must include #include# the corresponding header file.

2.2 user defined functions

The difference between custom functions and library functions is that we can design our own functions according to the effect we want to achieve.

Composition of custom functions:
Return type} function name (function parameter); (function parameters also have types) (there can be one or more)

Functions are defined first and then called.

Let's take the strlen function (calculating the length of a string) as an example

size_t stands for unsigned integer. Calculate the length of the string. It must not be negative

Const, we need to calculate the length of the string. We can't change the string, so we use const to decorate it

char * character pointer

Let's write a function to calculate the maximum of two numbers.

#include <stdio.h>
int Find_Max(int x, int y)
{
	if (x > y)
	{
		return x;
	}
	else
	{
		return y;
	}
    //There is a simpler way to write, using the binocular operator
    //return x > y ? x : y;
}
int main()
{
	int num1 = 0;
	int num2 = 0;
	scanf("%d %d", &num1, &num2);
	int max = Find_Max(num1, num2);
	printf("%d\n", max);
	return 0;
}

3, Parameters of function

3.1 actual parameters (actual parameters):

The parameters actually passed to the function are called arguments.
Arguments can be constants, variables, expressions, functions, etc.
No matter what type of arguments are, they must have definite values when making a function call in order to pass these values to the formal parameters.

2.2 formal parameters (formal parameters):

Formal parameters refer to the variables in parentheses after the function name, because formal parameters are instantiated only when the function is called
(allocate memory units), so it is called formal parameter. Formal parameters are automatically destroyed after the function call is completed. Therefore form
The argument is only valid in a function.

The code for finding the maximum value of the two functions above, num1 and num2 are the arguments, and x and y are the formal parameters

Let's take a look at the monitor, & take the address symbol and the address of the formal parameter and the argument. It is obvious that the formal parameter and the argument open up two different addresses, so the formal parameter is equivalent to a temporary copy of the actual parameter.

4, Function call

4.1 value transfer call

The formal parameters and arguments of the function occupy different memory space respectively, and the modification of the formal parameters will not affect the arguments.  

4.2 address calling

Addressing call is a way to call a function by passing the memory address of the variable created outside the function to the function parameters.
This parameter transfer method can establish a real relationship between the function and the variables outside the function, that is, the function can be operated directly inside
As an external variable of a function.

Let's write a function to exchange the contents of two integer variables

void Swap1(int x, int y)
{
	int tmp = 0;
	tmp = x;
	x = y;
	y = tmp;
}

void Swap2(int* px, int* py) {
	int tmp = 0;
	tmp = *px;
	*px = *py;
	*py = tmp;
}
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	printf("Before exchange: a=%d,b=%d\n", a, b);
	//Swap1(a, b);
	Swap2(&a, &b);
	printf("After exchange: a=%d,b=%d\n", a, b);
	return 0;
}

Two functions are written here. We can compare Swap1 and Swap2.

As we have also mentioned above, formal parameters and arguments open up two different memory spaces. Swap1 is interpreted as a value passing call. We just exchange the formal parameters without changing the arguments, while the formal parameters are only a temporary copy of the arguments. When the function is called, the formal parameters will be automatically destroyed, so swap1 cannot achieve the functions we want.

Swap2 passes the address of the argument. The function parameter part is received by the pointer variable (the pointer variable is the storage address), which is the address call. The formal parameter and the argument use the same memory space, which can establish a true relationship between the function and the variables outside the function, that is, the variables outside the function can be directly operated inside the function.

From the above figure, we can see that the addresses of a and px are the same, and the addresses of b and py are the same.

Here are some codes for realizing various problems with functions

(1)

//Print prime numbers between 100 and 200
#include <stdio.h>
#include <math.h>
int is_prime(int n)
{
	//Number division of 2~n-1
	//Trial division of 2~sqrt(n)
	int j = 0;
	for (j = 2; j <= sqrt(n); j++)
	{
		if (n % j == 0)
		{
			return 0;
		}
	}
	return 1;
}
int main()
{
	int i = 0;
	for (i = 100; i <= 200; i++)
	{
		//Judge whether it is prime
		//The return value is 1, which means it is a prime number
		//The return value is 0, which means it is not a prime number
		if (is_prime(i) == 1)
		{
			printf("%d ", i);
		}
	}
	return 0;
}

 (2)

//Write a function to judge whether it is a leap year
#include <stdio.h>
int Is_leap_year(int n)
{
	//Rules for judging leap years:
	//(1) Can be divided by 4, but not by 100
	//(2) Can be divided by 400
	if (n % 4 == 0 && n % 100 != 0 || n % 400 == 0)
	{
		return 1;
	}
	return 0;
    //Concise method
    //return (((n % 4 == 0) && (n % 100 != 0)) || (n % 400 == 0));
}
int main()
{
	int y = 0;
	scanf("%d", &y);
	int ret = Is_leap_year(y);
	//If it is a leap year, return 1
	//If it is not a leap year, it returns 0
	if (ret == 1)
	{
		printf("%d Year is a leap year\n", y);
	}
	else
	{
		printf("%d Year is not a leap year\n", y);
	}
	return 0;
}

 (4)

//Write a function to realize the binary search of an integer ordered array
//Return subscript when found
//Return - 1 if not found
#include <stdio.h>
int binary_search(int arr[], int k, int sz)
{
	int left = 0;
	int right = sz - 1;
	while (left <= right)
	{
		int mid = left + (right - left) / 2;
		if (arr[mid] < k)
		{
			left = mid + 1;
		}
		else if (arr[mid] > k)
		{
			right = mid - 1;
		}
		else
		{
			return mid;
		}
	}
	return -1;
}
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 0;
	scanf("%d", &k);//Number of to find
	int sz = sizeof(arr) / sizeof(arr[0]);
	int ret = binary_search(arr, k, sz);
	if (-1 == ret)
	{
		printf("Can not find\n");
	}
	else
	{
		printf("Found, subscript:%d\n", ret
		);
	}

	return 0;
}

 

5, Nested calls and chained access to functions

Functions and functions can be combined according to actual needs, that is, they call each other.

5.1 nested calls to functions

#include <stdio.h>
void new_line()
{
	printf("Hello\n");
}
void three_line()
{
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		new_line();
	}
}
int main()
{
	three_line();
	return 0;
}
be careful: Functions can be called nested, but not defined nested.

Nested definition:

So remember this is wrong.

5.2 chain access

Take the return value of one function as an argument to another function.
This is normal code

This is the code for chain access

There is a typical chain access code

4321 is displayed on the screen. Why is this?

This is the return value of the printf function, which means that each of these functions returns the number of characters printed. If an error occurs, it returns a negative value. Therefore, from the inside to the outside, print 43 first, 43 is two characters, the next print 2, 2 is one character, so finally print 1, and finally print 4321 on the screen.

6, Declaration and definition of functions

6.1 function declaration

1. Tell the compiler what a function name is, what the parameters are and what the return type is. But whether it exists or not depends on the function declaration.
2. The declaration of a function usually appears before the use of the function. To meet the requirements of declaration before use.
3. The function declaration is generally placed in the header file.

6.2 definition of function

The definition of function refers to the specific implementation of the function and explains the function implementation of the function.

The following code is different from the above. The above code will put the custom function on the main function, but if it is written like this, a warning will be reported.

Therefore, it should be noted that the above-mentioned declaration before use. (but it's not often written like this, even if it's the right way)

 

VII. Function recursion

The programming technique of a program calling itself is called recursion.
As an algorithm, recursion is widely used in programming languages. A method in which a process or function directly or indirectly calls itself in its definition or description. It usually transforms a large and complex problem layer by layer into a smaller problem similar to the original problem.

Recursive strategy: only a small number of programs can describe the multiple repeated calculations required in the problem-solving process, which greatly reduces the amount of code in the program.
The main way of thinking about recursion is to make big things small

Simply put, function recursion means that the function calls itself.

7.1 two necessities of recursion

(1) There is a constraint. When this constraint is met, recursion will not continue.
(2) Getting closer to this constraint after each recursive call

For example:

//Receives an integer value (unsigned) and prints its bits in order
void print(int n)
{
	if (n > 9)
	{
		print(n / 10);
	}
	printf("%d ", n % 10);
}
int main()
{
	unsigned int num = 0;
	scanf("%d", &num);//1234
	print(num);//The print function can print out each bit of num in order

	return 0;
}

Draw a simple diagram to familiarize yourself with the recursive process:

 

Let's mention the stack area. Every time the program calls the function, it will open up a memory space on the memory stack area. For example, when the code just now is n = 1234, it will open up a space, and so on. If we don't set a limit condition, and don't get closer to the limit condition as we go on, will recursion continue all the time, The case of dead recursion is formed, but the space of the stack area is limited. If it is opened up without limitation, it will cause stack overflow. The following figure uses the above code to briefly illustrate.

 

7.2 recursion and iteration

As for recursion, we also introduced that iteration can be simply understood as a loop.

Here are some examples:

(1)

//Calculating factorial of n by recursion
int fac(int n)
{
	if (n <= 1)
	{
		return 1;
	}
	else
	{
		return n * fac(n - 1);
	}
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = fac(n);
	printf("%d\n", ret);

	return 0;
}

(2)

//Use recursion to find the nth Fibonacci number. (overflow is not considered)
int fib(int n)
{
	if (n <= 2)
	{
		return 1;
	}
	else
	{
		return fib(n - 1) + fib(n - 2);
	}
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = fib(n);
	printf("%d\n", ret);

	return 0;
}

This is written by recursive method, but there will be some small problems with recursive method. If we want to calculate the 40th Fibonacci number, it will not be printed on the screen immediately. That is because calculating the 40th number requires a large amount of calculation. Even the computer has to calculate it for a while. We can imagine how much calculation is.

To calculate the 40th Fibonacci number, as shown in the figure above, you need to calculate from 40 to the first number. If it is the 50th Fibonacci number, it will take longer.

But if you don't use recursive methods, will there be a better method to improve efficiency?

int fib(int n)
{
	int a = 1;
	int b = 1;
	int c = 0;
	int i = 0;
	if (n <= 2)
	{
		return 1;
	}
	while (n > 2)
	{
		c = a + b;
		a = b;
		b = c;
		n--;
	}
	return c;
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = fib(n);
	printf("%d\n", ret);

	return 0;
}

The above code does not use the recursive method, but it can also calculate the nth Fibonacci number, and the efficiency of the code is greatly improved. Compared with the recursive method from the nth to the first, this non recursive method from the first to the nth is very fast, so the knowledge is vivid, It can't be said that today we learn recursion and abandon other methods. We still have to find the optimal solution.

Conclusion:

I'll share the relevant knowledge about C language functions here. This blog is written here. I think it's great to write a blog. I feel that every day is very full. I'm looking forward to my next blog. (ha ha, sprinkle flowers after the end)

 

 

Keywords: C Back-end

Added by kornlord283 on Thu, 20 Jan 2022 01:49:08 +0200