[turn complexity into simplicity and squeeze knowledge into juice] function

Keywords: C

1. What is the function?

Wikipedia definition of function: subroutine
① Subroutine is a part of code in a large program, which is composed of one or more statement blocks. It is responsible for completing a specific task and has relative independence compared with other codes.
② Generally, there are input parameters and return values, which provide encapsulation of the process and hiding of details. These codes are usually integrated into software libraries.
In programming, functions let you name a set of commands that you can run at any time.

2. Type of function

Library function

In the development process, we will frequently use some functions. In order to improve the program and development efficiency, C language encapsulates these functions into library functions and stores them in the basic library of C language. The common functions are scanf() and printf().
Note: when using library functions, you must "say hello" in advance, that is, you must include #include the corresponding header file.
Learning library function website: www.cplusplus.com
Common library functions in C language:

  • IO function: input and output functions, such as scanf function and printf function.
  • String operation function: a function for string processing, string copy, calculated length and character search.
  • Character manipulation function: a function that processes individual characters.
  • Memory operation function: functions for memory copy, search and other operations.
  • Time / date function: a function that processes date type or date time type data.
  • Mathematical function: a function of numerical calculation, such as sqrt function.
  • Other library functions
    Learning library function website:
    http://www.cplusplus.com/
    https://zh.cppreference.com/w/%E9%A6%96%E9%A1%B5

Take learning strcpy library function as an example:
Find the strcpy function from the library website above

strcpy(arr1,arr2);//Copy the string from arr2 to arr1

example:

#include<stdio.h>
#include<string.h>
int main()
{
	char str1[20] = { 0 };
	char str2[] = "hello world!";
	char* str3;
	strcpy(str1, str2);
	str3 = strcpy(str1, str2);
	printf("%s\n", str1);
	printf("%s\n", str3);
	return 0;
}

str1 can copy the content to str2, including '\ 0' characters.
The return value of strcpy is char * (address), so char * is used to define the variable str3.

Custom function

Custom functions, like library functions, have function names, return types, and function parameters, which we can play freely.
Function composition:

ret_type fun_name(para1, * )
{
 statement;//Statement item
 return 0;//The return value and the return type of the function must be the same. If it is a void function, it can not be written 
}
ret_type Return type
fun_name Function name
para1    Function parameters

Let's take a chestnut:

int get_max(int x, int y)
{
	return (x > y ? x : y);
}
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	int max = get_max(a, b);
	printf("max=%d", max);
	return 0;
}

Call get_ When the max() function is used, get is given_ The max() function passes in two arguments a and B. after calling, it will return a value (the maximum value of a and b) to get_ The max (a, b) function is stored in the max integer variable.

Actual parameter (actual parameter)

The parameters really 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.
a, b in the above example.

Formal parameter (formal parameter)

Formal parameters refer to the variables in parentheses after the function name. They are called formal parameters because they are instantiated (memory units are allocated) only when the function is called. Formal parameters are automatically destroyed when the function call is completed. Therefore, formal parameters are only valid in functions.
x, y in the above example.

4. Function call

There are two methods of function call: Value Passing call and address passing call.

Value passing call

For value passing calls, the formal parameters and arguments of the function occupy different memory blocks respectively, and the modification of the formal parameters will not affect the arguments.

Write a function to exchange two numbers:

void Swap1(int x, int y)
{
	int temp = 0;
	temp = x;
	x = y;
	y = temp;
}
int main()
{
	int num1 = 1;
	int num2 = 2;
	printf("Before exchange::num1 = %d num2 = %d\n", num1, num2);
	Swap1(num1, num2);
	printf(" Swap1::num1 = %d num2 = %d\n", num1, num2);
	return 0;
}


The results show that num1 and num2 are not exchanged.

It can be seen from the monitoring during debugging that although x and y are exchanged, num1 and num2 are not exchanged. Because the x and Y addresses are different from num1 and num2 addresses respectively, they are relatively independent spaces. Therefore, the exchange of x and Y does not affect num1 and num2, and x and Y will be destroyed after the Swap function call.

Address call

① 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 true relationship between the function and the variables outside the function, that is, the function can be operated directly
As an external variable of a function.

Or write a function that exchanges two numbers.

#include<stdio.h>
void Swap2(int* px, int* py)
{
	int temp = 0;
	temp = *px;
	*px = *py;
	*py = temp;
}
int main()
{
	int num1 = 1;
	int num2 = 2;
	printf("Before exchange::num1 = %d num2 = %d\n", num1, num2);
	Swap2(&num1, &num2);
	printf(" Swap2::num1 = %d num2 = %d\n", num1, num2);
	return 0;
}


