C learning_10 (Nested call and chain access of functions, declaration and definition of functions, function recursion)

Table of contents

Nested calls and chained access of functions

nested calls

Functions can be called nestedly, can they be defined nestedly?

chain access

Function declaration and definition

statement

definition

function recursion

Two necessary conditions for recursion


Nested calls and chained access of functions

nested calls

        Function nested calling refers to calling another function in one function, and another function is called in the called function, and so on, forming a call relationship in which multiple functions are nested with each other. In programming, function nested calls can improve the flexibility and maintainability of the code, make the program structure clearer, and make the code reuse more.

#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;
}

        The function of this code is to output three lines of "hello world!". The specific explanation is as follows:

1. A function named new_line() is defined. The function of this function is to output a line of "hello world!" and add a newline character "\n" at the end of the line.

2. A function named three_line() is defined. The function of this function is to call the new_line() function three times to output three lines of "hello world!".

3. In the main function, the three_line() function is called, which realizes the function of outputting three lines of "hello world!".

4. The return value of the entire program is 0, indicating that the program ends normally.

        In this program, an example of function nested calls is that the three_line() function calls the new_line() function. Through the nested call of the function, the code has a better organizational structure, making the program easier to read and maintain.

Functions can be called nestedly, can they be defined nestedly?

#include<stdio.h>
void test()
{
	printf("hello world!\n");
	void test2()
	{
		printf("hello today!\n");
	}
}
int main()
{
	test();
}

        In this code, two functions test() and test2() are defined, and the test2() function is defined in the test() function, which is called a nested function. However, nested functions are not supported in the C language, so an error will occur when compiling this code.

Summary: Functions can be called nestedly, but not defined nestedly.

chain access

        Chained access is to use the return value of one function as the parameter of another function.

#include<stdio.h>
#include<string.h>
int main()
{
	//strlen - 求字符串的长度(不包括'\0')
	printf("%d\n",strlen("abcdef"));
	return 0;
}

        In this program, the return value of the strlen function is passed to the printf function as a parameter to realize the chain access of the function.

Note: The standard library function `strlen` calculates the length of the string, it does not include the `\0` at the end of the string.

Next let's look at a code

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

To explain this question, we need to understand what is the return value of the printf function?

The printf function returns the number of characters written.

#include<stdio.h>
int main()
{
    int ret = printf("%d ", 100);

    printf("%d",ret);//3
    return 0;
}

Now let's explain the above topic

The program output will output: 4321

        The body of the program is a `main()` function, which calls three nested `printf()` functions, and uses a format string for output.

1. The innermost `printf()` function outputs the number 43, and returns a value, which is the number of characters formatted and output to the screen, that is, the return value 2, indicating that two characters are output, namely '4 ' and '3'.

2. The parameter of the outer `printf()` function is the return value of the innermost `printf()` function, which is 2. Therefore, the outer `printf()` function prints out the number 2 and returns a value, which is the number of characters formatted and output to the screen, that is, the return value 1 means that a character is output, namely '2'.

3. The parameter of the outermost `printf()` function is the return value of the middle layer `printf()` function, which is 1. So the outermost `printf()` function just prints out a number 1 and returns a value, but no printf function receives the return value.

      Finally, the program returns 0, indicating a normal end.

What does the output look like when we add a space after each %d?

#include<stdio.h>
int main()
{

    printf("%d ", printf("%d ", printf("%d ", 43)));//Note that there is a space behind %d
    return 0;
}

The program output would output: 43 3 2

        The body of the program is a `main()` function, which calls three nested `printf()` functions, and uses a format string for output.

1. The innermost `printf()` function outputs the number 43 with a space behind it, and then returns a value, which is the number of characters formatted and output to the screen, that is, the return value 3, which means Three characters are output, namely '4', '3' and 'space'.

2. The parameter of the outer `printf()` function is the return value of the innermost `printf()` function, which is 3. Therefore, the outer `printf()` function prints the number 3 with a space behind it, and then returns a value, which is the number of characters formatted and output to the screen, that is, the return value 2, indicating the output two characters, namely '2' and 'space'.

3. The parameter of the outermost `printf()` function is the return value of the middle layer `printf()` function, which is 2. So the outermost `printf()` function just prints out a number 2, appends a space after it, and returns a value, but no printf function receives the return value.

      Finally, the program returns 0, indicating a normal end.

Function declaration and definition

statement

        In the C language, function declaration refers to telling the compiler the name, parameter type, and return value type of the function before the function is used, so that the compiler can correctly compile the use of the function when compiling. Function declarations are generally placed in header files.

        A function declaration usually consists of the following parts:

