Lua基础知识入门

1 基础知识

标识符:标识符的定义和 C语言相同:字母和下划线_ 开头, 下划线_ + 大写字母一般是lua保留字, 如_VERSION
全局变量:默认情况下,变量总是认为是全局的,不需要申明,给一个变量赋值后即创建了这个全局变量,访问一个没有初始化的全局变量也不会出错,只不过得到的结果是:nil

2 数据类型

数据类型:lua是动态型语言,变量不需要类型定义,直接赋值即可。 值可以存储在变量中,作为参数传递或者结果return
nil: 无效值, 在条件表达式中相当于false
boolean: true false, 注意: false 和 nil 看作是 false,其他的都为 true,数字 0 也是 true
number: 双精度类型的实浮点数 相当于double, 注意:Lua 默认只有一种 number 类型 – double(双精度)类型(默认类型可以修改 luaconf.h 里的定义)
string:字符串,由一对双引号或者单引号表示
funtcion: 由c或者lua编写的函数
userdata:表示任意存储在变量中的c数据结构
thread:表示执行的独立线路,用于执行协同程序
table:Lua 中的表(table)其实是一个"关联数组"(associative arrays),数组的索引可以是数字、字符串或表类型。
– 在 Lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个空表。

–可以使用type函数测试给定变量或者值的类型:
print(type(“Hello world”))
print(type(66))
print(type(‘66’))
print(type(“66”))
print(type(nil))

2.1 多重赋值

Lua可以对多个变量同时赋值,变量用逗号分开,赋值语句右边的值会依次赋给左边的变量

n = 1
a, b = 10, 2*n

2.2 交换变量

a = 34
b = 12
a, b = b, a
print(a, b) --输出:12   34

3 运算符

3.1 算数运算符

+ 加法
- 减法
* 乘法
/ 除法
% 取余,求出除法的余数
^ 乘幂,计算次方
- 负号,取负值

3.2 逻辑运算符

a = true
b = false
c = nil

print(a and b) -- 与  输出:false
print(a or b)  -- 或  输出:true
print(not a)   -- 非  输出:false

4 字符串相关

字符串的三种表示方式:

  1. 单引号间的一串字符
  2. 双引号间的一串字符
  3. [[…]] 间的一串字符, 支持换行

4.1 字符串操作

4.1.1字符串拼接: …

print("d"  ..  "cj")

4.1.2字符串转换

c = tostring(10) -- 数字 转 字符串 
print(c)

d = tonumber("666") --字符串转数字,若转换失败返回nil
print(d)

e = tonumber("abc")
print(e)

输出:
image.png

4.1.3 获取字符串长度

