Elementary C language - 2. Functions

        In the last blog, we mentioned branches and loops in C language. In this article, I will share the relevant knowledge of C language functions, so please keep your eyes open and take a good look (haha).

preview

        When it comes to functions, the first thing that comes to our mind is mathematical functions. This very interesting and practical knowledge in the field of mathematics can also be said to be a tool. Will it have the same effect in the programming world, then the answer was: yes. Not only in mathematics, but also a very useful tool in programming, so without further ado, let's start our next content.


content

1. What is a function in C language?

Second, the classification of C language functions

        2.1 Library functions

        2.2 Custom Functions

Third, the parameters of the function

        3.1 Actual parameters (actual parameters):

        2.2 Formal parameters (formal parameters):

Fourth, the function call

        4.1 Call by value

        4.2 Call by address

5. Nested calls and chained access of functions

        5.1 Nested Calls of Functions

        5.2 Chain access

Six, function declaration and definition

        6.1 Declaration of functions

        6.2 Definition of functions

 Seven, function recursion

                  7.1 Two imperatives for recursion

         7.2 Recursion and iteration

Conclusion:


1. What is a function in C language?

        The following text is 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 data passed by the user or not. The function that receives user data must specify parameters when it is defined, and it does not receive user data. The data does not need to be specified, according to this, functions can be divided into parameterized functions and non-parameterized functions. A function is a piece of encapsulated and reusable code, which makes our program more modular and does not need to write a lot of repetitive Code. The function can be saved ahead of time and given a unique name, and the code can be used as long as you know its name.”

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


 Second, the classification of C language functions

        2.1 Library functions

        First of all, let's cite a few library functions we have used

Such as:

1) Print a "Hello World!" on the screen, we will use (printf)

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

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

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

        How many library functions are there in the end? Here is a website, and everyone knows it.

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

There are a lot of library functions we will use here, so it's a very useful website.

Commonly used library functions in C language are:
        IO function, input and output function;
        String manipulation functions;
        character manipulation functions;
        memory manipulation functions;
        time/date functions, such as timestamps;
        Mathematical functions, such as power, square root, absolute value;
        other library functions, etc.

Notice:

        To use library functions, the header files corresponding to #include  must be included.


        2.2 Custom 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 parameters);  (function parameters are also typed) (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, calculates the length of the string, it is definitely not a negative number

const, we want to calculate the length of the string, we cannot let the string change, so use const to modify

char* character pointer

 Then let's write a function ourselves to calculate the maximum value of two numbers.

#include <stdio.h>
int Find_Max(int x, int y)
{
	if (x > y)
	{
		return x;
	}
	else
	{
		return y;
	}
    //还有一个更简单的写法,用三目操作符
    //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;
}


Third, the parameters of the function

        3.1 Actual parameters (actual parameters):

The actual parameters passed to the function are called actual parameters.
Arguments can be: constants, variables, expressions, functions, etc.
Regardless of the type of quantities the actual parameters are, they must have definite values ​​in order to pass those values ​​to the formal parameters when the function is called.

        2.2 Formal parameters (formal parameters):

Formal parameters refer to the variables in parentheses after the function name, because formal parameters are only instantiated when the function is called
(allocate memory unit), so it is called formal parameter. Formal parameters are automatically destroyed when the function call is complete. thus form
The formula parameter is only valid within a function.

The code above to find the maximum value of two functions, num1, num2 are actual parameters, x, y are formal parameters

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


Fourth, the function call

        4.1 Call by value

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


        4.2 Call by address

Call by reference is a way to call a function by passing the memory address of a variable created outside the function to the function parameter.
This method of passing parameters allows the function to establish a real connection with the variables outside the function, that is, the function can be directly manipulated inside the function.
as a variable outside the function.

Next we write a function to swap 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("交换前:a=%d,b=%d\n", a, b);
	//Swap1(a, b);
	Swap2(&a, &b);
	printf("交换后:a=%d,b=%d\n", a, b);
	return 0;
}

        Two functions are written here, we can compare Swap1 and Swap2.

        We also mentioned above that formal parameters and actual parameters open up two different memory spaces. For the interpretation of Swap1 as a pass-by-value call, we only exchange the formal parameters without changing the actual parameters, and the formal parameters are only temporary parameters of the actual parameters. Copy, when the function is called, the formal parameters will be automatically destroyed, so Swap1 cannot achieve the function we want.

        Swap2 passes the address of the actual parameter, and the function parameter part is received by the pointer variable (the pointer variable is the storage address). This is the call by reference. The formal parameter and the actual parameter use the same memory space, which can make the function and function . The outer variables establish a real connection, that is, the variables outside the function can be directly manipulated 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.


Let's write a few codes that use functions to implement various problems

(1)

