【C】函数真的难嘛?其实一点也不难,原理很简单。

简介: # 什么是函数程序是由多个零件组合而成的,而函数就是这种“零件”的一个较小单位。## main函数和库函数C语言程序中,main函数是必不可少的。程序运行的时候,会执行main函数的主题部分。main函数中使用了printf、scanf、puts等函数。由C语言提供的这些为数众多的函数称为库函数。## 什么是函数当然,我们也可以自己创建函数。而实际上,我们也必须亲自动手创建各种函数。下面我们来自己创建一个简单的函数。创建一个函数,接收两个整数参数,返回较大整数的值。printf函数和scanf函数等创建得比较好得函数,即使不知道其内容,只要了解使用方法,也可以轻松使用。## 函

什么是函数

程序是由多个零件组合而成的,而函数就是这种“零件”的一个较小单位。

main函数和库函数

C语言程序中,main函数是必不可少的。程序运行的时候,会执行main函数的主题部分。main函数中使用了printf、scanf、puts等函数。由C语言提供的这些为数众多的函数称为库函数。

什么是函数

当然,我们也可以自己创建函数。而实际上,我们也必须亲自动手创建各种函数。下面我们来自己创建一个简单的函数。
创建一个函数,接收两个整数参数,返回较大整数的值。
printf函数和scanf函数等创建得比较好得函数,即使不知道其内容,只要了解使用方法,也可以轻松使用。

函数定义

首先来说下函数的创建方法,这里我们来定义一个名为max2的函数,如下所示:
image.png
这里的函数定义由多个部分构成。

函数头

该部分表示函数的名称和格式。虽然称为头函数,实际上说它是函数的“脸”可能更加的合适。

返回类型

函数返回的值——返回值的类型。该函数的情况下,返回的是两个int型数值中较大的一个,所以其类型是int。

函数名

函数的名称。从其他零件调用函数时,使用函数名。

形参声明

小括号括起来的部分,是用于接收辅助性提示的变量——形式参数的声明。

函数体

函数体是复合语句。仅仅在某个函数中使用的变量,原则上应在该函数中声明和使用,但是要注意不能声明和形参同名的变量,否则会发生变量名冲突。

函数调用

下面是使用函数的方法,代码如下:


#include<stdio.h>

int Max(int n, int m)
{
   
   
    if (n>m)
    {
   
   
        return n;
    }
    else
    {
   
   
        return m;
    }
}

int mian()
{
   
   
    int n = 0;
    int m = 0;

    puts("请输入两个整数:");
    printf("整数1:");
    scanf("%d", &n);
    printf("整数2:");
    scanf("%d", &m);

    printf("较大的整数的值是%d\n", Max(n, m));

    return 0;
}

该程序中定义了两个函数Max和mian。程序启动时会执行的时main函数。
运行结果:
image.pngimage.png

  1. 函数的调用形式是在函数后面加上小括号,这个小括号称为函数调用运算符。使用函数调用运算符的表达式就称为函数调用表达式。
  2. 函数调用运算符括起来的是实参,当实参不止一个的时候,要是使用逗号将其分开。
  3. 进行函数调用后,程序的流程将一下子跳转到该函数处,main函数的执行就会中断,直到该函数调用完成之后才会继续执行main函数中的代码。
  4. 进行函数调用后,程序的流程会转到被调用函数处,这时,传递过来的实参值会被赋给函数接收的形参。
  5. 形参的初始化完成后,将执行函数体。在程序中遇到return 语句,或者执行到函数体最后的大括号是,就会从该函数跳到调用函数。

image.png
如上图所示,执行到return b; return语句执行结束后,程序就会返回到原来进行调用的地方,再次执行被中断的main函数。
函数调用运算符的总结如下图:
image.png
函数调用的时候传递的只是函数的参数的值,因此调用函数时使用的实参既可以时变量,也可以是常量。
例如:下面的函数调用,将输出变量n1和5中比较哪一个值大
Max(n1,5);
另外需要注意的是,实参和形参是完全不同的两个东西,因此不用担心实参和形参的名字一样的问题。
上面我还提到了return 语句,它的结构如下图所示;
image.png
函数返回的是“表达式“的值,不能返回两个以上的值。

