Detailed explanation of C language functions (with exercises!!)

1. What is a function?

We often see the concept of function in mathematics. But do you know the functions in C language?
Wikipedia definition of function: Subroutine
In computer science, subroutine, procedure , function, routine, method,
subprogram, callable unit) is a certain part of the code in a large program, which is composed of one or more statement blocks
. It is responsible for completing a specific task and is relatively independent from other code.
Generally there will be input parameters and return values, providing encapsulation and hiding of details of the process. These codes are usually integrated into software libraries

2. Classification of functions in C language

2.1 Library functions

Why are there library functions?
1. We know that when we learn C language programming, we always want to know the result after writing a code and want to
print the result. Check it out on our screens. At this time, we will frequently use a function: printing information to the screen in a certain format (printf). 2. During the programming process, we will frequently copy strings (strcpy). 3. In programming, we also calculate, and we always calculate operations such as n raised to the kth power (pow). Like the basic functions we described above, they are not business code. Every programmer may use it during our development process. In order to support portability and improve program efficiency, the basic library of C language provides a series of similar libraries. Functions to facilitate programmers in software development. So how to learn library functions? Let’s take a brief look here: www.cplusplus.com








Let’s refer to the documentation and learn several library functions: A brief summary, the commonly used library functions in C language are:
1. IO function
2. String operation function
3. Character operation function
4. Memory operation function
5. Time/date function< /span> Let’s refer to the documentation to learn several library functions: 7. Other library functions
6. Mathematical functions

strcpy

char * strcpy ( char * destination, const char * source );

memset

void * memset ( void * ptr, int value, size_t num );

Note:
But a secret that library functions must know is: when using library functions, they must include #include Corresponding header file.
Here we refer to the documentation to learn the above library functions in order to master the usage of the library functions.

2.1.1 How to learn to use library functions?

Do you need to remember them all? No
You need to learn how to use the query tool:
MSDN (Microsoft Developer Network)
www.cplusplus.com
http://en.cppreference.com(English version)
http://zh.cppreference.com
< a i=7>(Chinese version) English is very important. At the very least, you have to understand the literature.

2.2 Custom functions

If library functions can do everything, what do programmers need to do?
All the more important are custom functions.
Custom functions are the same as library functions, with function name, return value type and function parameters.
But the difference is that we design these ourselves. This gives programmers a lot of room to play.
Function composition:

ret_type fun_name(para1, * )
{
    statement;//语句项
}
//ret_type 返回类型
//fun_name 函数名
//para1   函数参数

Let’s give an example:
Write a function to find the maximum of two integers.

#include <stdio.h>

//get_max函数的设计
int get_max(int x, int y)
{
    return (x>y)?(x):(y);
}
int main()
{
    int num1 = 10;
    int num2 = 20;
    int max = get_max(num1, num2);
    printf("max = %d\n", max);
    return 0;
}

Another example:
Write a function to exchange the contents of two integer variables.

#include <stdio.h>
//实现成函数,但是不能完成任务
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 num1 = 1;
    int num2 = 2;
    Swap1(num1, num2);
    printf("Swap1::num1 = %d num2 = %d\n", num1, num2);
    Swap2(&num1, &num2);
    printf("Swap2::num1 = %d num2 = %d\n", num1, num2);
    return 0;
}

3. Function parameters

3.1 Actual parameters (actual parameters):

The parameters actually passed to the function are calledactual parameters.
Actual parameters can be: constants, variables, expressions, functions, etc.
No matter what type of quantity the actual parameters are, they must have definite values ​​when making function calls so that these values ​​can be transferred to the formal parameters
.

3.2 Formal parameters (formal parameters):

Formal parameters refer to the variables in parentheses after the function name. Because formal parameters are only instantiated (memory
allocated) when the function is called, they are called formal parameters. parameter. Formal parameters are automatically destroyed after the function call is completed. Therefore formal parameters are only valid within functions.

Top surface Swap1 Sum Swap2 Function middle index < /span> This is the analysis of the actual function of the Japanese form: . the actual numberis& num1 , &num2 Functional Swap2 和传给 num2 ,num1 Swap1. In the main function format countTorex, y, px, py

Here you can see that when the Swap1 function is called, x and y have their own space and have the same content as the actual parameters.
So we can simply think: After the formal parameter is instantiated, it is actually equivalent to a temporary copy of the actual parameter .

4. Function call:

4.1 Call by value

The formal parameters and actual parameters of a function occupy different memory blocks respectively, and modifications to the formal parameters will not affect the actual parameters.

4.2 Call by address

        Calling by address is a way of calling a function by passing the memory address of the variable created outside the function to the function parameter.
This method of passing parameters can establish a real connection between the function and the variables outside the function, that is, the variables outside the function can be directly manipulated
inside the function.

5. Nested calls and chained access of functions

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

5.1 Nested calls

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

Functions can be called nested, but not defined.

5.2 Chain access

Use the return value of one function as a parameter of another function.