1. Return type: The return value type of the function, which can be `void`, which means no return value, or any basic data type, such as `int`, `float`, `double`, etc.

2. Function name: the name of the function, used to call the function in the program.

3. Parameter list: the data type and name of the parameters accepted by the function, and the number of parameters can be 0 or more.

A typical function declaration has the following form:

        return-type function-name(parameter-list);

For example, here is the declaration of a sum function:

        int sum(int a, int b);

The return type of this function is `int`, the function name is `sum`, and the parameter list contains two parameters `a` and `b` of type `int`.

        Therefore, if you want to call this function in a program, you need to provide two parameters of type `int`, and assign the return value of this function to a variable of type `int`.

definition

        In C language, function definition refers to realizing the specific function of a function, that is, writing the code in the function body.

A function definition consists of the following parts:

1. Function header: Similar to the function declaration, the function header includes the return type, function name and parameter list. In a function definition, the parameter names in the parameter list can be different from those in the function declaration, but the parameter types must be the same.

2. Function body: The function body is the specific code of the function implementation, which includes the parameters and local variables defined in the function declaration, as well as the executed statement and return value.

A typical function definition has the following form:

        return type function name (argument list)

        {    

                // function body    

                return return value;

        }

For example, here is the definition of a sum function:

        int sum(int a, int b)

        {    

                int result = a + b;    

                return result;

        }

        The return type of this function is `int`, the function name is `sum`, and the parameter list contains two parameters `a` and `b` of type `int`. In the function body, first define an integer variable `result`, then assign the result of adding `a` and `b` to `result`, and finally use the `return` keyword to return the value of `result`. If you want to call this function in a program, you need to provide two parameters of type `int`, and assign the return value of this function to a variable of type `int`.

Summary: Functions must be declared before they are used.

function recursion

        Recursion is a method of solving a problem by calling itself. In computer science, recursion is a commonly used algorithm that simplifies the way problems are solved. In the process of recursion, the problem is continuously decomposed into smaller problems, and the problem is solved through the return value of the recursive function.

        A recursive function usually consists of two parts: a base case and a recursive case. The base case is the condition for the recursion to end. When the base case is met, the recursive function no longer calls itself, but returns a fixed value. The case of recursion is recursion itself, i.e. a recursive function calls itself and breaks down the problem into smaller subproblems.

        The calling process of a recursive function is a stack process. Each time a recursive function is called, the execution state of the current function will be saved in the stack. With the end of each recursive function call, the function execution state saved in the stack will also be sequentially Pop until the last recursive function call ends and returns the result.

         The main way of thinking about recursion is: to make big things small

Two necessary conditions for recursion

1. There are restrictions. When the restrictions are met, the recursion will not continue.

2. After each recursive call, the limit is getting closer and closer.

Let's look at a piece of code to help us understand the recursive algorithm

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

1. In the `main` function, we define a `unsigned int` variable `num`, and use the `scanf` function to input an integer "1234" from the console, and assign it to `num`.

2. Then, we called the `print` function and passed `num` as a parameter.

3. In the `print` function, we first make a conditional judgment: if `n>9`, it means that the number has at least two digits, and the next recursive call is required.

4. When `n>9` is established, we call `print` function and pass `n/10` as a parameter, the value of this parameter is `1234/10=123`.

5. In the new `print` function, we also make a conditional judgment and find that `123>9` needs to call the function recursively.

6. We continue to call the `print` function and pass it `123/10` as a parameter, which has the value of `12`.

7. In the new `print` function, we also make a conditional judgment and find that `12>9` needs to call the function recursively.

8. We continue to call the `print` function and pass it `12/10` as a parameter, which has a value of `1`.

9. In the new `print` function, we also make a conditional judgment and find that `1<=9`, proceed to the next step directly.

10. Since `n<=9` holds true, we print out the value of `n%10`, that is, `1%10=1`.

11. Because the print value of the last recursive call is 1, so `n=12` in the current recursion, continue to print the value of `n%10`, that is, `12%10=2`.

12. Because the print value of the last recursive call is 2, so `n=123` in the current recursion, continue to print the value of `n%10`, that is, `123%10=3`.

13. Because the print value of the last recursive call is 3, so `n=1234` in the current recursion, continue to print the value of `n%10`, that is `1234%10=4`.

14. Since the last recursive call has been completed, the program returns to the `main` function, and ends the execution of the program with the `return 0` statement.

        Summary: This recursive algorithm realizes the printing of numbers by continuously dividing the input numbers by 10 and rounding down, and then taking the remainder. Specifically, each recursive call will print out the single digit of the number, then return to the previous recursive call, and print the values ​​of the remaining digits in turn, and finally realize the digital output. The following figure matches our understanding.