三个数中的最大值

下面我来说下写求三个整数中的最大值的函数,函数接收的形参,以及函数内定义的变量,都是该函数自己的东西。在函数max3的形参a、b、c和main函数的变量a、b、c虽然名称相同,但是分别是不同的东西。结构如下:
image.png
代码如下:

#include<stdio.h>

//返回三个数中的最大值函数
int max3(int a, int b, int c)
{
   
   
    int max = a;
    if (b>max)
    {
   
   
        max = b;
    }
    if (c>max)
    {
   
   
        max = c;
    }
    return max;
}

int main()
{
   
   
    int a = 0;
    int b = 0;
    int c = 0;

    puts("请输入三个整数。");
    printf("整数1;");
    scanf("%d", &a);
    printf("整数2;");
    scanf("%d", &b);
    printf("整数3;");
    scanf("%d", &c);

    printf("最大值是:%d", max3(a, b, c, ));
    return 0;
}

将函数的返回值作为参数传递个函数

输入两个整数,计算他们的平方差并显示,代码如下:


#include<stdio.h>

//计算整数的平方
int sqr(int a)
{
   
   
    return a * a;
}

//返回差值
int diff(int a, int b)
{
   
   
    return (a > b ? a - b : b - a);
}

int main()
{
   
   
    int x = 0;
    int y = 0;

    puts("请输入两个整数。");
    printf("整数1:");
    scanf("%d", &x);
    printf("整数2:");
    scanf("%d", &y);

    printf("x和y的平方差是%d。\n", diff(sqr(x), spr(y)));
    return 0;
}

运行结果:
image.png
函数sqr会返回形参a所接收值的平方,所以函数调用表达式sqr(x)和sqr(y)的判断结果是16和25,这两个数会被直接作为调用函数diff时的实参传递。因此函数表达式diff(sqr(x),sqr(y))就是diff(16,25),对该表达式进行判断,就会得到函数diff返回的9。

调用其他函数

在自己创建的函数中也可以调用其他函数,求4个数中的最大值代码如下:

#include<stdio.h>

//求两个数最大值
int max2(int x, int y)
{
   
   
    return (x > y ? x : y);
}

//求4个数的最大值
int max4(int a, int b, int c, int d)
{
   
   
    return max2(max2(a, b), maxz(b, c));
}

int main()
{
   
   
    int n1 = 0;
    int n2 = 0;
    int n3 = 0;
    int n4 = 0;

    puts("请输入4个整数。");
    printf("整数1:");
    scanf("%d", &n1);
    printf("整数2:");
    scanf("%d", &n2);
    printf("整数3:");
    scanf("%d", &n3);
    printf("整数4:");
    scanf("%d", &n4);

    printf("最大值是:%d\n", max4(n1, n2, n3, n4));
    return 0;
}

我们可以认为函数就是程序的一个零件,例如,想要实现显示功能的时候,就调用printf这个零件。在制作零件的过程中,如果有其他方便的零件,我们也可以大量的使用。

值传递

下面是一个计算幂的函数,如果n是整数,则通过对x进行n次乘法运算得出的n次方幂,代码如下:

#include<stdio.h>

double power(double a, int b)
{
   
   
    int i = 0;
    double temp = 1.0;

    for ( i = 1; i <= b; i++)
    {
   
   
        temp *= a;
    }
    return temp;
}

int main()
{
   
   
    double a = 0.0;
    int b = 0;

    printf("求a的b次方幂。\n");
    printf("实数a:");
    scanf("%d", &a);
    printf("整数b:");
    scanf("%d", &b);

    printf("%.2f的%d次幂是%.2f", a, b, power(a, b));
    return 0;
}