#include <stdio.h>
#include <string.h>
int main()
{
    char arr[20] = "hello";
    int ret = strlen(strcat(arr,"bit"));//这里介绍一下strlen函数
    printf("%d\n", ret);
    return 0;
}
#include <stdio.h>
int main()
{
    printf("%d", printf("%d", printf("%d", 43)));
    //结果是啥?
    //注:printf函数的返回值是打印在屏幕上字符的个数
    return 0;
}

6. Declaration and definition of functions

6.1 Function declaration:

1. Tell the compiler what the function is called, what the parameters are, and what the return type is. But whether it exists or not cannot be determined by the function
declaration.
2. The declaration of a function generally appears before the use of the function. To satisfydeclare first and then use.
3. The function declaration is generally placed in the header file.

6.2 Function definition:

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

Contents of test.h
Place function declaration

#ifndef __TEST_H__
#define __TEST_H__
//函数的声明
int Add(int x, int y);

#endif //__TEST_H__

Contents of test.c
Implementation of placement function

#include "test.h"
//函数Add的实现
int Add(int x, int y)
{
    return x+y;
}

This writing form of divided files is written in modules when playing Three-Character Chess and Minesweeper.

7. Function recursion

7.1 What is recursion?

The programming technique in which a program calls itself is calledrecursion (recursion).
Recursion as an algorithm is widely used in programming languages. A process or function has a direct or indirect
call to itself in its definition or description.
A method that usually transforms a large and complex problem into layers. To solve a smaller problem similar to the original problem,
recursive strategy
requires only a small number of programs to describe what is needed to solve the problem Repeating calculations multiple times greatly reduces the amount of code in the program.
The main way of thinking about recursion is: Make big things small

7.2 Two necessary conditions for recursion

·There is a restriction condition. When this restriction condition is met, the recursion will not continue.
· Each recursive call gets closer and closer to this limit.

7.2.1 Exercise 1:

accepts an integer value (unsigned) and prints each bit of it in sequence.
For example:
Input: 1234, output 1 2 3 4.

Reference Code:

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

7.2.2 Exercise 2:

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

Reference Code:

#incude <stdio.h>
int Strlen(const char*str)
{
    if(*str == '\0')
      return 0;
    else
      return 1+Strlen(str+1);
}
int main()
{
    char *p = "abcdef";
    int len = Strlen(p);
    printf("%d\n", len);
    return 0;
}

7.3 Recursion and iteration

7.3.1 Exercise 3

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

Reference Code:

int factorial(int n)
{
    if(n <= 1)
      return 1;
    else
      return n * factorial(n-1);
}

7.3.2 Exercise 4:

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

Reference Code:

int fib(int n)
{
    if (n <= 2)    
      return 1;
    else
      return fib(n - 1) + fib(n - 2);
}

But we found that has a problem;
When using the fib function, if we want to calculate the 50 Fibonacci numbers are particularly time-consuming.
If you use the factorial function to find the factorial of 10000 (regardless of the correctness of the result), the program will crash.

why?

We found that many calculations of the fib function are actually repeated during the calling process.
If we modify the code:

int count = 0;//全局变量
int fib(int n)
{
    if(n == 3)
      count++;
    if (n <= 2)    
      return 1;
    else
      return fib(n - 1) + fib(n - 2);
}

Finally, we output the count, which is a very large value.
So how can we improve?
When debugging the factorial function, if your parameters are relatively large, an error will be reported: stack overflow (stack overflow)
Such information.

The stack space allocated by the system to the program is limited, but if an infinite loop or (dead recursion) occurs, this may lead to a
direct allocation of stack space, eventually resulting in When the stack space is exhausted, this phenomenon is called stack overflow.

So how to solve the above problems:

1. Rewrite recursion into non-recursion.
2. Use static objects instead of nonstatic local objects. In the design of recursive functions, static objects can be used instead of nonstatic local objects (that is, stack objects). This not only reduces the overhead of generating and releasing nonstatic objects during each recursive call and return, but also static The object can also save the intermediate state of recursive calls and can be accessed by each calling layer. For example, the following code is implemented in a non-recursive way:

//求n的阶乘
int factorial(int n)
{
    int result = 1;
    while (n > 1)
   {
      result *= n ;
      n -= 1;
   }
    return result;
}
//求第n个斐波那契数
int fib(int n)
{
  int result;
  int pre_result;
  int next_older_result;
  result = pre_result = 1;
  while (n > 2)
  {
     n -= 1;
     next_older_result = pre_result;
     pre_result = result;
     result = pre_result + next_older_result;
  }
  return result;
}

hint:

1. Many problems are explained in recursive form simply because it is clearer than the non-recursive form.
2. However, iterative implementation of these problems is often more efficient than recursive implementation, although the code is slightly less readable.
3. When a problem is too complex to be implemented iteratively, the simplicity of the recursive implementation can compensate for the runtime overhead it brings.
Several classic questions about function recursion:
1. Tower of Hanoi problem
2. Frog jumping steps problem

Guess you like

Origin blog.csdn.net/A1546553960/article/details/132948029