//打印100~200之间的素数
#include <stdio.h>
#include <math.h>
int is_prime(int n)
{
	//2~n-1的数试除
	//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++)
	{
		//判断是否为素数
		//返回值为1,表示是素数
		//返回值为0,表示不是素数
		if (is_prime(i) == 1)
		{
			printf("%d ", i);
		}
	}
	return 0;
}


 (2)

//写一个函数判断是不是闰年
#include <stdio.h>
int Is_leap_year(int n)
{
	//判断闰年的规则:
	//(1)能被4整除,但不能被100整除
	//(2)能被400整除
	if (n % 4 == 0 && n % 100 != 0 || n % 400 == 0)
	{
		return 1;
	}
	return 0;
    //简洁方法
    //return (((n % 4 == 0) && (n % 100 != 0)) || (n % 400 == 0));
}
int main()
{
	int y = 0;
	scanf("%d", &y);
	int ret = Is_leap_year(y);
	//如果是闰年,就返回1
	//如果不是闰年,就返回0
	if (ret == 1)
	{
		printf("%d年是闰年\n", y);
	}
	else
	{
		printf("%d年不是闰年\n", y);
	}
	return 0;
}


 (4)

//写一个函数,实现一个整形有序数组的二分查找
//找到了就返回下标
//找不到就返回-1
#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);//要查找的数
	int sz = sizeof(arr) / sizeof(arr[0]);
	int ret = binary_search(arr, k, sz);
	if (-1 == ret)
	{
		printf("找不到了\n");
	}
	else
	{
		printf("找到了,下标为:%d\n", ret
		);
	}

	return 0;
}

 


5. Nested calls and chained access of functions

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

        5.1 Nested Calls of 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;
}
Note:  Functions can be called nested, but not defined nested.

Nested definitions:

 So remember this is wrong.


        5.2 Chain access

Use the return value of one function as an argument to another function.
this is normal code

 This is the code for chained access

There is a typical chained access code

 4321 is displayed on the screen, why is this?

        This is the return value of the printf function, meaning: each of these functions returns the number of characters printed, or a negative value if an error occurs. So from the inside to the outside, first print 43, 43 is two characters, next print 2, 2 is one character, so last print 1, and finally print 4321 on the screen.


Six, function declaration and definition

        6.1 Declaration of functions

1. Tell the compiler what the name of a function is, what the parameters are, and what the return type is. But whether it exists or not is not determined by the function declaration.
2. The declaration of a function generally appears before the use of the function. To satisfy the declaration before use .
3. Function declarations are generally placed in header files.

        6.2 Definition of functions

The definition of a function refers to the specific implementation of the function, and the function implementation of the function is explained.

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

 Therefore, it should be noted that the above-mentioned declaration is used first . (but not often written like below, even if it is correct)

 


 Seven, function recursion

The programming technique in which a program calls itself is called recursion.
        Recursion as an algorithm is widely used in programming languages. A procedure or function in its definition or specification has a method of calling itself directly or indirectly, which usually transforms a large and complex problem into a smaller problem similar to the original problem to solve.

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

Simply put, function recursion is a function that calls itself .

        7.1 Two imperatives for recursion

(1) There is a restriction, when this restriction is met, the recursion will not continue.
(2) getting closer and closer to this limit after each recursive call

As an example:

//接收一个整型值(无符号),按照顺序打印它的每一位
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);//print函数可以把num的每一位按照顺序打印出来

	return 0;
}

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

 

        The stack area is mentioned here. Every time the program calls a function, a memory space is opened on the stack area of ​​the memory. For example, in the code just now, a space is opened when n = 1234, and so on. If we do not set a restriction, and As the recursion goes on, without getting closer and closer to this limit, the recursion will continue to repeat, forming a situation of dead recursion, but the space of the stack area is limited, and the unlimited development will cause stack overflow . The following figure uses the above code to briefly illustrate.

 


         7.2 Recursion and iteration

Regarding recursion, we have also introduced it above. As for iteration, it can be simply understood as a loop.

Here are a few examples:

(1)

//用递归计算n的阶乘
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)

//用递归求第n个斐波那契数。(不考虑溢出)
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 in a recursive method, but there are some small problems with the recursive method. If we want to calculate the 40th Fibonacci number, it will not be printed on the screen immediately, that is because the 40th Fibonacci number is calculated. Numbers require a relatively large amount of calculation, even a computer has to do it for a while.

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

But if there is no recursive method, will there be a better way 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 to using the recursive method to calculate from the nth to the first, This non-recursive method calculates from the 1st to the nth method very fast, so the knowledge is vivid. It can’t be said that if you learn recursion today, you will abandon other methods. We still have to find the best solution. solution.


Conclusion:

        The relevant knowledge about C language functions is shared here, and this blog is written here. Looking back on the feeling of blogging, it is still very good. I feel that every day is very fulfilling. I am looking forward to the next blog. . (Haha, the end of the flower)

 

 

Guess you like

Origin blog.csdn.net/m0_64607843/article/details/122540152