如上所示,形参a被赋上实参a的值,形参b被赋上实参b的值,像这样通过值来进行参数传递的机制称为值传递。
函数间参数的传递是通过值传递进行的。
这就相当于我们复印一本书,在复印版的书上用红色铅笔写写画画,不会对原来那本书造成任何影响。
形参a是实参a的副本,形参b是实参b的副本。所以在被调用一方的函数中,即使改变接收的形参的值,调用一方的实参也不会改变。

函数设计

上面讲到了函数定义和函数调用相关的基础知识,下面来讲更加正式的函数创建方法等。

没有返回值的函数

显示出一个直角在左下方的等腰 直角三角形,代码如下:

#include<stdio.h>

void put_stars(int n)
{
   
   
    while (n-->0)
    {
   
   
        putchar('*');
    }
}

int main()
{
   
   
    int i = 0;
    int len = 0;

    printf("生成一个直角在左下方的等腰直角三角形。\n");
    printf("短边;");
    scanf("%d", &len);

    for ( i = 0; i < len; i++)
    {
   
   
        put_stars(i);
        putchar('\n');
    }
}

本函数只是用来进行显示的,因此没有需要返回的值,这种没有返回值的类型,要声明为void。

通用性

通过函数使用put_stars可以把用于显示三角形的二重循环简化为一重循环,从而提高程序的可读性。
显示直角在右下方的等腰直角三角形代码如下:

#include<stdio.h>

void put_chars(int ch, int n)
{
   
   
    while (n-->0)
    {
   
   
        putchar(ch);
    }
}

int main()
{
   
   
    int i = 0;
    int len = 0;

    printf("生成一个直角在右下方的等腰直角三角形。\n");
    printf("短边:");
    scanf("%d", &len);

    for ( i = 0; i < len; i++)
    {
   
   
        put_chars(' ', len - i);
        put_chars('*', i);
        putchar('\n');
    }
    return 0;
}

本程序还需要连续显示空白字符,因此需要创建另一个函数put_chars来代替函数put_stars。该函数可以连续显示出n个通过形参传递过来的字符。

不含形参的函数

输入一个正整数并显示其倒转之后的值,代码如下:

#include<stdio.h>

int scan_pint(void)
{
   
   
    int temp = 0;
    do
    {
   
   
        printf("请输入一个正整数;");
        scanf("%d", &temp);
        if (temp<=0)
        {
   
   
            puts("\a请不要输入非正整数。");
        }
    } while (temp<=0);
    return temp;
}

int rev_int(int num)
{
   
   
    int temp = 0;
    if (num>0)
    {
   
   
        do
        {
   
   
            temp = temp * 10 + num % 10;
            num /= 10;
        } while (num>0);
    }
    return temp;
}

int main()
{
   
   
    int nx = scan_pint();

    printf("该整数倒转之后的值是%d。\n", rev_int(nx));
    return 0;
}

函数scan_pint读取从键盘输入的正整数并返回,该函数不接收形参,为了加以说明在小括号里面写了void。

函数返回值的初始化

main函数中声明变量nx的部分,该变量的初始值是函数scan_pint()的调用表达式,变量nx使用函数的返回值进行初始化。

作用域

函数scan_pint和函数rev_pint都包含一个拥有相同标识符的变量,但是它们却是各自独自不同的变量。
也就是说,函数scan_pint中的temp变量是函数scan_pint特有的变量,而rev_pint中的变量temp是函数rev_pint中特有的变量。
赋给变量的标识符,它的名称都有个一通用的范围,称为作用域
在程序块中声明的变量的名称,只在该程序块中通用,在其他区域都无效,也就是说,变量的名称从变量声明的位置开始,到包含该声明的程序块最后的大括号为止,这一区间内通用,这样的作用域称为块作用域

文件作用域

输入5名学生的分数,显示其中的最高分,代码如下:

#include<stdio.h>

#define NU  5
int tensu[NU];
int top(void);

