第六天: C语言核心概念与实战技巧全解析
1 主函数(main)
大家好,今天我们来深入探讨一下C语言中非常特殊的一个函数——main
函数。虽然大家对它并不陌生,但是它的重要性和特殊性值得我们再次回顾。
main
函数的定义
main
函数是我们整个C源程序的入口点。计算机在运行程序时,会将代码翻译成一条一条的指令,而main
函数就是这些指令执行的起点。
main
函数的特殊性
main
函数必须被定义为int main()
或者int main(int argc, char *argv[])
。这里需要注意的是,main
函数的名称不能改变,否则程序将无法正确运行。
main
函数的返回值
main
函数的返回值是int
类型,通常我们会在程序的最后加上return 0;
表示程序正常结束。这个返回值是给操作系统的,表示程序的执行状态。
main
函数的参数
main
函数可以没有参数,也可以有两个参数:
int argc
:表示命令行参数的个数。char *argv[]
:表示命令行参数的值,每个参数都是一个字符串。
main
函数的调用
其他函数可以被main
函数调用,但是不能反过来。main
函数是程序的起点,不能被其他函数调用。
实践操作
下面我们通过一个简单的例子来演示main
函数参数的使用:
c
#include <stdio.h>int main(int argc, char *argv[]) {printf("主函数的参数个数为: %d\n", argc);for (int i = 0; i < argc; i++) {printf("第%d个参数为: %s\n", i + 1, argv[i]);}return 0;
}
在这个例子中,我们打印出了传给main
函数的参数个数,以及每个参数的具体值。
练习题
假设我们要编写一个程序,该程序接受两个参数:一个整数和一个字符串。请编写相应的main
函数代码。
c
#include <stdio.h>int main(int argc, char *argv[]) {if (argc != 3) {printf("使用方法: %s <整数> <字符串>\n", argv[0]);return 1;}int number = atoi(argv[1]);char *str = argv[2];printf("整数参数为: %d\n", number);printf("字符串参数为: %s\n", str);return 0;
}
在这个练习题中,我们首先检查参数个数是否正确,然后使用atoi
函数将字符串转换为整数,并打印出两个参数的值。
2 函数原型、声明和多文件编译
大家好,今天我们来聊聊C语言中的函数原型、函数声明以及多文件编译的那些事儿。
函数原型
首先,咱们得搞清楚啥是函数原型。所谓的函数原型,就是在使用函数之前,你得先告诉编译器这个函数长啥样。这就意味着你得先声明后使用。
为什么要有函数原型?
在我们编写程序的时候,函数的定义通常都是放在main
函数的前面。这是因为编译器是从上往下扫描代码的,它得先知道有这个函数,才能在main
函数中调用它。但如果函数定义在main
函数后面,编译器在扫描main
函数时就不认识这个函数,这就尴尬了。
函数原型的例子
比如,我们定义一个简单的加法函数add
:
c
int add(int x, int y) {return x + y;
}
如果我们在main
函数中直接使用add
,但忘记在前面声明它,编译器就会自动做一个隐式的函数声明,但这通常不是一个好习惯。
函数声明
函数声明其实就是告诉编译器函数的三要素:函数名、输入参数的类型和返回值的类型。这样编译器在编译时就能知道函数的存在和如何调用它。
函数声明的写法
函数声明的写法很简单,就是把函数的定义中的花括号和函数体去掉,只留下函数的签名:
c
int add(int x, int y);
多文件编译
当我们的程序变得越来越大,函数越来越多时,我们可能希望将不同的函数放在不同的文件中。这时候就需要用到多文件编译。
如何进行多文件编译?
使用gcc
命令时,我们可以指定多个源文件进行编译,并将它们链接成一个可执行文件:
bash
gcc declaration.c add.c -o test.exe
这样,gcc
会编译declaration.c
和add.c
,并将它们链接成test.exe
。
练习题
假设我们有两个函数add
和multiply
,分别计算两个整数的和与积。请编写相应的函数原型和声明,并在一个main
函数中调用它们。
函数原型和声明
c
// function prototypes
int add(int x, int y);
int multiply(int x, int y);// function declarations
int add(int x, int y) {return x + y;
}int multiply(int x, int y) {return x * y;
}
main
函数的调用
c
#include <stdio.h>int main() {int result_add = add(10, 35);int result_multiply = multiply(10, 35);printf("Add: %d\n", result_add);printf("Multiply: %d\n", result_multiply);return 0;
}
在这个练习题中,我们首先定义了两个函数的原型,然后在main
函数中调用它们,并打印结果。
这就是我们今天的内容,希望大家能够有所收获。如果有任何问题,欢迎随时提问。
3 全局作用域
大家好,今天我们来探讨一个新的话题,叫做作用域。简单来说,就是我们之前定义的所有东西,比如变量、数组、常量,甚至函数,它们都有一个名字,这个名字就是我们所说的标识符。那这些变量的名字是在所有地方都能用吗?显然不是,比如for
循环里定义的int i = 0
,出了循环就没用了,访问不到这个变量了。所以,变量的起作用的范围是有限的,这个我们就叫做变量的作用域。
作用域的分类
作用域可以分为全局作用域、局部作用域和块级作用域。在同一个作用域里边,不能有同名的标志符。
全局作用域
全局作用域,顾名思义,它的作用范围是全局生效的,在程序的任何一个地方都能够访问到我们定义的这个变量、数组或者函数之类的东西。
全局变量的定义
如果一个变量定义在所有函数和代码块之外,那么它就拥有全局作用域,这个变量就叫做全局变量。
全局变量的特点
- 全局可见:全局变量在整个程序中任何一个地方都可以访问。
- 可修改:在任何地方都可以修改全局变量的值。
- 生命周期:全局变量的生命周期贯穿整个程序运行的时间,程序一运行,全局变量就出生了,直到程序运行结束才销毁。
- 初始值:如果全局变量不做初始化,它有默认值,这个默认值就是全零。
全局变量的使用
下面是一个全局变量使用的例子:
c
#include <stdio.h>// 定义一个全局变量
int a = 100;int main() {printf("In main, a = %d\n", a); // 在main函数中访问全局变量areturn 0;
}void add() {printf("In add, a = %d\n", a); // 在add函数中访问全局变量a
}
在这个例子中,我们在全局作用域定义了一个变量a
,在main
函数和add
函数中都可以访问到这个变量。
练习题
假设我们需要在程序中多次使用一个常量PI
,值为3.14159。请编写一个全局常量的定义,并在main
函数和另一个函数中使用它。
c
#include <stdio.h>// 定义一个全局常量PI
const double PI = 3.14159;int main() {printf("In main, PI = %f\n", PI); // 在main函数中访问全局常量PIreturn 0;
}void calculateCircumference(double radius) {double circumference = 2 * PI * radius;printf("In calculateCircumference, Circumference = %f\n", circumference); // 在函数中使用全局常量PI
}
在这个练习题中,我们定义了一个全局常量PI
,并在main
函数和calculateCircumference
函数中使用它来计算圆的周长。
注意:全局变量虽然方便,但过度使用可能会导致代码难以维护,因为它可以在程序的任何地方被修改,可能会导致不可预见的错误。所以,除非必要,尽量避免使用全局变量。
4 局部作用域
大家好,继全局作用域之后,今天我们来聊聊局部作用域。全局变量虽然方便,但它们可以被程序的任何部分修改,这可能会导致一些问题。因此,我们通常会将变量定义在函数内部,这样定义的变量就拥有局部作用域,也就是局部变量。
局部作用域简介
局部作用域是指变量、常量或数组只在定义它们的函数或代码块内部可见。与之对应的就是局部变量、局部常量和局部数组。
函数参数
函数的参数本质上也是局部变量。它们只在函数内部有效,函数执行完毕后,这些变量就会被销毁。
局部变量的特点
- 局部可见:局部变量只在定义它们的函数或代码块内部可见。
- 生命周期:局部变量的生命周期仅限于函数的执行期间。
- 初始值:如果局部变量未初始化,它们的值是不确定的,可能是内存中的任意值。
局部变量的使用
下面是一个局部变量使用的例子:
c
#include <stdio.h>void add(int x, int y) {int sum = x + y;printf("In add, sum = %d\n", sum);
}int main() {int a = 200;printf("In main, a = %d\n", a);add(10, 20);return 0;
}
在这个例子中,sum
是add
函数的局部变量,a
是main
函数的局部变量。它们只在各自的函数内部有效。
局部变量与全局变量的冲突
如果局部变量和全局变量有相同的名字,局部变量会覆盖全局变量的值。
c
#include <stdio.h>int globalA = 100;void func() {int a = 200; // 局部变量a覆盖了全局变量aprintf("In func, a = %d\n", a);
}int main() {printf("In main, globalA = %d\n", globalA);func();printf("In main, globalA = %d\n", globalA);return 0;
}
在这个例子中,func
函数中的a
是局部变量,它覆盖了全局变量globalA
的值。
练习题
假设我们需要在main
函数和add
函数中分别使用一个名为result
的变量,请编写相应的代码,并在每个函数中初始化result
。
c
#include <stdio.h>void add(int x, int y) {int result = x + y; // `result`是`add`函数的局部变量printf("In add, result = %d\n", result);
}int main() {int result = 0; // `result`是`main`函数的局部变量printf("In main, result = %d\n", result);add(10, 20);return 0;
}
在这个练习题中,我们定义了两个同名的局部变量result
,一个在main
函数中,另一个在add
函数中。它们互不影响,各自有自己的作用域和生命周期。
这就是我们今天的内容,希望大家能够有所收获。如果有任何问题,欢迎随时提问。
注意:局部变量的使用可以限制变量的作用域,这有助于减少程序中变量名的冲突,并且可以提高程序的可读性和可维护性。同时,一定要记得初始化局部变量,以避免使用不确定的值。
5 块级作用域
大家好,今天我们来聊聊块级作用域。在C语言中,块级作用域是指变量的作用域限制在特定的代码块内,这通常是由一对花括号{}
定义的区域。
块级作用域简介
块级作用域的概念在C99标准中被引入,它允许我们在代码块内定义变量,这些变量只在该代码块内部可见。这意味着,一旦代码块执行结束,这些变量的生命周期也就结束了。
块级作用域的特点
- 代码块内有效:在花括号
{}
内部定义的变量,只在该代码块内有效。 - 生命周期有限:块级变量的生命周期仅限于代码块的执行期间。
- 与外部变量同名:块级变量可以与全局变量或外部变量同名,但不会相互影响。
块级作用域的使用
下面是一个块级作用域的使用示例:
c
#include <stdio.h>int main() {int a = 100; // 全局变量const double pi = 3.14; // 全局常量{int a = 200; // 块级变量,与全局变量a同名const double pi = 3.15; // 块级常量,与全局常量pi同名printf("Inside block, a = %d, pi = %f\n", a, pi);}printf("Outside block, a = %d, pi = %f\n", a, pi);return 0;
}
在这个例子中,a
和pi
在代码块内部被重新定义,它们的作用域限制在花括号内部。在代码块外部,访问的是全局变量a
和全局常量pi
。
块级作用域与内存
块级变量通常存储在栈(stack)上,它们的内存分配和释放是自动的,随着代码块的进入和退出而进行。
练习题
假设我们需要在main
函数中使用一个临时变量temp
,该变量只在main
函数的某个特定代码块内有效。请编写相应的代码。
c
#include <stdio.h>int main() {int a = 100;printf("Before block, a = %d\n", a);{int temp = 300; // 块级变量tempprintf("Inside block, temp = %d\n", temp);}printf("After block, a = %d\n", a); // 这里不能访问tempreturn 0;
}
在这个练习题中,temp
变量只在花括号内部有效,一旦离开这个代码块,temp
就无法访问了。
这就是我们今天的内容,希望大家能够有所收获。如果有任何问题,欢迎随时提问。
注意:块级作用域提供了一种限制变量生命周期的手段,有助于减少变量名的冲突,并且可以提高程序的可读性和可维护性。同时,由于块级变量的生命周期有限,使用时应注意不要在代码块外部访问这些变量,以免出现编译错误。
6 局部变量与全局变量
大家好,今天我们来解答关于局部变量和全局变量的一些疑问。之前我提到局部变量会覆盖全局变量,可能让大家产生了一些误解。其实,局部变量和全局变量是两个不同的变量,它们的作用域优先级不同。
局部变量与全局变量的关系
局部变量和全局变量可以同名,但它们不是同一个变量。局部变量的作用域仅限于定义它的代码块,而全局变量在整个程序中都可见。
访问优先级
当你访问一个变量时,程序会优先访问局部变量。如果局部变量和全局变量同名,局部变量会覆盖全局变量的值。可以把它理解为“就近原则”,即优先访问离当前作用域最近的变量。
示例代码
让我们看一个简单的例子:
c
#include <stdio.h>int a = 100; // 全局变量void func() {int a = 200; // 局部变量printf("In func, a = %d\n", a); // 访问局部变量
}int main() {printf("In main, a = %d\n", a); // 访问全局变量func();return 0;
}
在这个例子中,func
函数中的a
是局部变量,而main
函数中访问的是全局变量a
。运行结果会显示局部变量的值优先。
访问全局变量
如果你想在局部作用域中访问全局变量,可以使用extern
关键字来声明全局变量。这样可以明确告诉编译器你要访问的是外部的全局变量。
示例代码
c
#include <stdio.h>int a = 100; // 全局变量void func() {extern int a; // 声明使用外部全局变量printf("In func, a = %d\n", a); // 访问全局变量
}int main() {printf("In main, a = %d\n", a); // 访问全局变量func();return 0;
}
在这个例子中,func
函数通过extern
声明访问了全局变量a
。
练习题
假设我们在main
函数中定义一个局部变量b
,并在func
函数中定义一个同名的局部变量b
。请编写相应的代码,展示如何访问这两个变量。
c
#include <stdio.h>int b = 50; // 全局变量void func() {int b = 100; // 局部变量printf("In func, b = %d\n", b); // 访问局部变量
}int main() {int b = 200; // 局部变量printf("In main, b = %d\n", b); // 访问局部变量func();printf("In main, global b = %d\n", ::b); // 访问全局变量return 0;
}
在这个练习题中,我们定义了两个同名的局部变量b
,一个在main
函数中,另一个在func
函数中。它们互不影响,各自有自己的作用域和生命周期。
这就是我们今天的内容,希望大家能够有所收获。如果有任何问题,欢迎随时提问。
注意:局部变量的优先级高于全局变量,使用时要注意变量的作用域,以避免不必要的错误。同时,尽量避免使用同名变量,以提高代码的可读性和可维护性。
7 作用域和内存
大家好,今天我们来系统地总结一下作用域和内存的关系。在之前的学习中,我们已经接触过全局变量和局部变量,它们在内存中存放的位置是不同的。
内存区域的划分
在运行程序时,内存会被划分为不同的区域,用于存放不同类型的数据。
栈区(Stack)
栈区是存放局部变量的地方。它是一种后进先出(LIFO)的数据结构,像一个桶,先放入的数据被压在底部,后放入的数据放在顶部。当函数调用结束时,顶部的数据(局部变量)就会被弹出并销毁。
全局静态区
全局变量、全局数组和全局常量存放在全局静态区。这些数据在程序开始运行时就被加载到内存中,并一直存在直到程序结束。
作用域和内存的关系
全局变量
全局变量在程序运行时就占据了内存空间,它们的作用域是全局的,因此在程序的任何地方都可以访问。
局部变量
局部变量在函数调用时才占据内存空间,并在函数调用结束时释放。它们的作用域仅限于定义它们的函数或代码块内。
示例代码分析
c
#include <stdio.h>int globalVar = 5; // 全局变量void fn(int num) {int localVar = 200; // 局部变量printf("%d\n", localVar);
}int main() {int localVar = 20; // 局部变量printf("%d\n", localVar);fn(10);return 0;
}
在这个例子中,globalVar
是全局变量,localVar
是局部变量。全局变量在程序开始时就分配了内存,而局部变量在函数调用时才分配内存,并在函数返回后释放。
练习题
考虑以下代码,分析并确定每个printf
的输出结果。
c
#include <stdio.h>int globalN = 10; // 全局变量void test01() {printf("%d\n", globalN); // 1
}void test02() {globalN = 25;printf("%d\n", globalN); // 2
}int main() {int localN = 30; // 局部变量printf("%d\n", localN); // 3test01(); // 4test02(); // 5printf("%d\n", globalN); // 6return 0;
}
答案
- 输出全局变量
globalN
的值,即10
。 - 修改全局变量
globalN
的值为25
,并输出,即25
。 - 输出
main
函数中的局部变量localN
的值,即30
。 - 调用
test01
,输出全局变量globalN
的值,即10
(未改变)。 - 调用
test02
,修改全局变量globalN
的值为25
,并输出,即25
。 - 最后再次输出全局变量
globalN
的值,即25
(已被test02
修改)。
这就是我们今天的内容,希望大家能够有所收获。如果有任何问题,欢迎随时提问。
注意:理解作用域和内存的关系对于编写高效的C语言程序至关重要。全局变量和局部变量的使用应根据其作用域和生命周期来决定。
8 静态局部变量
大家好,今天我们来聊聊静态局部变量。之前我们学习了全局变量和局部变量,全局变量全局有效,但容易被修改,局部变量生命周期短,每次函数调用都是新的轮回。那么,有没有一种变量,既能够保持局部性,又能记住之前的值呢?这就是我们今天要学习的静态局部变量。
静态局部变量简介
静态局部变量是使用static
关键字声明的局部变量。它具有局部变量的作用域,但生命周期贯穿整个程序执行过程,就像全局变量一样。
静态局部变量的特点
- 局部作用域:静态局部变量仅在定义它的函数或代码块内可见。
- 全局生命周期:静态局部变量的生命周期与程序执行过程相同,一旦初始化,值将保持直到程序结束。
- 记忆能力:静态局部变量能够记住之前的值,即使函数调用结束后,其值也不会丢失。
静态局部变量的使用
下面是一个静态局部变量的使用示例:
c
#include <stdio.h>int countFunction() {static int count = 0; // 静态局部变量count++;return count;
}int main() {printf("Function called %d times\n", countFunction());printf("Function called %d times\n", countFunction());return 0;
}
在这个例子中,count
是countFunction
函数的静态局部变量,它记录了函数被调用的次数。
练习题
假设我们需要记录一个函数在程序运行过程中被调用了多少次,请编写相应的代码。
c
#include <stdio.h>int getCallCount() {static int callCount = 0; // 静态局部变量callCount++;return callCount;
}int main() {printf("Function called %d times\n", getCallCount());printf("Function called %d times\n", getCallCount());printf("Function called %d times\n", getCallCount());return 0;
}
在这个练习题中,我们定义了一个静态局部变量callCount
来记录getCallCount
函数被调用的次数。
这就是我们今天的内容,希望大家能够有所收获。如果有任何问题,欢迎随时提问。
注意:静态局部变量是一种特殊的变量,它结合了局部变量和全局变量的特点,适用于需要在函数内部保持状态的场景。使用时要注意,静态局部变量的值在函数调用之间是保持不变的,因此可以用来计数或者保存函数的状态。
9 静态全局变量
大家好,今天我们来继续探讨static
关键字的用法,特别是它如何影响全局变量。
静态全局变量简介
在C语言中,static
关键字可以修饰全局变量,这样的全局变量被称为静态全局变量。与普通全局变量相比,静态全局变量的最大区别在于它们的可见性。
静态全局变量的特点
- 局部可见性:静态全局变量只在定义它们的文件内部可见,其他文件无法直接访问。
- 全局生命周期:静态全局变量的生命周期仍然是整个程序执行期间,与普通全局变量相同。
为什么使用静态全局变量?
静态全局变量主要用于控制全局变量的访问权限,防止它们被其他文件意外修改。
示例代码
c
// file1.c
#include <stdio.h>static int globalStaticVar = 100; // 静态全局变量void function1() {printf("In file1, globalStaticVar = %d\n", globalStaticVar);
}// file2.c
extern int globalStaticVar; // 尝试外部访问void function2() {printf("In file2, globalStaticVar = %d\n", globalStaticVar); // 这将导致编译错误
}
在这个例子中,globalStaticVar
是file1.c
中的静态全局变量。file2.c
尝试通过extern
关键字访问它,但这是不允许的,会导致编译错误。
练习题
假设我们有两个文件file1.c
和file2.c
,我们希望在file1.c
中定义一个静态全局变量,并在file2.c
中访问它。请指出以下代码的问题,并提供正确的做法。
c
// file1.c
int globalVar = 200; // 普通全局变量// file2.c
extern int globalVar; // 尝试外部访问void function2() {printf("In file2, globalVar = %d\n", globalVar);
}
答案
上述代码中,globalVar
是一个普通全局变量,可以在file2.c
中通过extern
关键字访问。但如果想要限制globalVar
的访问范围,使其只能在file1.c
中访问,我们需要将其声明为静态全局变量:
c
// file1.c
static int globalVar = 200; // 静态全局变量// file2.c
// extern int globalVar; // 这行代码将被移除,因为globalVar现在是静态的void function2() {// printf("In file2, globalVar = %d\n", globalVar); // 这将导致编译错误,因为globalVar现在是不可访问的
}
在这个修正后的例子中,globalVar
现在是file1.c
中的静态全局变量,file2.c
无法访问它。
这就是我们今天的内容,希望大家能够有所收获。如果有任何问题,欢迎随时提问。
注意:静态全局变量是控制全局变量访问权限的有效手段,它可以帮助我们避免全局变量被意外修改,提高程序的稳定性和可维护性。
10 递归函数原理分析
大家好,今天我们来探讨一个非常有趣的知识点,那就是递归函数。递归函数是一个自己调用自己的函数,它在执行过程中会重复使用同一段代码。
递归函数简介
递归函数的特点是它必须有两个条件才能成功执行:
- 结束条件:防止无限递归,类似于循环中的退出条件。
- 趋近于结束条件的趋势:类似于循环变量的变化过程,递归函数中通常通过参数的变化来实现。
递归函数的执行过程
递归函数的执行过程类似于循环,但它是通过函数调用自己来实现的。每次调用时,都会传递一个参数,这个参数会随着递归的深入而变化,直到满足结束条件。
示例代码
下面是一个简单的递归函数示例,用于打印从n到1的数字:
c
#include <stdio.h>void printNumbers(int n) {if (n > 1) {printNumbers(n - 1); // 递归调用}printf("%d ", n);
}int main() {printNumbers(5);return 0;
}
在这个例子中,printNumbers
函数会递归调用自己,直到参数n
变为1。
练习题
假设我们需要计算一个数的阶乘,请编写一个递归函数来实现这个功能。
c
#include <stdio.h>long factorial(int n) {if (n == 0) {return 1; // 结束条件} else {return n * factorial(n - 1); // 递归调用}
}int main() {int number = 5;printf("Factorial of %d is %ld\n", number, factorial(number));return 0;
}
在这个练习题中,factorial
函数通过递归调用自己来计算一个数的阶乘。
答案
运行上述代码,将输出5的阶乘结果:
Factorial of 5 is 120
这就是我们今天的内容,希望大家能够有所收获。如果有任何问题,欢迎随时提问。
注意:递归函数是一个强大的工具,但使用时需要注意防止无限递归和栈溢出。递归函数的结束条件和参数变化是确保递归正确执行的关键。
11 递归函数案例:阶乘
大家好,今天我们来探讨一个经典的递归函数案例——计算阶乘。阶乘是一个数与所有小于它的正整数的乘积,例如5的阶乘是5×4×3×2×1。
阶乘的计算方法
阶乘可以通过循环实现,但今天我们使用递归函数来实现。递归函数是一种自己调用自己的函数,它在执行过程中会重复使用同一段代码。
递归函数的基本概念
递归函数必须有两个条件:
- 结束条件:防止无限递归,类似于循环中的退出条件。
- 趋近于结束条件的趋势:类似于循环变量的变化过程,递归函数中通常通过参数的变化来实现。
示例代码
下面是一个计算阶乘的递归函数示例:
c
#include <stdio.h>// 阶乘函数
int factorial(int n) {if (n == 1) {return 1; // 结束条件} else {return n * factorial(n - 1); // 递归调用}
}int main() {int number = 5;printf("The factorial of %d is %d\n", number, factorial(number));return 0;
}
在这个例子中,factorial
函数通过递归调用自己来计算一个数的阶乘。
练习题
假设我们需要计算一个数的阶乘,请编写一个递归函数来实现这个功能。
答案
上述代码已经给出了阶乘的递归函数实现。运行上述代码,将输出5的阶乘结果:
The factorial of 5 is 120
递归函数的执行过程
递归函数的执行过程类似于循环,但它是通过函数调用自己来实现的。每次调用时,都会传递一个参数,这个参数会随着递归的深入而变化,直到满足结束条件。
递归函数的图解
为了更好地理解递归函数的执行过程,我们可以画出递归树或者使用调试工具来逐步跟踪递归函数的调用过程。
factorial(5)
调用开始,n
等于5。n
不等于1,所以执行5 * factorial(4)
。factorial(4)
调用开始,n
等于4。n
不等于1,所以执行4 * factorial(3)
。factorial(3)
调用开始,n
等于3。n
不等于1,所以执行3 * factorial(2)
。factorial(2)
调用开始,n
等于2。n
不等于1,所以执行2 * factorial(1)
。factorial(1)
调用开始,n
等于1,满足结束条件,返回1。- 从
factorial(1)
开始,逐层返回,计算2 * 1
,3 * 2
,4 * 6
,5 * 24
,最终得到120。
这就是我们今天的内容,希望大家能够有所收获。如果有任何问题,欢迎随时提问。
注意:递归函数是一个强大的工具,但使用时需要注意防止无限递归和栈溢出。递归函数的结束条件和参数变化是确保递归正确执行的关键。
12 递归函数案例:斐波那契数列
大家好,今天我们来探讨一个经典的递归函数案例——斐波那契数列。斐波那契数列是一个非常著名的数列,它的规律是从第三个数开始,每个数都是前两个数之和。
斐波那契数列简介
斐波那契数列的前两项都是1,从第三项开始,每一项都等于前两项的和。数列如下:1, 1, 2, 3, 5, 8, 13, …
递归函数实现斐波那契数列
递归函数实现斐波那契数列的思路非常简单,因为斐波那契数列本身就有一个递推公式:F(n) = F(n-1) + F(n-2)。
示例代码
c
#include <stdio.h>// 斐波那契数列函数
int fibonacci(int n) {if (n == 1 || n == 2) {return 1; // 递归结束条件} else {return fibonacci(n - 1) + fibonacci(n - 2); // 递归调用}
}int main() {int n = 7; // 计算第7项printf("The %dth Fibonacci number is %d\n", n, fibonacci(n));return 0;
}
在这个例子中,fibonacci
函数通过递归调用自己来计算斐波那契数列的第n项。
练习题
假设我们需要计算斐波那契数列的第n项,请编写一个递归函数来实现这个功能。
答案
上述代码已经给出了斐波那契数列的递归函数实现。运行上述代码,将输出第7项的斐波那契数:
The 7th Fibonacci number is 13
递归函数的执行过程
递归函数的执行过程类似于循环,但它是通过函数调用自己来实现的。每次调用时,都会传递一个参数,这个参数会随着递归的深入而变化,直到满足结束条件。
递归函数的图解
为了更好地理解递归函数的执行过程,我们可以画出递归树或者使用调试工具来逐步跟踪递归函数的调用过程。
fibonacci(7)
调用开始,n
等于7。n
不等于1且不等于2,所以执行fibonacci(6) + fibonacci(5)
。fibonacci(6)
调用开始,n
等于6。n
不等于1且不等于2,所以执行fibonacci(5) + fibonacci(4)
。fibonacci(5)
调用开始,n
等于5。n
不等于1且不等于2,所以执行fibonacci(4) + fibonacci(3)
。fibonacci(4)
调用开始,n
等于4。n
不等于1且不等于2,所以执行fibonacci(3) + fibonacci(2)
。fibonacci(3)
调用开始,n
等于3。n
不等于1且不等于2,所以执行fibonacci(2) + fibonacci(1)
。fibonacci(2)
和fibonacci(1)
都满足结束条件,返回1。- 从
fibonacci(1)
和fibonacci(2)
开始,逐层返回,计算fibonacci(3)
,fibonacci(4)
,fibonacci(5)
,fibonacci(6)
,最终得到fibonacci(7)
的值。
这就是我们今天的内容,希望大家能够有所收获。如果有任何问题,欢迎随时提问。
注意:递归函数是一个强大的工具,但使用时需要注意防止无限递归和栈溢出。递归函数的结束条件和参数变化是确保递归正确执行的关键。
13 递归函数案例:猴子吃桃问题
大家好,今天我们来讨论一个有趣的递归问题——猴子吃桃问题。这个问题描述了一个猴子吃桃的过程,我们的目标是找出最初有多少个桃子。
猴子吃桃问题简介
猴子每天都会吃掉剩下桃子的一半再加一个。到了第十天,猴子发现只剩下一个桃子了。我们需要倒推出第一天最初有多少个桃子。
递归函数实现猴子吃桃问题的解决
这个问题可以通过递归函数来解决,因为我们知道第十天剩下一个桃子,可以倒推出第九天有多少个桃子,以此类推。
示例代码
c
#include <stdio.h>// 递归函数,计算第n天的桃子数
int peach(int n) {if (n == 10) {return 1; // 第十天剩下一个桃子} else {return (peach(n + 1) + 1) * 2; // 根据递推公式计算前一天的桃子数}
}int main() {int n = 1; // 从第一天开始计算printf("The number of peaches on the first day is %d\n", peach(n));return 0;
}
在这个例子中,peach
函数通过递归调用自己来计算第一天的桃子数。
练习题
假设我们需要计算猴子吃桃问题中第一天最初有多少个桃子,请编写一个递归函数来实现这个功能。
答案
上述代码已经给出了猴子吃桃问题的递归函数实现。运行上述代码,将输出第一天最初有多少个桃子:
The number of peaches on the first day is 1534
递归函数的执行过程
递归函数的执行过程是通过递推公式从第十天开始倒推到第一天,每次调用都会传递一个参数,这个参数会随着递归的深入而变化,直到满足结束条件。
递归函数的图解
为了更好地理解递归函数的执行过程,我们可以画出递归树或者使用调试工具来逐步跟踪递归函数的调用过程。
peach(1)
调用开始,n
等于1。n
不等于10,所以执行(peach(2) + 1) * 2
。peach(2)
调用开始,n
等于2。n
不等于10,所以执行(peach(3) + 1) * 2
。- 以此类推,直到
peach(10)
调用开始,n
等于10,满足结束条件,返回1。 - 从
peach(10)
开始,逐层返回,计算peach(9)
,peach(8)
,直到peach(1)
。
这就是我们今天的内容,希望大家能够有所收获。如果有任何问题,欢迎随时提问。
注意:递归函数是一个强大的工具,但使用时需要注意防止无限递归和栈溢出。递归函数的结束条件和参数变化是确保递归正确执行的关键。
14 常用系统函数:字符串函数
大家好,今天我们来聊聊C语言中常用的系统函数,特别是字符串相关的函数。这些函数通常包含在string.h
头文件中,使用前需要引入这个头文件。
字符串函数简介
字符串函数是处理字符串时经常用到的函数,它们帮助我们简化字符串操作,避免重复造轮子。
strlen函数
strlen
函数用于计算字符串的长度。为什么需要这个函数呢?因为字符串实际上是字符数组,而sizeof
运算符会返回整个数组的大小,包括结尾的空字符\0
。所以,strlen
函数可以帮助我们得到不包括空字符的字符串长度。
示例代码
c
#include <stdio.h>
#include <string.h> // 引入字符串处理函数的头文件int main() {char msg[] = "Hello";printf("Length of 'msg': %zu\n", strlen(msg)); // %zu用于打印size_t类型的数据return 0;
}
strcpy函数
strcpy
函数用于将一个字符串的内容复制到另一个字符串中。使用这个函数时,需要确保目标字符串有足够的空间来存储源字符串的内容。
示例代码
c
#include <stdio.h>
#include <string.h>int main() {char src[] = "Alice";char dest[10]; // 确保有足够的空间strcpy(dest, src);printf("dest: %s\n", dest);return 0;
}
strcat函数
strcat
函数用于将两个字符串连接起来。它会将第二个字符串追加到第一个字符串的末尾。
示例代码
c
#include <stdio.h>
#include <string.h>int main() {char msg[] = "Hello, ";char name[] = "Alice";strcat(msg, name);printf("msg: %s\n", msg);return 0;
}
练习题
假设我们需要编写一个程序,将两个字符串"Hello, "
和"World"
连接起来,并打印结果。
答案
上述代码已经给出了字符串连接的示例。运行上述代码,将输出连接后的字符串:
msg: Hello, World
这就是我们今天的内容,希望大家能够有所收获。如果有任何问题,欢迎随时提问。
注意:在使用字符串函数时,需要确保目标字符串有足够的空间来存储结果,以避免溢出。同时,了解这些函数的工作原理有助于我们更好地理解和使用它们。
15 常用系统函数:标准输入输出与字符串处理
大家好,今天我们来聊聊C语言中与标准输入输出和字符串处理相关的常用系统函数。这些函数都定义在stdio.h
头文件中,是我们日常编程中不可或缺的工具。
字符串处理函数
sprintf函数
sprintf
函数类似于printf
,但它不是将格式化的输出打印到控制台,而是存储到一个字符串中。这个函数的原型是:
c
int sprintf(char *str, const char *format, ...);
str
:目标字符串的指针,用于存储格式化后的输出。format
:格式化字符串,与printf
中的格式相同。...
:可变参数列表,根据format
中的格式说明符提供相应的参数。
示例代码
c
#include <stdio.h>int main() {char output[100];int age = 19;double score = 69.5;sprintf(output, "My name is %s, I am %d years old, and my score is %.2f.", "Alice", age, score);printf("%s\n", output);return 0;
}
sscanf函数
sscanf
函数类似于scanf
,但它不是从控制台读取输入,而是从字符串中按照指定格式提取数据。这个函数的原型是:
c
int sscanf(const char *str, const char *format, ...);
str
:源字符串的指针,从中提取格式化的数据。format
:格式化字符串,与scanf
中的格式相同。...
:可变参数列表,用于存储从str
中提取的数据。
示例代码
c
#include <stdio.h>int main() {char input[] = "Score1: 98.5, Score2: 65.5";float score1, score2;sscanf(input, "Score1: %f, Score2: %f", &score1, &score2);printf("Score1: %.2f, Score2: %.2f\n", score1, score2);return 0;
}
练习题
假设我们需要从字符串中提取两个成绩,并打印出来。
答案
上述代码已经给出了从字符串中提取成绩的示例。运行上述代码,将输出:
Score1: 98.50, Score2: 65.50
这就是我们今天的内容,希望大家能够有所收获。如果有任何问题,欢迎随时提问。
注意:在使用sprintf
和sscanf
时,需要确保目标字符串有足够的空间来存储结果,以避免溢出。同时,了解这些函数的工作原理有助于我们更好地理解和使用它们。
16 常用系统函数:时间函数
大家好,今天我们来聊聊C语言中与时间相关的常用系统函数。这些函数可以帮助我们获取当前时间、转换时间格式等。
时间函数简介
在C语言中,时间相关的函数通常包含在time.h
头文件中。我们可以使用这些函数来处理与时间相关的操作。
time函数
time
函数用于获取当前时间的时间戳。时间戳是从1970年1月1日00:00:00 UTC到当前时间所经过的秒数。
函数原型
c
time_t time(time_t *t);
t
:如果传入NULL,函数返回当前时间的时间戳;如果传入一个地址,函数将当前时间的时间戳存储在该地址指向的变量中。
示例代码
c
#include <stdio.h>
#include <time.h>int main() {time_t now; // 用于存储当前时间的时间戳time(&now); // 获取当前时间的时间戳printf("Current time: %ld\n", now);return 0;
}
ctime函数
ctime
函数用于将时间戳转换为可读的字符串形式。
函数原型
c
char *ctime(const time_t *t);
t
:指向时间戳的指针。
示例代码
c
#include <stdio.h>
#include <time.h>int main() {time_t now; // 用于存储当前时间的时间戳time(&now); // 获取当前时间的时间戳printf("Current time: %s", ctime(&now));return 0;
}
difftime函数
difftime
函数用于计算两个时间戳之间的差值,返回它们之间的秒数。
函数原型
c
double difftime(time_t time1, time_t time2);
time1
和time2
:两个时间戳。
示例代码
c
#include <stdio.h>
#include <time.h>int main() {time_t start, end;double duration;// 获取开始时间time(&start);// 执行一些操作,例如计算前n项和for (int i = 0; i < 1000000; i++) {// 模拟计算}// 获取结束时间time(&end);// 计算持续时间duration = difftime(end, start);printf("Duration: %f seconds\n", duration);return 0;
}
练习题
假设我们需要计算一段代码执行的时间,请编写相应的代码。
答案
上述代码已经给出了计算代码执行时间的示例。运行上述代码,将输出代码执行的持续时间。
这就是我们今天的内容,希望大家能够有所收获。如果有任何问题,欢迎随时提问。
注意:在使用时间函数时,需要确保头文件time.h
已经被包含。这些函数为我们提供了一种方便的方式来处理时间相关的操作,例如获取当前时间、转换时间格式等。
17 常用系统函数:数学函数
大家好,今天我们来聊聊C语言中与数学计算相关的常用系统函数。这些函数都包含在math.h
头文件中,是我们进行数学运算时的好帮手。
数学函数简介
在C语言中,数学相关的函数可以帮助我们进行各种数学计算,如求平方根、立方根、幂运算等。
sqrt函数
sqrt
函数用于计算平方根。
函数原型
c
double sqrt(double x);
x
:要计算平方根的数值。
示例代码
c
#include <stdio.h>
#include <math.h>int main() {double result = sqrt(16);printf("Square root of 16: %lf\n", result);return 0;
}
cbrt函数
cbrt
函数用于计算立方根。
函数原型
c
double cbrt(double x);
x
:要计算立方根的数值。
示例代码
c
#include <stdio.h>
#include <math.h>int main() {double result = cbrt(8);printf("Cube root of 8: %lf\n", result);return 0;
}
pow函数
pow
函数用于计算幂运算。
函数原型
c
double pow(double base, double exponent);
base
:底数。exponent
:指数。
示例代码
c
#include <stdio.h>
#include <math.h>int main() {double result = pow(2, 10);printf("2 to the power of 10: %lf\n", result);return 0;
}
fabs函数
fabs
函数用于计算绝对值。
函数原型
c
double fabs(double x);
x
:要计算绝对值的数值。
示例代码
c
#include <stdio.h>
#include <math.h>int main() {double result = fabs(-5.5);printf("Absolute value of -5.5: %lf\n", result);return 0;
}
取整函数
C语言中还有几个常用的取整函数:ceil
、floor
、round
和trunc
。
ceil
:向上取整。floor
:向下取整。round
:四舍五入取整。trunc
:截断小数部分。
示例代码
c
#include <stdio.h>
#include <math.h>int main() {double x = 12.34;printf("Ceil of %lf: %lf\n", x, ceil(x));printf("Floor of %lf: %lf\n", x, floor(x));printf("Round of %lf: %lf\n", x, round(x));printf("Trunc of %lf: %lf\n", x, trunc(x));return 0;
}
练习题
- 计算并打印100的平方根。
c
#include <stdio.h>
#include <math.h>int main() {double result = sqrt(100);printf("Square root of 100: %lf\n", result);return 0;
}
- 计算并打印5的立方根。
c
#include <stdio.h>
#include <math.h>int main() {double result = cbrt(5);printf("Cube root of 5: %lf\n", result);return 0;
}
- 计算并打印3的5次方。
c
#include <stdio.h>
#include <math.h>int main() {double result = pow(3, 5);printf("3 to the power of 5: %lf\n", result);return 0;
}
- 计算并打印-8.2的绝对值。
c
#include <stdio.h>
#include <math.h>int main() {double result = fabs(-8.2);printf("Absolute value of -8.2: %lf\n", result);return 0;
}
- 判断一个数是否为质数,并定义成函数返回布尔值。
c
#include <stdio.h>
#include <math.h>int isPrime(int num) {if (num <= 1) return 0;for (int i = 2; i <= sqrt(num); i++) {if (num % i == 0) return 0;}return 1;
}int main() {int num = 17;printf("Is %d a prime number? %s\n", num, isPrime(num) ? "Yes" : "No");return 0;
}
- 打印金字塔形状的乘法表。
c
#include <stdio.h>void printPyramid(int n) {for (int i = 1; i <= n; i++) {for (int j = 1; j <= i; j++) {printf("%d*%d=%-2d ", j, i, j * i);}printf("\n");}
}int main() {int n = 5;printPyramid(n);return 0;
}
这就是我们今天的内容,希望大家能够有所收获。如果有任何问题,欢迎随时提问。
注意:在使用数学函数时,需要确保头文件math.h
已经被包含。这些函数为我们提供了一种方便的方式来进行数学计算。
18 C语言学习笔记 - 复习总结
大家好,今天我们来回顾一下之前讲到的C语言的基本概念和知识点。
函数的基本概念
函数是可重用的代码块,有名字,可以有输入(参数)和输出(返回值)。函数的声明语法包括返回类型、函数名和参数列表。函数体是花括号括起来的代码,表示函数的具体执行过程。
函数的返回值和参数
- 函数可以有返回值,也可以没有。没有返回值的函数通常返回类型为
void
。 - 函数的参数分为形式参数(形参)和实际参数(实参)。形参在函数声明或定义时使用,实参在函数调用时传递。
函数调用
函数调用时,实参的数量和类型必须与形参完全一致,否则会报错。
作用域和生命周期
- 全局作用域:全局变量在程序的任何地方都可见。
- 局部作用域:局部变量只在定义它们的函数或代码块内部可见。
- 块级作用域:C99新标准引入,针对代码块内部的变量。
- 生命周期:全局变量的生命周期贯穿整个程序运行的始终,局部变量的生命周期仅限于函数的执行期间。
静态关键字
static
关键字可以修饰局部变量,使其生命周期延长至整个程序执行期间,但作用域仍然限定在局部。static
全局变量只能在定义它们的文件内部访问。
递归函数
递归函数是自己调用自己的函数。递归必须有明确的结束条件和趋近于结束条件的趋势。
递归函数的特点
- 递归函数必须有结束条件,否则会无限递归。
- 递归函数通常通过参数的变化来控制递归的深度。
常用系统函数
字符串函数
strlen
:计算字符串长度。strcpy
:复制字符串。strcat
:拼接字符串。
时间函数
time
:获取当前时间的时间戳。ctime
:将时间戳转换为可读的字符串。
数学函数
sqrt
:计算平方根。cbrt
:计算立方根。pow
:计算幂运算。fabs
:计算绝对值。ceil
、floor
、round
、trunc
:不同类型的取整函数。
练习题
- 计算100的平方根并打印。
c
#include <stdio.h>
#include <math.h>int main() {double result = sqrt(100);printf("Square root of 100: %lf\n", result);return 0;
}
- 判断一个数是否为质数,并定义成函数返回布尔值。
c
#include <stdio.h>
#include <math.h>int isPrime(int num) {if (num <= 1) return 0;for (int i = 2; i <= sqrt(num); i++) {if (num % i == 0) return 0;}return 1;
}int main() {int num = 17;printf("Is %d a prime number? %s\n", num, isPrime(num) ? "Yes" : "No");return 0;
}
这就是我们今天的内容,希望大家能够有所收获。如果有任何问题,欢迎随时提问。
注意:在编写C语言程序时,理解函数、作用域、递归和常用系统函数的概念是非常重要的。这些知识点将帮助你更好地理解和编写C程序。
相关文章:
第六天: C语言核心概念与实战技巧全解析
1 主函数(main) 大家好,今天我们来深入探讨一下C语言中非常特殊的一个函数——main函数。虽然大家对它并不陌生,但是它的重要性和特殊性值得我们再次回顾。 main函数的定义 main函数是我们整个C源程序的入口点。计算机在运行程…...