Next, let's look at a few more codes

        1. Writing a function does not allow the creation of temporary variables to find the length of the string.

Let’s first look at how to find the length of a string without creating a temporary variable

#include<stdio.h>
int my_strlen(char* s)
{
	int count = 0;
	while (*s != '\0')
	{
		count++;
		s++;
	}
	return count;
}
int main()
{
	char arr[] = "abc";
	//[a b c \0]
	/*
		库函数求字符串的长度
		int len = strlen(arr);
		printf("%d\n", len);
	*/
	printf("%d\n", my_strlen(arr));
	return 0;
}

        First, a character array arr is defined in the main function and initialized to "abc". Note that the string ends with '\0' , which means the end of the string, so "abc" is actually composed of letters a, b, c and a '\0'.

        Call the custom function my_strlen() in the main function. The parameter of this function is also a character pointer, pointing to the string whose length is to be calculated. A counter count is defined inside the function and initialized to 0. Then use the while loop to traverse the string, and increment the counter every time a character is encountered. In this way, calling my_strlen(arr) will return the length of the string "abc", which is 3.

Then write the code for this question according to the requirements of the topic.

#include<stdio.h>
//递归
/*
	my_strlen("abc")
	1+my_strlen("bc")
	1+1+my_strlen("c")
	1+1+1+my_strlen("")
	1+1+1+0
	3
*/
int my_strlen(char* s)
{
	if (*s == '\0')
		return 0;
	else
		return 1 + my_strlen(s+1);
}
int main()
{
	char arr[] = "abc";
	printf("%d\n", my_strlen(arr));
	return 0;
}

int my_strlen(char* s)

{  // Define a function called my_strlen that accepts a pointer s to an array of chars.   

        if (*s == '\0')  // If the current character pointed to by the pointer s is '\0', that is, the end of the string, then return 0, indicating that the length of the string is 0.        

                return 0;    

        else  // If the pointer s is not pointing to '\0', execute the following code.        

                return 1 + my_strlen(s+1);  // Return 1 (representing the length of the current character) plus recursively call the my_strlen() function and pass in the pointer s+1 of the next character.

}

1. When we call the my_strlen function for the first time, the first address of the string is passed in, that is, s points to the first character 'a' of the string.

2. Inside the function, first check whether the current character pointed to by s is '\0', that is, the end of the string. Since the current character is 'a', not '\0', enter the else branch.

3. In the else branch, the function returns 1 + my_strlen(s+1). We pass in s+1, which is the pointer to the next character 'b' of the string, and call the my_strlen function recursively.

4. When the my_strlen function is called for the second time, the pointer s pointing to 'b' is passed in. Since 'b' is not the end of the string, the function goes to the else branch again and returns 1 + my_strlen(s+1). We pass in s+1 again, pointing to the next character 'c' in the string, and call the my_strlen function recursively.

5. When the my_strlen function is called for the third time, the pointer s pointing to 'c' is passed in. Also because 'c' is not the end of the string, the function enters the else branch again and returns 1 + my_strlen(s+1). We pass in s+1 again, pointing to '\0', and recursively call the my_strlen function.

6. When the my_strlen function is called for the fourth time, the pointer s pointing to '\0' is passed in. Since '\0' is the end of the string, the function goes to the if branch and returns 0.

7. Then the my_strlen function of the upper layer receives the return value 0, and adds 1 to it, that is, 1 + 0 = 1, indicating that the string length is 1. This return value is returned again to the higher-level function, that is, the function that calls the my_strlen function for the second time.

8. The second call to the my_strlen function receives the return value 1, and adds 1 to it, that is, 1 + 1 = 2, indicating that the string length is 2. This return value is returned again to the higher-level function, that is, the function that first called the my_strlen function.

9. The first call to the my_strlen function receives the return value 2, and adds 1 to it, that is, 1 + 2 = 3, indicating that the string length is 3.

Finally, 3 is returned to the main function and output on the screen. In this way, using the recursive function, we have calculated the length of the string "abc", which is 3.

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

Let's take a look at our previous writing