int mian()
{
   
   
    extern  int tensu[];
    int i = 0;

    printf("请输入%d学生的分数。\n",NU);
    for ( i = 0; i < NU; i++)
    {
   
   
        printf("%d:", i + 1);
        scanf("%d", &tensu[i]);

    }

    printf("最高分=%d\n", top());
    return 0;
}

int top(void)
{
   
   
    extern  int tensu[];
    int i = 0;
    int max = tensu[0];

    for ( i = 0; i < NU; i++)
    {
   
   
        if (tensu[i]>max)
        {
   
   
            max = tensu[i];

        }
    }
    return max;
}

在函数的程序块中声明的变量等标识符是该程序块特有的部分,而像数组tensu这样,在函数外声明的变量标识符,其名称从声明的位置开始,到该程序的结尾都是通用的。这样的作用域称为文件作用域。

声明和定义

在上面的程序中声明,一个名为tensu的数组,像这样创建变量实体的声明称为定义声明,另外使用extern的声明表示”使用的在某处创建的tensu“,这里并没有真正创建出变量的实体,因此称为非定义声明。
由于数组tensu是在函数外定义的,所以只需要在main函数或top函数中明确声明要使用它,就可以放心使用。

函数原型声明

编译器在读取数据的时候,也是按照从头到尾的顺序依次读取的,因为本程序中函数top的函数定义在main函数之后,所以要想在main函数中调用top函数,编译器就需要知道。
因此就需要如下声明:
int top(void);
像这样明确记述了函数的返回类型,以及形参的类型和个数等的声明称为函数原型声明。
函数原型声明只声明了函数的返回值和形参等相关信息,并没有定义函数的实体。如果函数返回值的类型和形式参数发生了改变,那么函数定义和函数原型声明两部分都必须进行修改。

头文件和文件包含指令

通过函数原型声明,可以指定函数的参数以及返回值的类型等信息。这样就可以放心调用该函数了。
库函数printf或者putchar等的函数原型声明都包含在中,因此必须要使用下述固定的指令。
#include<stdio.h>
通过#include指令,就可以把中的全部内容都读取到程序中。包含库函数的函数原型声明的称为头文件,而取得头文件内容的#include指令称为文件包含指令。

函数的通用性

函数top的工作过程如下:
找出int型数组tensu最前面NU个元素的最大值,然后返回该值。
当我们创建函数的时候就需要考虑函数的通用性。

可以处理任意数组

可以处理不同元素个数的数组

数组的传递

计算英语分数和数学分数,代码如下:

#include<stdio.h>
#define NU 5

int max_of(int v[],int n)
{
   
   
    int i = 0;
    int max = v[0];

    for ( i = 1; i < n; i++)
    {
   
   
        if (v[i]>max)
        {
   
   
            max = v[i];
        }
    }
    return max;
}

int main()
{
   
   
    int i = 0;
    int eng[NU];
    int mat[NU];
    int max_e = 0;
    int max_m = 0;

    printf("请输入%d名学生的分数。\n", NU);
    for ( i = 0; i < NU; i++)
    {
   
   
        printf("[%d]英语:", i + 1);
        scanf("%d", &eng[NU]);
        printf("    数学:");
        scanf("%d", &mat[NU]);
    }

    max_e = max_of(eng, NU);
    max_m = max_of(mat, NU);

    printf("英语最高分=%d\n", max_e);
    printf("数学最高分=%d\n", max_m);

    return 0;
}

函数max_of的动作如下:
找出包含任意个元素的int 类型数组中的元素的最大值,然后返回该值。

函数的传递和const类型的修饰符

被调用函数中作为形参接收到的数组,就是函数调用时被作为实参的数组。
因此,对接受的数组元素进行修改,也会反映到调用时传入的数组中,下面让我们看以下代码:

#include<stdio.h>

void set_zero(int v[], int n)
{
   
   
    int i = 0;

    for ( i = 0; i < n; i++)
    {
   
   
        v[i] = 0;
    }
}