It can be seen from the monitoring during debugging that px and px are pointer variables, in which the addresses (i.e. pointers) of num1 and num2 are stored, * is a dereference operator, which is used to find the variables stored in the address through the address. For example, px is the pointer variable of num1, and its value is the address (pointer) of num1, * px - find the variable num1 stored in the address through the address of num1, Finally, you can assign a value to it.
Address calling enables variables num1 and num2 to exchange.

5. Nested call and chained access of functions

Nested Call

Functions and functions can be organically combined.

#include<stdio.h>
void new_line()
{
	printf("hello world!\n");
}
void three_line()
{
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		new_line();
	}
}
int main()
{
	three_line();
	return 0;
}


Call three in the main function_ Line function, three_ Calling new_ in line function Line function, this "doll" is a nested call.

Chain access

Take the return value of one function as an argument to another function.

Find the length of a string:

Using chain access, it should be written as follows:

The return value of the strlen function is used as an argument to the printf function.

Learn more about chained access:

#include<stdio.h>
int main()
{
	printf("%d", printf("%d", printf("%d", 43)));
	return 0;
}


This program actually takes the return value of the printf function as the parameter of the printf function.
stay cplusplus.com Finding printf function

The return value of the printf function is the total number of characters.

Program analysis: the innermost printf function prints 43, the second layer printf function prints the return value of the innermost printf function ("2 characters of 43"), the outermost printf function prints the return value of the second layer printf function ("1 character of 2"), and "4321" is displayed at the end.

6. Function declaration and definition

Function declaration:

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

Function definition:

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

The difference between the two: the declaration is like a trailer, telling the compiler that there is this function, but there is only its table; The definition is a positive film, which explains the specific operation content of the function and injects the soul into the function.

#include<stdio.h>
int Add(int x, int y);//Function declaration
int main()
{
	int a = 0;
	int b = 0;
	int sum = 0;
	scanf("%d %d", &a, &b);//function call
	sum = Add(a, b);
	printf("sum = %d\n", sum);
	return 0;
}
int Add(int x, int y)//Function definition
{
	return x + y;
}

If the function declaration part is removed:

Without the function declaration, the compiler reads the function call and does not know the function, so the compiler will report an error.

In order to solve the omission or removal of the function declaration part, we can put the function definition part in front of the function call. Because the compiler reads the code from top to bottom.

Where is the function declaration?
Generally speaking, the function declaration is placed in the header file, because the compilation process of the program loads the contents of the header file first.

The function definition is written in the. c file

7. Function recursion

What is recursion?

Recursion: a procedure or function that 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, and the recursive strategy only needs a few programs. Describe the multiple repeated calculations required in the problem-solving process, which greatly reduces the amount of code in the program.
Main way of thinking: make big things small

Two necessary conditions for recursion

  • There is a constraint. When this constraint is met, recursion will not continue.
  • After each recursive call, it gets closer and closer to this limit.

For example: call the main function with the main function

#include<stdio.h>
int main()
{
	printf("hello world!\n");
	main();
	return 0;
}


Run result: print "hello world!" until the stack overflows.
What is stack overflow?
First, when the function is called, it requests space from memory. The programming memory is divided into three parts: stack area, heap area and static storage area.
As shown in the figure:

Each function call needs to allocate a certain space in the stack area. As the number of calls increases, the space in the stack area decreases. Finally, the space in the stack area is exhausted, which is stack overflow.

Exercise 1: (drawing explanation)

Accept an integer value (unsigned) and print its bits in order. For example: input: 123, output 1, 2, 3

Reference code:

#include<stdio.h>
void print(int n)
{
	if (n / 10)
	{
		print(n / 10);
	}
	printf("%d ", n % 10);
}
int main()
{
	unsigned int num = 0;
	scanf("%d", &num);
	print(num);
	return 0;
}

Program analysis:
123 modulo gives 3123 divided by 10 gives 12, so modulo 10 divided by 10 gives each digit.
print(123)—>print(12) 3—>print(1) 2 3—>1 2 3.

Note: 1. There should be restrictions and the restrictions should be approached recursively every time.
2. The number of recursion should not be too many to avoid stack overflow.
Exercise 2: (drawing and explanation)

Writing a function is not allowed to create a temporary variable to find the length of the string.

If temporary variables are allowed:

#include<stdio.h>
int my_strlen(char *s)
{
	int count = 0;
	while (*s != '\0')
	{
		count++;
		s++;
	}
	return count;
}
int main()
{
	char arr[20] = "hello world";
	int len = my_strlen(arr);
	//The address of the first element of the array is passed
	printf("%d", len);
	return 0;
}

Instead of creating temporary variables, use recursion:

#include<stdio.h>
int my_strlen(char *s)
{
	if (*s != '\0')
		return 1 + my_strlen(s + 1);
	else
		return 0;
}
int main()
{
	char arr[20] = "xin";
	int len = my_strlen(arr);
	printf("%d", len);
	return 0;
}