#include<stdio.h>
int Fac(int n)
{
	int i = 0;
	int result = 1;
	for (i = 1; i < n + 1; i++)
	{
		result *= i;
	}
	return result;
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = Fac(n);
	printf("%d\n", ret);
	return 0;
}

        First, the program includes a header file <stdio.h>, which is a header file in the C language standard library and provides a series of functions related to input and output, such as printf() and scanf().

        Next is to define the function Fac (), the parameter of this function is an integer n, returns an integer. Two variables i and result are defined inside the function, which are used for the loop count and the multiplication of the final result respectively. Among them, the loop structure adopts a for loop, and the loop condition is that i is less than n plus 1, that is, the multiplication operation is performed one by one from 1 to n. The result is multiplied by the value of i in each loop, and the final result is the factorial of n. Finally, return the result through the return statement. ,

        In the main function main(), an integer n is first defined for receiving user input. Assign the integer entered by the user to the variable n through the scanf() function. Next, call the Fac() function, pass n as a parameter, and get the calculation result. Finally, the result is output through the printf() function, and 0 is returned to indicate that the program ends normally.

        Overall, this program is relatively simple, by using ( iterative ) loops and functions to achieve the function of calculating the factorial of n.

Then write the code for this question according to the requirements of the topic.

#include<stdio.h>
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;
}

        This is a program to calculate factorial. Unlike the previous program, this program is implemented in a recursive manner.        

        First, the program includes a header file <stdio.h>, which is a header file in the C language standard library and provides a series of functions related to input and output, such as printf() and scanf().        

        Next is to define the function Fac (), the parameter of this function is an integer n, returns an integer. The function uses a recursive method to calculate the factorial. When n is less than or equal to 1, return 1 directly, otherwise return the result of multiplying n by Fac(n-1), that is, convert the problem into calculating the factorial of (n-1) and multiply it by n. This is the process of recursion.

        In the main function main(), an integer n is first defined for receiving user input. Assign the integer entered by the user to the variable n through the scanf() function. Next, call the Fac() function, pass n as a parameter, and get the calculation result. Finally, the result is output through the printf() function, and 0 is returned to indicate that the program ends normally.

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

        The Fibonacci sequence means that each subsequent number is the sum of the previous two numbers.

        That is: 1, 1, 2, 3, 5, 8, 13, 21, 34, ...

        The Fibonacci sequence can be defined recursively, namely: F(1) = 1 ; F(2) = 1 ; F(n) = F(n-1) + F(n-2) (n > = 2) Among them, F(1) and F(2) are the initial values, and each subsequent number is the sum of the previous two numbers.

       The program first includes the header file <stdio.h>, which is a header file in the C language standard library and provides a series of functions related to input and output, such as printf() and scanf().

        Next is to define the function Fib(), which takes an integer n and returns an integer. The function uses a recursive method to calculate the Fibonacci sequence. When n is less than or equal to 2, return 1 directly, otherwise return the result of Fib(n-1) plus Fib(n-2), that is, transform the problem into calculating the Fibonacci of (n-1) and (n-2) The sum of the sequence of deeds. This is the process of recursion.

        In the main function main(), an integer n is first defined for receiving user input. Assign the integer entered by the user to the variable n through the scanf() function. Next, call the Fib() function, pass n as a parameter, and get the calculation result. Finally, the result is output through the printf() function, and 0 is returned to indicate that the program ends normally.

        This example is relatively simple, but it is not the best way to calculate the Fibonacci sequence by recursion, because it has the problem of repeated calculation , so in practical applications, more loops are used to calculate Fibonacci sequence.

Cycle mode:

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

        The program first includes the header file <stdio.h>, which is a header file in the C language standard library and provides a series of functions related to input and output, such as printf() and scanf().

        Next is to define the function Fib(), which takes an integer n and returns an integer. The function uses a loop to calculate the Fibonacci sequence. First, three integers a, b, and c are defined, and a, b, and c are initialized to 1, indicating the initial value of the Fibonacci sequence. Then through the while loop, when n is greater than or equal to 3, calculate the value of c equal to a plus b, and then assign the values ​​of a and b to b and c respectively, that is, the problem is transformed into calculating the next Fibonacci sequence value. When n is less than 3, the loop ends and returns the value c of the last Fibonacci sequence.

        In the main function main(), an integer n is first defined for receiving user input. Assign the integer entered by the user to the variable n through the scanf() function. Next, call the Fib() function, pass n as a parameter, and get the calculation result. Finally, the result is output through the printf() function, and 0 is returned to indicate that the program ends normally.

        Using the loop method to calculate the Fibonacci sequence, compared with the recursive method, will not cause the problem of stack overflow, and the code execution efficiency is higher, so in practical applications, more loops are used to calculate Fibonacci Nach sequence.

Summarize:

        1. Many problems are explained in a recursive form simply because it is clearer than a non-recursive form.

        2. However, the iterative implementation of these problems is often more efficient than the recursive implementation, although the readability of the code is slightly worse.

        3. When a problem is too complex to implement iteratively, the simplicity of recursive implementation can compensate for the runtime overhead it brings.

Guess you like

Origin blog.csdn.net/qq_64446981/article/details/130409091