void printf_array(const int v[], int n)
{
   
   
    int i = 0;

    printf("{");
    for ( i = 0; i < n; i++)
    {
   
   
        printf("%d", v[i]);
    }
    printf("}");
}

int main()
{
   
   
    int ary1[] = {
   
   1,2,3,4,5};
    int ary2[] = {
   
    3,2,1 };

    printf("ary1=");
    printf_array(ary1, 5);
    putchar('\n');
    printf("ary2=");
    printf_array(ary2, 3);
    putchar('\n');

    set_zero(ary1, 5);
    set_zero(ary2, 3);

    printf("把0赋值给两个数组的所有元素。\n");
    printf("ary1=");
    printf_array(ary1, 5);
    putchar('\n');
    printf("ary2=");
    printf_array(ary2, 3);
    putchar('\n');

    return 0;
}

为了解决这个问题,C语言提供了禁止在函数内修改接收到的数组内容的方法,只要在声明形参的时候加上被称为const的类型修饰符就可以了。
如果只是引用所接收的数组元素的值,而不改写的话,在声明接收数组的形参,就应该加上const。这样函数调用方就可以放心的调用函数了。

线性查找(顺序查找)

在数组中查找目标值的程序代码如下;

 #include<stdio.h>
#define NU 5
#define FAILD -1

int search(const int vx[], int key, int n)
{
   
   
    int i = 0;

    while (1)
    {
   
   
        if (i==n)
        {
   
   
            return FAILD;
        }
        if (vx[i]==key)
        {
   
   
            return i;
        }
        i++;
    }
}

int main()
{
   
   
    int i = 0;
    int ky = 0;
    int idx = 0;
    int vx[NU];

    for ( i = 0; i < NU; i++)
    {
   
   
        printf("vx[%d]:", i);
        scanf("%d", &vx[i]);
    }
    printf("要查找的值:");
    scanf("%d", &ky);

    //从元素个数为NU的数组中查找ky
    idx = search(vx, ky, NU);

    if (idx==FAILD)
    {
   
   
        puts("查找失败。");
    }
    else
    {
   
   
        printf("%d是数组的第%d号元素。\n", ky, idx + 1);
    }
    return 0;
}

函数search从元素数为n的int型数组vx的开头,顺次查找是否存在与key值相同的元素,如果有,则返回数组元素下标。如果没有,则返回FAILD,也就是-1。
函数search中while语句的控制表达式是”1“,因此只有在执行return 语句的时候才跳出循环,否则循环体将会一直重复执行下去。
像这样,从数组的开头出发顺次搜索,找出与目标的元素的一系列操作,称为线性查找或者顺序查找

哨兵查找法

进行循环操作的时候,需要不停判断是否满足两个结束循环条件,虽说判断很简单,但是经过数次累积之后,也是一个不小的负担。
如果数组的大小还有富余,我们就可以把想要查找的数值存储到数组的末尾的元素v[n]中,这样一来,即使数组没有想要查找的数值,当遍历到v[n]的时候,也会满足条件。
在数组末尾追加数据称为哨兵,使用哨兵进行查找的方法称为哨兵查找法。使用这种方法可以简化对循环结束条件的判断。
代码如下:

#include<stdio.h>
#define NU 5
#define FAILED -1

int search(int v[], int key, int n)
{
   
   
    int i = 0;

    v[n] = key;

    while (1)
    {
   
   
        if (v[i]==key)
        {
   
   
            break;
        }
        i++;
    }
    return (i < n ? i : FAILED);
}

int main()
{
   
   
    int i = 0;
    int ky = 0;
    int idx = 0;
    int vx[NU + 1];

    for ( i = 0; i < NU; i++)
    {
   
   
        printf("vx[%d]:", i);
        scanf("%d", &vx[i]);
    }

    printf("要查找的值:");
    scanf("%d", &ky);

    if ((idx=search(vx,ky,NU))==FAILED)
    {
   
   
        puts("\a查找失败。");
    }
    else
    {
   
   
        printf("%d是数组的第%d号元素。\n", ky, idx + 1);
    }
    return 0;
}