Program analysis:
If the first character is not '\ 0', let the pointer variable + 1 jump to the next character until '\ 0' is found and return 0

Character pointer variable + 1, skip back 1 byte
Integer pointer variable + 1, skip back 4 bytes
Different pointer variable types + 1 have different bytes to jump back, but they all jump back one element

Function iteration

Iteration: the process of repeatedly executing a series of operation steps (loops) to find the following quantities from the previous quantities in turn. Each result of this process is obtained by performing the same operation steps as the previous result.

Exercise 3: (drawing explanation)

Find the factorial of n. (overflow is not considered)

Method 1: function iteration

#include<stdio.h>
int Fac(int n)
{
	int i = 0;
	int y = 1;
	for (i = 1; i <= n; i++)
	{
		y = y * i;//Variable y not only participates in the operation, but also saves the result. The currently saved result is the initial value of the next cycle calculation
	}
	return y;
}
int main()
{
	int n = 0;
	int ret = 0;
	printf("Please enter an integer:>\n");
	scanf("%d", &n);
	ret = Fac(n);
	printf("%d The factorial of is%d", n, ret);
	return 0;
}

Method 2: function recursion

#include<stdio.h>
int Fac(int n)
{
	if (n > 1)
	{
		return n * Fac(n - 1);
	}
	else
		return 1;
}
int main()
{
	int n = 0;
	int ret = 0;
	printf("Please enter an integer:>\n");
	scanf("%d", &n);
	ret = Fac(n);
	printf("%d The factorial of is%d", n, ret);
	return 0;
}

Program analysis:

Exercise 4:

Find the nth Fibonacci number. (overflow is not considered)

Fibonacci Number: from the third number, each number is equal to the sum of the first two numbers.

Function iteration:

#include<stdio.h>
int Fib(int n)
{
	int a = 1;
	int b = 1;
	int c = 1;
	while (n > 2)
	{
		c = a + b;
		a = b;
		b = c;
		n--;
	}
	return c;
}
int main()
{
	int n = 0;
	int ret = 0;
	scanf("%d", &n);
	ret = Fib(n);
	printf("%d", ret);
	return 0;
}

The last a becomes b, the last b becomes c, and so on.

Function recursion:

#include<stdio.h>
int Fib(int n)
{
	if (n > 2)
	{
		return Fib(n - 1) + Fib(n - 2);
	}
	else
		return 1;
}
int main()
{
	int n = 0;
	int ret = 0;
	scanf("%d", &n);
	ret = Fib(n);
	printf("%d", ret);
	return 0;
}

But we will find the problem:
When n is very large, the program efficiency is very low or even crashes. Because many calculations are repeated when calling the Fib function.
As shown in the figure, for example, n=50

You can see that 47 is calculated three times. With recursion, the number is split smaller and the repeated calculation is more.
We can add the measurement count variable to test:

When Fib(2) is calculated, count + +. It can be seen that Fib(2) has been calculated 514229 times in total! The efficiency is obviously low.
Moreover, when Fib() calls enough, the stack area cannot reallocate space, which will lead to stack overflow (mentioned earlier).
Therefore, in contrast, the iterative method is more efficient. It only needs n-2 times to calculate a number, and redundant calculations will not be repeated.

The difference and advantage of function recursion and iteration

1. Some problems are explained in recursive form, just because it is clearer than non recursive form.
2. The iterative implementation of some problems is often more efficient than the recursive implementation, but the readability of the code is slightly worse.
3. When a problem is quite complex and difficult to implement iteratively, the simplicity of recursive implementation can compensate for the runtime overhead.

Several classic topics of function recursion (independent research):

  1. Hanoi Tower problem
  2. Frog jumping steps

Function sub file writing

When writing a program to realize the calculation of addition, subtraction, multiplication and division, I believe everyone will write it in a. c file, write the main function, and then write the addition, subtraction, multiplication and division functions. Of course, simple code can be like this, but when the amount of code of each function is large, or multiple people need to cooperate to complete it, the efficiency will be greatly reduced if it is written in the same. c file. At this time, it is necessary to write the function in separate files.
Benefits of sub file programming:

  • Modular programming idea
  • The main function code is concise and clear
  • Each module is convenient for debugging
  • Clear division of functions and responsibilities, such as writing A game, interface to A, time delay to B, image size to C

Note:

1. Generally, the function declaration and function definition are written separately. The function declaration is placed in the header file (. h) and the function definition is placed in the source file (. c) to prevent compilation errors
2. Calling the function requires a header file, that is, include "header file name. h"

Assuming that the addition, subtraction, multiplication and division functions are complex functions, they need to be written in separate files. As follows:
Write the source files and header files of each function respectively, and finally quote their header files in the main function.
Add.h

Add.c

Main function

Posted by balsdorf on Sun, 26 Sep 2021 21:00:59 -0700