str = "dcj666"
print(#str)
print(#"dcj666")

输出:
image.png

5 函数

function lua_func_test(n)
    if 0 == n then
        print("0 == n")
        return 0
    else 
        print("1 == n")
        return n
    end
end

--这与上述是一样的
lua_func_test2 = function(n)
    if 0 == n then
        print("0 == n")
        return 0
    else 
        print("1 == n")
        return n
    end
end

ret = lua_func_test(5)
print(ret)

输出:
image.png

函数支持多值返回:

function lua_func_test_02(a, b, c)
    return a, b, c
end
local i, j, k = lua_func_test_02(11, 22, 33)
print(i, j, k)

输出:
image.png

6 Table

lua的table中可以放置任意类型的数据:如number,string,function等

6.1 数字下标:从 1 开始

注意:lua中数组下标从 1 开始

a = {112,  {}, function () end, "dcj"}
print(a[1])
print(#a) --获取table元素个数

a[1] = 666
print(a[1])

table.insert(a, 2, "666")  --在a[2]处插入"666"
local s = table.remove(a, 2)  --删除a[2]这个元素, 并将删除的元素返回给s

输出:
image.png

function做table的元素

funcList = {
    function(a, b) return a*b end,
    function(a, b) return a-b end,
    function(a) return (-a) end
}
print(funcList[1](3,4))
print(funcList[2](3,4))
print(funcList[3](3))

输出:
image.png

6.2 table下标:指定下标

前面例子中的table都只是一些简单的List(列表),每个元素的下标都是自动从1排列的
实际上,Lua中,下标可以直接在声明时进行指定,像下面这样:

t = {6,7,8,9}
--上面和下面的代码等价
t = {
    [1] = 6,
    [2] = 7,
    [3] = 8,
    [4] = 9,
}

--甚至你可以跳过某些下标
t = {
    [1] = 6,
    [3] = 7,
    [5] = 8,
    [7] = 9,
}
print(t[7]) --输出9

--在声明后赋予元素值也是可以的
t = {}--空的table
t[101] = 10
print(t[101]) --输出10
t = {
    [1] = 123,
    [13] = "abc",
    [666] = "666",
}

print("下标为1的元素:",t[1],type(t[1]))
print("下标为13的元素:",t[13],type(t[13]))
print("下标为666的元素:",t[666],type(t[666]))

输出:
下标为1的元素:  123     number
下标为13的元素: abc     string
下标为666的元素:        666     string

6.3 字符串做下标

前面学习的table下标都是数字,在lua中,下标也可以是字符串:

t = {
	a1 = "aa",
    ["666"] = "666", -- 666 = "666", 这样会报错
  	["apple"] = 10,
    banana = 12,
    pear = 6,
}
--使用["下标"] = 值  和  下标 = 值  都是正确写法, 当第二种方式有歧义时,应该用第一种方式

t["new"] = "new values" -- 也可以新增

--可以用下面两种方式访问:
print(t["apple"]) --输出10
print(t.apple) --输出10

print(t["666"]) --输出666
--print(t.666) --报错

print(t["banana"]) --输出12
print(t.banana) --输出12

print(t["new"]) --输出new values
t = {
    apple = {
        price = 7.52,
        weight = 2.1,
    },
    banana = {
        price = 8.31,
        weight = 1.4,
        year = '2018'
    },
    year = '2019',
    {
        price = 6.21,
        weight = 2.5,
    },
}

print(
    t.price,                --输出nil
    t.apple.price,          --输出7.52
    t.banana.weight,        --输出1.4
    t.year,                 --输出2019
    t[1].price,             --输出6.21
    t[1].weight             --输出2.5
)


print(  
    t["price"],             --输出nil
    t["apple"]["price"],    --输出7.52
    t["banana"]["weight"],  --输出1.4
    t["year"]               --输出2019
)

7 全局表 _G

lua中所有的全局变量都在** _G** 这个table中
例如定义一个全局变量a, 在_G这个table中打印出来:

dcj = 666;
print(_G["dcj"])

table自身也是个全局变量,也在_G中, 并且table.insert中的insert函数是table的下标,也可以将insert打印出来:

print(_G["table"])
print(_G["table"]["insert"])

输出:
image.png

8 boolean类型

注意:lua中只有false和nil表示假, 其余都为真(0也表示真)

a = true
b = false
c = nul

print(1 < 2)
print(1 > 2)
print(1 >= 2)
print(1 <= 2)
print(1 == 2)
print(1 ~= 2)  --  注意:~=表示不等于

print(a and b) -- 与 
print(a or b)  -- 或
print(not a)   -- 非

输出:
image.png

b = 1
print(b > 10 and "yes" or "no")

b = 11
print(b > 10 and "yes" or "no")

输出:no
yes

9 分支判断

a = 2

if a == 1 then
    print("a == 1")
elseif a == 2 then
    print("a == 2")
elseif a == 3 then
    print("a == 3")
else
    print(a)
end

if 0 then
	print("0 is true")
end

输出:
a == 2
0 is true

10 循环

10.1 for循环

image.png
临时变量名可以直接在代码区域使用(但不可更改),每次循环会自动加步长值,并且在到达结束值后停止循环。

for i = 1, 10, 2  do  -- 1表示循环储值,10表示结束值, 2表示步长, i的作用域仅仅在for循环内部
	print(i)
end

print(i) -- 输出nil,i的作用域仅仅在for循环内部

10.2 while循环

local n = 10

while n >= 1 do
	if n==5 then
		break --跳出循环
	end
	
	print(n)
	n = n - 1   -- lua 不支持 n-- 这种操作
end

输出:
image.png

11 迭代器

pairs和ipairs的区别:
:::info
:都是能遍历集合(表、数组),两者均优先按顺序输出没有key的值;
:::
:::info
:对于有key的集合:
ipairs从第一个数字key开始,依次输出所有的key+1的键值,遇到字符下标并不会结束遍历,只是不输出而已,如果遇到nil则退出;
pairs无序输出字符类型key或者数字类型key的键值,遇到nil不输出,但不会停止遍历;
:::

11.1 ipairs

t = {"aa", "bb", "cc", "dd", "ee"}

for i = 1, #t  do  --从下标1开始,到下标#t结束(#t表示t的元素个数)
	print(i, t[i])
end

--针对数字下标的数组,可以使用ipairs迭代器
--等同于下面
for i, j  in ipairs(t)  do  -- i表示下标, j存放下标i对应的值
	print(i, j)
end

输出:
image.png

t = {
	[1] = "aaaaaa",
	[2] = "bbbbbbb",
	[3] = "ccccccc",
	[5] = "ddddddddd"  --下标不连续,t[4]为nil,遇到nil会自动停止
}

for i, j  in ipairs(t)  do  -- i表示下标, j表示下标i对应的值
	print(i, j)
end

for i, j  in pairs(t)  do  -- i表示下标, j表示下标i对应的值
	print(i, j)
end

输出:
image.png
结论:
1、ipairs会按照key的顺序输出数据,遇到不连续的数据停止输出;
2、pairs会无序输出所有数据;

table = { 
    [3] = "test3",
    ["test"] = "val1",
    "val3" ,
    [4] = "val2",
    "val4"
}
print("-----------ipairs----------------")
for k,v in ipairs(table) do
    print(k,v)
end
print("-----------pairs----------------")
for k,v in pairs(table) do
    print(k,v)
end

image.png
结论:
1、pairs和ipairs均优先输出没有key的value;
2、pairs会输出所有的数据,不带key的值按顺序输出,带key的值无序输出;
3、ipairs会跳过字符串的key,按顺序输出数字型key的值;

table = { 
    [6] = "test3",
    ["test"] = "val1",
    "val3" ,
    [11] = "val2",
    nil,
    "val4"
}
print("-----------ipairs----------------")
for k,v in ipairs(table) do
    print(k,v)
end
print("-----------pairs----------------")
for k,v in pairs(table) do
    print(k,v)
end

输出:
image.png
结论:
1、ipairs遇到nil会停止输出;
2、pairs遇到nil不会停止输出;

11.2 pairs

针对字符串做数组下标的数组迭代,使用pairs迭代器

t = {
	apple = "aa",
	banana = "bb",
	water = "cc",
}
for i, j  in pairs(t)  do  -- i表示下标, j存放下标i对应的值
	print(i, j)
end

输出:
image.png

12 多文件调用require

require:

  1. 运行指定文件
  2. 末尾不带拓展名
  3. 目录层级用“.”分隔
  4. 只会运行一次
  5. 从package.path中的路径里查找

13 元表、面向对象

t =     {
    a = 66,
}
mt = {
    __add = function(a, b)
        return a.a + b
    end,
    __index = function(table, key)
        return 123
    end
}
setmetatable(t, mt)
print(t+1) --输出67
print(t["dcj"]) --访问一个不存在的下标,会调用__index元方法, 输出123



t = {
    a = 66,
}
mt = {
    __add = function(a, b)
        return a.a + b
    end,
    __index = {
        abc = 123,
        def = 456,
    },
}
setmetatable(t, mt)
print(t["dcj"]) --__index也可以是个table, 在__index也可以是个table找“dcj”元素,输出nil
print(t["abc"]) --__index也可以是个table, 在__index也可以是个table找“abc”元素, 输出123
print(t["def"]) --__index也可以是个table, 在__index也可以是个table找“def”元素, 输出456

image.png

13.1 语法糖:

t = {
    a = 66,
    add = function(tab, sum)
        tab.a = tab.a + sum
    end,
}

t:add(10) -- 等价于 t.add(t, 10), 输出:76
print(t.a)

13.2 面向对象

需要好好理解!!!

bag = {

}
bagmt = {
    put = function(t, item)
        table.insert(t.items, item)
    end,
    take = function(t)
        return table.remove(t.items, item)
    end,
    list = function(t)
        return table.concat(t.items, ", ")
    end,
    clear = function(t)
        t.items = {}
    end,
}
bagmt["__index"] = bagmt
function bag.new()
    local t = {
        items  = {}
    }
    setmetatable(t, bagmt) --当调用t中不存在的函数的时候,就回去t的metatable中去找
    return t
end

--bag.new()函数中会新建一个表t,t设置了元表bagmt, bagmt中有四个元方法(put,take,list,clear)
--由于b中没有put这些方法,所以回去bagmt中找
local b = bag.new()
b:put("apple1") --等价于b.put(b, "apple1"), 将"apple1"放入b的items表中 
b:put("apple2")
b:put("apple3")
b:put("apple4")

print(b:take())

print(b:list())

14 数据打包和解包

aaa = 0x11223344
bbb = 0x55667788

data = string.pack(">LL", aaa, bbb)  --数据打包

print("len:", #data)

for i=1, #data do
    print(i, data:byte(i))
end

a, b = string.unpack(">LL", data)  --数据解包
str_a = string.format("0x%x", a)
str_b = string.format("0x%x", b)

print("str_a: ", str_a)
print("str_b: ", str_b)

输出:
image.png

15 C语言与lua的相关调用

15.1 C语言中调用lua

c代码只需要编译一次,lua可以随时改动;因为lua是动态语言。嵌入lua的好处是c只需要写一次代码,编译一次程序,所有的变化都可以通过修改lua的代码.
main.c 中调用math.lua中的函数

/*
 * @Descripttion: xx模块
 * @Author: cjDong
 * @Date: 2024-07-15 11:30:05
 * @LastEditors: cjDong
 * @LastEditTime: 2024-07-17 14:07:04
 */

#include <stdio.h>

#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"


static int call_func(lua_State *L, const char* funcname, int x, int y)
{
    int ret;
    lua_getglobal(L, funcname); // 查找lua文件中的全局函数,并压入虚拟栈

    /* 压栈,传入参数 */
    lua_pushnumber(L, x);
    lua_pushnumber(L, y);
    
    lua_call(L, 2, 1); /* 执行函数,lua_call 的参数中第二个是参入参数个数,第三个是返回值个数 */

    /* 取出返回值 */
    ret = (int)lua_tonumber(L, -1);

    /*清除返回值的栈*/
    lua_pop(L, 1);

    return ret;
}


int main(int argc, char *argv[])
{
    lua_State *L = luaL_newstate();  /* 创建lua虚拟机 */
    luaL_openlibs(L);     /* 加载lua库,比如math库、table库等 */

    /* 加载lua文件到c语言内存中,进行语法检查,不会编译 */
    luaL_dofile(L, "math.lua");

    /* 调用C函数,这个里面会调用lua函数 */
    call_func(L, "add", 2, 3);
    call_func(L, "sub", 2, 3);
    call_func(L, "mul", 2, 3);
    call_func(L, "div", 2, 3);

    /* 清除Lua */
    lua_close(L);
    
    return 0;
}
function add(x, y)
    print("lua: add function\r\n")
    return x + y
end

function sub(x, y)
    print("lua: sub function\r\n")
    return x - y
end

function mul(x, y)
    print("lua: mul function\r\n")
    return x * y
end

function div(x, y)
    print("lua: div function\r\n")
    return x / y
end
#!/bin/bash

gcc  -o out main.c -llua -ldl -lm

./out

15.2 lua中调用c语言

Q:Lua调用C函数的两种方式?
A:
1、程序主体在C中运行,C函数注册到Lua中。C调用Lua,Lua调用C注册的函数,C得到函数的执行结果。
2、程序主体在Lua中运行,C函数作为库函数供Lua使用。
第一种方式看起来很罗嗦,也很奇怪。既然程序主体运行在C中,而且最终使用的也是C中定义的函数,那么为何要将函数注册给Lua,然后再通过Lua调用函数呢?
相比于第一种方式,第二种方式使用的更加普遍。
一个Lua库(Lua本身所提供的库)实际上是一个定义了若干Lua函数的”chunk”,这些函数通常作为”table”的域来保存。一个C库(C语言编写,注册给Lua使用的库)的实现方式类似于Lua库的实现方式。首先C库中定义提供给Lua使用的函数,其次还需要一个“特殊函数”,它的作用是注册所有C库中的函数,并将它们存储在适当的位置(类似于Lua库中的函数作为”table”的域来保存)。
Lua可以调用C库中的函数,就是通过这个注册的过程实现的。一旦C函数注册到Lua中,Lua就可以直接通过C函数的引用获取到C函数的地址(这也是我们注册的意义,将C函数的地址提供给Lua)。换句话说,一旦C函数注册,Lua调用他们不依赖于函数名,”package”位置,或者是可见规则。
以上两种方式下面都会列举对应的例子,理解第一种方式,将有助于你理解第二种方式的实现流程。

Q:从Lua中调用C所遵循的规则?
A:当C调用Lua函数的时候,必须遵循一些简单的协议来传递参数和获取返回结果。同样的,从Lua中调用C函数,也必须遵循一些协议来传递参数和获得返回结果。此外,从Lua调用C函数我们必须注册函数,也就是说,我们必须把C函数的地址以一个适当的方式传递给Lua解释器。
任何在Lua中注册的C函数必须有同样的原型,
typedef int (*lua_CFunction) (lua_State *L); // 定义在"lua.h"中。
被注册的C函数接收一个单一的lua_State类型的参数,同时返回一个表示返回值个数的数字。函数在将返回值入栈之前无需清理栈,在函数返回之后,Lua会自动清除栈中返回结果下面的所有内容。

15.2.1 方式1:程序主体在C中运行

该方式看起来很罗嗦,也很奇怪。既然程序主体运行在C中,而且最终使用的也是C中定义的函数,那么为何要将函数注册给Lua,然后再通过Lua调用函数呢?

15.2.2 方式2:程序主体在Lua中运行

该方式使用的更加普遍

#include <stdio.h>
#include <math.h>
#include <stdarg.h>
#include <stdlib.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>


/* 所有注册给Lua的C函数具有
 * "typedef int (*lua_CFunction) (lua_State *L);"的原型。
 */
static int l_sin(lua_State *L)
{   
    // 如果给定虚拟栈中索引处的元素可以转换为数字,则返回转换后的数字,否则报错。
    double d = luaL_checknumber(L, 1);
    lua_pushnumber(L, sin(d));  /* push result */

    /* 这里可以看出,C可以返回给Lua多个结果,
     * 通过多次调用lua_push*(),之后return返回结果的数量。
     */
    return 1;  /* number of results */
}



/* 需要一个"luaL_Reg"类型的结构体,其中每一个元素对应一个提供给Lua的函数。
 * 每一个元素中包含此函数在Lua中的名字,以及该函数在C库中的函数指针。
 * 最后一个元素为“哨兵元素”(两个"NULL"),用于告诉Lua没有其他的函数需要注册。
 */
static const struct luaL_Reg mylib[] = {
    {"mysin", l_sin},
    {NULL, NULL}
};



/* 此函数为C库中的“特殊函数”。
 * 通过调用它注册所有C库中的函数,并将它们存储在适当的位置。
 * 此函数的命名规则应遵循:
 * 1、使用"luaopen_"作为前缀。
 * 2、前缀之后的名字将作为"require"的参数。
 */
extern int luaopen_mylib(lua_State* L)
{
    /* void luaL_newlib (lua_State *L, const luaL_Reg l[]);
     * 创建一个新的"table",并将"mylib"中所列出的函数注册为"table"的域。
     */ 
    luaL_newlib(L, mylib);

    return 1;
}
--[[ 
    这里"require"的参数对应C库中"luaopen_mylib()"中的"mylib"。
     C库就放在"main.lua"的同级目录,"require"可以找到。
]]


local mylib = require "mylib"

-- 结果与上面的例子中相同,但是这里是通过调用C库中的函数实现。
print(mylib.mysin(3.14 / 2))    --> 0.99999968293183
gcc math.c -fPIC -shared -o mylib.so -Wall

lua main.lua

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/843534.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

docker默认存储地址 var/lib/docker 满了,换个存储地址操作流程

1. 查看docker 存储地址 docker info如下 var/lib/docker2、查看内存大小 按需执行 df -h 找超过100M的大文件 find / -type f -size 100M -exec ls -lh {} \; df -Th /var/lib/docker 查找这个文件的容量 df -h 查找所有挂载点 du -hs /home/syy_temp/*1、df -h 2、sud…

Linux网络——套接字与UdpServer

目录 一、socket 编程接口 1.1 sockaddr 结构 1.2 socket 常见API 二、封装 InetAddr 三、网络字节序 四、封装通用 UdpServer 服务端 4.1 整体框架 4.2 类的初始化 4.2.1 socket 4.2.2 bind 4.2.3 创建流式套接字 4.2.4 填充结构体 4.3 服务器的运行 4.3.1 rec…

全国区块链职业技能大赛国赛考题区块链产品需求分析与方案设计

任务1-1:区块链产品需求分析与方案设计 本任务需要依据项目背景完成需求分析与方案设计,具体要求如下: 依据给定区块链食品溯源系统的业务架构图,对考题进行业务分析,尽可能多的去考虑一个业务系统所需要的模块,使用Visio或思维导图工具展现本系统的基本设计概念和处理流…

基于ffmepg的视频剪辑

1.ffmpeg命令实现视频剪辑 FFmpeg是一个非常强大的视频处理工具&#xff0c;可以用来剪辑视频。以下是一个基本的FFmpeg命令行示例&#xff0c;用于剪辑视频&#xff1a; $ ffmpeg -i ./最后一滴水.mp4 -ss 0:0:20 -t 50 -c copy output.mp4-i ./最后一滴水.mp4 输入文件  …

图像生成(Text-to-Image)发展脉络

这篇博客对 图像生成&#xff08;image generation&#xff09; 领域的经典工作发展进行了梳理&#xff0c;包括重要的一些改进&#xff0c;目的是帮助读者对此领域有一个整体的发展方向把握&#xff0c;并非是对每个工作的详细介绍。 脉络发展&#xff08;时间顺序&#xff0…

探究大语言模型(LLM)漏洞和安全优秀实践

你可能已听说过LLM强势亮相&#xff0c;至少ChatGPT就是代表。 大语言模型(LLM)指语言处理模型。这类模型经过训练&#xff0c;可以执行各种各样的语言任务&#xff1a;翻译、文本生成和问题回答等。 有几个LLM家族和架构&#xff0c;最著名的是GPT(生成式预训练Transformer)…

Grafana :利用Explore方式实现多条件查询

背景 日志统一推送到Grafana上管理。所以&#xff0c;有了在Grafana上进行日志搜索的需求&#xff0c;而进行日志搜索通常需要多条件组合。 解决方案 通过Grafana的Explore的方式实现多条件查询。 直接看操作步骤&#xff1a; 在主页搜索框中输入“Explore” 进入这个界面…

python—日期相差多少天(PythonTip)

[题目描述] 编写一个程序&#xff0c;计算两个日期之间的天数。 导入datetime模块。定义函数calculate_days_between()数&#xff0c;其中有两个参数&#xff1a;(date1, date2)&#xff0c;类型为字符串&#xff0c;格式为YYYY-MM-DD。在函数内&#xff0c;将字符串转换为date…

全面战争模拟器免费下载地址,纯分享

全面战争模拟器以其独特的物理引擎和搞笑的战斗场面吸引了大量玩家&#xff0c;并在游戏社区中赢得了极高的评价。它不仅提供了丰富的策略性玩法&#xff0c;还通过滑稽的视觉效果和搞笑的战斗带来了极大的娱乐性。游戏的沙盒模式和自定义功能更是让玩家能够充分发挥创意&#…

磁盘的作业

1、新添加一块硬盘&#xff0c;大小为5g&#xff0c;给这块硬盘分一个mbr格式的主分区(大小为3g)&#xff0c;给此主分区创建ext2的文件系统&#xff0c;挂载到/guazai1目录&#xff0c;并写入文件内容为"this is fist disk"文件名为1.txt的文件。 [rootwyk ~]# fdis…

02线性表 - 链表

这里是只讲干货不讲废话的炽念&#xff0c;这个系列的文章是为了我自己以后复习数据结构而写&#xff0c;所以可能会用一种我自己能够听懂的方式来描述&#xff0c;不会像书本上那么枯燥和无聊&#xff0c;且全系列的代码均是可运行的代码&#xff0c;关键地方会给出注释^_^ 全…

【时时三省】(C语言基础)函数和数组

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ——csdn时时三省 函数 跟数学里面的函数很相似 数组 一组相同类型的元素的集合 比如把5个整形1-5存起来 int arr&#xff3b;10&#xff3d;&#xff1d;&#xff5b;1&#xff0c;2&#xff0c;3&#x…

逻辑门的题目怎么做?

FPGA语法练习——二输入逻辑门&#xff0c;一起来听~~ FPGA语法练习——二输入逻辑门 题目介绍&#xff1a;F学社-全球FPGA技术提升平台 (zzfpga.com)

高功能自闭症:挑战与潜能并存

高功能自闭症是一种复杂的神经发育障碍&#xff0c;其患者通常在认知、语言和行为方面存在发育障碍&#xff0c;但保持相对正常的社交互动和自理能力。这种疾病由大脑神经发育异常引起&#xff0c;涉及神经递质、脑结构和功能连接等多个方面&#xff0c;导致信息处理和整合困难…

WebRTC音视频-前言介绍

目录 效果预期 1&#xff1a;WebRTC相关简介 1.1&#xff1a;WebRTC和RTC 1.2&#xff1a;WebRTC前景和应用 2&#xff1a;WebRTC通话原理 2.1&#xff1a;媒体协商 2.2&#xff1a;网络协商 2.3&#xff1a;信令服务器 效果预期 1&#xff1a;WebRTC相关简介 1.1&…

SpringCloud的认识和初步搭建

目录 一.认识SpringCloud 二.SpringCloud的部署 2.1开发环境 2.2数据库的建立 2.3SpringCloud的部署 第一步&#xff1a; 创建Maven项目 第二步&#xff1a;完善pom文件 第三步&#xff1a;创建两个子项目 第四步&#xff1a;声明项目依赖以及构建插件 第五步&#xf…

Docker核心技术:容器技术要解决哪些问题

云原生学习路线导航页&#xff08;持续更新中&#xff09; 本文是 Docker核心技术 系列文章&#xff1a;容器技术要解决哪些问题&#xff0c;其他文章快捷链接如下&#xff1a; 应用架构演进容器技术要解决哪些问题&#xff08;本文&#xff09;Docker的基本使用Docker是如何实…

Ubuntu20.04从零开搭PX4MavrosGazebo环境并测试

仅仅是个人搭建记录 参考链接&#xff1a; https://zhuanlan.zhihu.com/p/686439920 仿真平台基础配置&#xff08;对应PX4 1.13版&#xff09; 语雀 mkdir -p ~/tzb/catkin_ws/src mkdir -p ~/tzb/catkin_ws/scripts cd catkin_ws && catkin init catkin build cd…

RV1103使用rtsp和opencv推流视频到网页端

参考&#xff1a; Luckfox-Pico/Luckfox-Pico-RV1103/Luckfox-Pico-pinout/CSI-Camera Luckfox-Pico/RKMPI-example Luckfox-Pico/RKMPI-example 下载源码 其中源码位置&#xff1a;https://github.com/luckfox-eng29/luckfox_pico_rtsp_opencv 使用git clone由于项目比较大&am…

共享模型之无锁

一、问题提出 1.1 需求描述 有如下的需求&#xff0c;需要保证 account.withdraw() 取款方法的线程安全&#xff0c;代码如下&#xff1a; interface Account {// 获取余额Integer getBalance();// 取款void withdraw(Integer amount);/*** 方法内会启动 1000 个线程&#xf…