由于函数search需要改变数组v的内容,因此在声明形参的时候不能加入const类型修饰符。
使用赋值运算符=进行赋值
将函数search的返回值赋给变量idx。
使用相等运算符==进行相等性的判断
判断赋值表达式idx=search(vx,ky,NU)和FAILED是否相等。

多维数组的传递

求4名学生在两次考试中3课程的的总分并显示。
代码如下:

#include<stdio.h>

void mat_add(const int a[4][3], const int b[4][3], int c[4][3])
{
   
   
    int i = 0;
    int j = 0;

    for ( i = 0; i < 4; i++)
    {
   
   
        for ( j = 0; j < 3; j++)
        {
   
   
            c[i][j] = a[i][j] + b[i][j];
        }
    }
}

void mat_printf(const int m[4][3])
{
   
   
    int i = 0;
    int j = 0;

    for ( i = 0; i < 4; i++)
    {
   
   
        for ( j = 0; j < 3; j++)
        {
   
   
            printf("%4d", m[i][j]);
        }
        putchar('\n');
    }
}

int main()
{
   
   
    int tensu1[4][3] = {
   
    {
   
   91,63,78},{
   
   67,72,46},{
   
   89,34,53},{
   
   32,54,34} };
    int tensu2[4][3] = {
   
    {
   
   97,67,82},{
   
   73,43,46},{
   
   97,56,21},{
   
   85,46,35} };
    int  sum[4][3];

    mat_add(tensu1, tensu2, sum);

    puts("第一次考试的分数:");
    mat_printf(tensu1);
    puts("第二次考试的分数:");
    mat_printf(tensu2);
    puts("总分:");
    mat_printf(sum);

    return 0;
}

代码运行结果:
image.png

作用域和存储期

要创建大规模程序,必须首先理解作用域和存储期。

作用域和标识符的可见性

在下面的程序中对变量x的声明总共有三处,代码如下:

#include<stdio.h>

int x = 75;
void printf_x(void)
{
   
   
    printf("x=%d\n", x);
}

int main()
{
   
   
    int i = 0;
    int x = 999;

    printf_x();

    printf("x=%d\n", x);

    for ( i = 0; i < 5; i++)
    {
   
   
        int x = i * 100;
        printf("x=%d\n", x);
    }

    printf("x=%d\n", x);

    return 0;
}

运行结果:
image.png
首先我们来看下int x = 75;处声明的x。该变量的初始值为75,因为它在函数外面声明定义的,所以这个x拥有文件作用域。
因此,函数print_x中的”x“就是上述的x,程序执行后,屏幕上会输出
x=75 ……显示的是x的值
因为printf_x();处调用了函数printf_x,所以会首先进行上面的打印显示。
注意:
如果两个同名变量分别拥有文件作用域和块作用域,那么只要拥有块作用域的变量是”可见“的,而拥有文件作用域的变量会被”隐藏“起来。
当同名变量都被赋予了块作用域的时候,内层的变量是”可见“的,而外层的变量会被”隐藏“起来。

存储期

在函数中声明的变量,并不是从程序开始到程序结束始终有效的,变量的生存期也就是寿命有两种,它们可以通过存储期这个概念来实现。
代码如下:

#include<stdio.h>

int fx = 0;

void func(void)
{
   
   
    static int sx = 0;
    int ax = 0;

    printf("%3d%3d%3d\n", ax++, sx++, fx++);
}

int main()
{
   
   
    int i = 0;
    puts("ax sx fx");
    puts("----------");
    for ( i = 0; i < 10; i++)
    {
   
   
        func();
    }
    puts("----------");

    return 0;
}

运行结果:
image.png
在函数func中声明了sx和ax两个变量,但是声明sx的时候我们使用了存储类说明符static。可能正因为如此,虽然使用相同的值进行初始化并递增的,但最终的ax和sx的值并不相同。

  • 自动存储期