初始JavaEE篇——多线程(5):生产者-消费者模型、阻塞队列
找往期文章包括但不限于本期文章中不懂的知识点: 个人主页:我要学编程程(ಥ_ಥ)-CSDN博客 所属专栏:JavaEE 文章目录 阻塞队列生产者—消费者模型生产者—消费者模型的优势:生产者—消费者模型的劣势: Java标准库中的阻…...

2024年下教师资格证面试报名详细流程❗
⏰ 重要时间节点: (一)下半年笔试成绩查询:11月8日10:00 (二)注册报名:11月8日10:00-11日18:00 (三)网上审核:11月8日10:00-11日18:00 (四&#x…...
软考:常用协议和端口号
常用协议及其对应的端口号如下: TCP/IP协议: TCP(传输控制协议):端口号为6UDP(用户数据报协议):端口号为17 网络应用协议: HTTP(超文本传输协议)…...

Linux更改符号链接
目录 1. 删除旧链接 2. 创建新的符号链接 例如我的电脑上有两个版本的cuda,11.8和12.4 1. 删除旧链接 rm cuda 2. 创建新的符号链接 ln -s /usr/local/cuda-11.8/ /usr/local/cuda...

int main(int argc,char* argv[])详解
#include <stdio.h> //argc 是指命令行输入参数的个数; //argv[]存储了所有的命令行参数, //arg[0]通常指向程序中的可执行文件的文件名。在有些版本的编译器中还包括程序文件所在的路径。 //如:"d:\Production\Software\VC_2005_Test\Win32控制台应用程序\Vc_T…...

单片机原理及应用笔记:C51流程控制语句与项目实践
作者介绍 周瑞康,男,银川科技学院,计算机人工智能学院,2022级计算机科学与技术8班本科生,单片机原理及应用课程第八组。 指导老师:王兴泽 电子邮箱2082545622qq.com 前言: 本篇文章是参考《…...

大数据日志处理框架ELK方案
介绍应用场景大数据ELK日志框架安装部署 一,介绍 大数据日志处理框架ELK(Elasticsearch、Logstash、Kibana)是一套完整的日志集中处理方案,以下是对其的详细介绍: 一、Elasticsearch(ES) 基本…...

VQGAN(2021-06:Taming Transformers for High-Resolution Image Synthesis)
论文:Taming Transformers for High-Resolution Image Synthesis 1. 背景介绍 2022年中旬,以扩散模型为核心的图像生成模型将AI绘画带入了大众的视野。实际上,在更早的一年之前,就有了一个能根据文字生成高清图片的模型——VQGAN…...

docker中使用ros2humble的rviz2不显示问题
这里写目录标题 docker中使用ros2humble的rviz2不显示问题删除 Docker 镜像和容器删除 Docker 容器Linux服务器下查看系统CPU个数、核心数、(make编译最大的)线程数总结: RVIZ2 不能显示数据集 docker中使用ros2humble的rviz2不显示问题 问题描述: roo…...

【AIGC】2024-arXiv-Lumiere:视频生成的时空扩散模型
2024-arXiv-Lumiere: A Space-Time Diffusion Model for Video Generation Lumiere:视频生成的时空扩散模型摘要1. 引言2. 相关工作3. Lumiere3.1 时空 U-Net (STUnet)3.2 空间超分辨率的多重扩散 4. 应用4.1 风格化生成4.2 条件生成 5. 评估和比较5.1 定性评估5.2 …...
正则表达式:文本处理的强大工具
正则表达式是一种强大的文本处理工具,它允许我们通过定义一系列的规则来匹配、搜索、替换或分割文本。在编程、文本编辑、数据分析和许多其他领域中,正则表达式都扮演着重要的角色。本文将介绍正则表达式的基本概念、语法和一些实际应用。 正则表达式的…...
Doris单机安装
1、安装包下载 官网地址:https://doris.apache.org/zh-CN/docs/gettingStarted/quick-start/ 下载地址:https://apache-doris-releases.oss-accelerate.aliyuncs.com/apache-doris-3.0.2-bin-x64.tar.gz 2、操作系统环境准备 #环境准备 cat /proc/cp…...

ubuntu内核更新导致显卡驱动掉的解决办法
方法1,DKMS指定内核版本 用第一个就行 1,借鉴别人博客解决方法 2,借鉴别人博客解决方法 方法2,删除多于内核的方法 系统版本:ubuntu20.24 这个方法是下下策,如果重装驱动还是不行,就删内核在…...

【Java数据结构】树】
【Java数据结构】树 一、树型结构1.1 概念1.2 特点1.3 树的类型1.4 树的遍历方式1.5 树的表示形式1.5.1 双亲表示法1.5.2 孩子表示法1.5.3 孩子双亲表示法1.5.4 孩子兄弟表示法 二、树型概念(重点) 此篇博客希望对你有所帮助(帮助你了解树&am…...

Java面试题——微服务篇
1.微服务的拆分原则/怎么样才算一个有效拆分 单一职责原则:每个微服务应该具有单一的责任。这意味着每个服务只关注于完成一项功能,并且该功能应该是独立且完整的。最小化通信:尽量减少服务之间的通信,服务间通信越少,…...

Python 中 print 函数输出多行并且选择对齐方式
代码 # 定义各类别的标签和对应数量 categories ["class0", "class1", "class2", "class3", "class4", "class5"] counts [4953, 547, 5121, 8989, 6077, 4002]# 设置统一的列宽 column_width 10# 生成对齐后…...

书生营L0G3000 Git 基础知识
任务1: 破冰活动:自我介绍 用vi就行了 按照教程来就好了 git会报错密码,输入的时候换成token就好了 https://stackoverflow.com/questions/68775869/message-support-for-password-authentication-was-removed 提交。(github上预览自己的…...

【C++初阶】模版入门看这一篇就够了
文章目录 1. 泛型编程2. 函数模板2. 1 函数模板概念2. 2 函数模板格式2. 3 函数模板的原理2. 4 函数模板的实例化2. 5 模板参数的匹配原则2. 6 补充:使用调试功能观察函数调用 3. 类模板3 .1 类模板的定义格式3. 2 类模板的实例化 1. 泛型编程 在C语言中࿰…...

Spring Bean创建流程
Spring Bean 创建流程图 大家总是会错误的理解Bean的“实例化”和“初始化”过程,总会以为初始化就是对象执行构造函数生成对象实例的过程,其实不然,在初始化阶段实际对象已经实例化出来了,初始化阶段进行的是依赖的注入和执行一…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...

Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台
淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...

MLP实战二:MLP 实现图像数字多分类
任务 实战(二):MLP 实现图像多分类 基于 mnist 数据集,建立 mlp 模型,实现 0-9 数字的十分类 task: 1、实现 mnist 数据载入,可视化图形数字; 2、完成数据预处理:图像数据维度转换与…...

SOC-ESP32S3部分:30-I2S音频-麦克风扬声器驱动
飞书文档https://x509p6c8to.feishu.cn/wiki/SKZzwIRH3i7lsckUOlzcuJsdnVf I2S简介 I2S(Inter-Integrated Circuit Sound)是一种用于传输数字音频数据的通信协议,广泛应用于音频设备中。 ESP32-S3 包含 2 个 I2S 外设,通过配置…...