在函数中不使用存储类说明符static而定义出的对象(变量),被赋予了自动存储期,它具有以下特点:
程序执行到对象声明的时候就创建出了相对应的对象,而执行到包含该声明的程序块的结尾,也就是大括号的时候,该对象就会消失。

  • 静态存储期

在函数中使用static定义出来的对象,或者在函数外声明定义出来的对象都被赋予了静态存储期,它具有以下特点:
在程序开始执行的时候,就具体地说是在main函数执行之前的准备阶段被创建出来,在程序结束的时候消失。
也就是说,该对象拥有了”永久“的寿命。另外如果不显示地进行初始化,则该对象会自动初始化为0。
对象的存储期如下图:
image.png

总结

  • 将多个处理集中到一起进行时,可以使用函数这一程序的零件。返回类型、函数名、形参这三个部分决定了函数的特征。不接收参数的函数,其形参类型为void。
  • 函数体是复合语句(程序块)。如果有仅在函数中使用的变量,原则上应在该函数中声明和使用。
  • 函数调用的形式是在函数名后面加上小括号,这个括号称为函数调用运算符。如果没有实参,则小括号为空。有多个实参的情况下,使用逗号隔开。
  • 进行函数调用后,程序的流程将一下子跳转到该函数处。

image.png
image.png
image.png
以上就是我关于函数的介绍,希望都帮到大家。也请大家给我指点不足,谢谢!!!

相关文章
|
7月前
|
自然语言处理 前端开发 JavaScript
前端经典面试题 | 闭包的作用和原理
前端经典面试题 | 闭包的作用和原理
【C++&数据结构】超详细一文带小白轻松全面理解 [ 二叉搜索树 ]—— [从零实现&逐过程分析&代码演示&简练易懂](23)
【C++&数据结构】超详细一文带小白轻松全面理解 [ 二叉搜索树 ]—— [从零实现&逐过程分析&代码演示&简练易懂](23)
|
6月前
|
JSON 前端开发 Java
《优化接口设计的思路》系列:第一篇—接口参数的一些弯弯绕绕
大家好!我是sum墨,一个一线的底层码农,平时喜欢研究和思考一些技术相关的问题并整理成文,限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。 作为一名从业已达六年的老码农,我的工作主要是开发后端Java业务系统,包括各种管理后台和小程序等。在这些项目中,我设计过单/多租户体系系统,对接过许多开放平台,也搞过消息中心这类较为复杂的应用,但幸运的是,我至今还没有遇到过线上系统由于代码崩溃导致资损的情况。这其中的原因有三点:一是业务系统本身并不复杂;二是我一直遵循某大厂代码规约,在开发过程中尽可能按规约编写代码;三是经过多年的开发经验积累,我成为了一名熟练工,掌握了一些实用的技巧。
33 0
|
编解码 缓存 NoSQL
7点 讲明白地图切片的概念与原理
7点 讲明白地图切片的概念与原理
308 0
|
SQL 测试技术
软件测试面试题:解释以下函数及他们的不同之处?
软件测试面试题:解释以下函数及他们的不同之处?
51 0
|
算法 C++
C++ 基础复习系列2(打印图形类(循环)经典问题类)
C++ 基础复习系列2(打印图形类(循环)经典问题类)
C++ 基础复习系列2(打印图形类(循环)经典问题类)
|
存储 算法
算法不难的话,也挺简单的哈
算法不难的话,也挺简单的哈
86 0
|
算法 程序员
深究递归和迭代的区别、联系、优缺点及实例对比
递归的基本概念:程序调用自身的编程技巧称为递归,是函数自己调用自己. 一个函数在其定义中直接或间接调用自身的一种方法,它通常把一个大型的复杂的问题转化为一个与原问题相似的规模较小的问题来解决,可以极大的减少代码量.递归的能力在于用有限的语句来定义对象的无限集合.
202 0