規則引擎Drools使用,0基礎入門規則引擎Drools(二)高級語法

文章目錄

  • 系列文章索引
  • 五、規則屬性
    • 1、enabled屬性
    • 2、dialect屬性
    • 3、salience屬性
    • 4、no-loop屬性
    • 5、activation-group屬性
    • 6、agenda-group屬性
    • 7、auto-focus屬性
    • 8、timer屬性
    • 9、date-effective屬性
    • 10、date-expires屬性
  • 六、Drools高級語法
    • 1、global全局變量
    • 2、query查詢
    • 3、function函數
    • 4、LHS加強
      • (1)復合值限制in/not in
      • (2)條件元素eval
      • (3)條件元素not
      • (4)條件元素exists
      • (5)規則繼承
    • 5、RHS加強
      • (1)halt 終止后續規則
      • (2)getWorkingMemory
      • (3)getRule
    • 6、規則文件編碼規范

系列文章索引

規則引擎Drools使用,0基礎入門規則引擎Drools(一)基礎入門
規則引擎Drools使用,0基礎入門規則引擎Drools(二)高級語法
規則引擎Drools使用,0基礎入門規則引擎Drools(三)整合springboot
規則引擎Drools使用,0基礎入門規則引擎Drools(四)WorkBench控制臺
規則引擎Drools使用,0基礎入門規則引擎Drools(五)實戰+決策表

五、規則屬性

前面我們已經知道了規則體的構成如下:

rule "ruleName"attributeswhenLHSthenRHS
end

Drools中提供的屬性如下表(部分屬性):

屬性名說明
salience指定規則執行優先級
dialect指定規則使用的語言類型,取值為java和mvel
enabled指定規則是否啟用
date-effective指定規則生效時間
date-expires指定規則失效時間
activation-group激活分組,具有相同分組名稱的規則只能有一個規則觸發
agenda-group議程分組,只有獲取焦點的組中的規則才有可能觸發
timer定時器,指定規則觸發的時間
auto-focus自動獲取焦點,一般結合agenda-group一起使用
no-loop防止死循環

1、enabled屬性

enabled屬性對應的取值為true和false,默認值為true。

用于指定當前規則是否啟用,如果設置的值為false則當前規則無論是否匹配成功都不會觸發。

rule "rule_comparison_notMemberOf"//指定當前規則不可用,當前規則無論是否匹配成功都不會執行enabled falsewhenComparisonOperatorEntity(names not memberOf list)thenSystem.out.println("規則rule_comparison_notMemberOf觸發");
end

2、dialect屬性

dialect屬性用于指定當前規則使用的語言類型,取值為java和mvel,默認值為java。

注:mvel是一種基于java語法的表達式語言。

mvel像正則表達式一樣,有直接支持集合、數組和字符串匹配的操作符。

mvel還提供了用來配置和構造字符串的模板語言。

mvel表達式內容包括屬性表達式,布爾表達式,方法調用,變量賦值,函數定義等。

3、salience屬性

salience屬性用于指定規則的執行優先級,取值類型為Integer。數值越大越優先執行。每個規則都有一個默認的執行順序,如果不設置salience屬性,規則體的執行順序為由上到下。

可以通過創建規則文件salience.drl來測試salience屬性,內容如下:

//當前規則文件用于測試執行優先級
package testsalience//定義第一個規則
rule "rule_1"salience 10//指定規則執行的優先級,數值越大越優先wheneval(true)//返回true,即當前規則匹配成功thenSystem.out.println("規則:rule_1觸發了...");
end//定義第二個規則
rule "rule_2"salience 11wheneval(true)//返回true,即當前規則匹配成功thenSystem.out.println("規則:rule_2觸發了...");
end//定義第三個規則
rule "rule_3"salience 5wheneval(true)//返回true,即當前規則匹配成功thenSystem.out.println("規則:rule_3觸發了...");
end

通過控制臺可以看到,規則文件執行的順序是按照我們設置的salience值由大到小順序執行的。

建議在編寫規則時使用salience屬性明確指定執行優先級。

4、no-loop屬性

no-loop屬性用于防止死循環,當規則通過update之類的函數修改了Fact對象時,可能使當前規則再次被激活從而導致死循環。取值類型為Boolean,默認值為false。測試步驟如下:

第一步:編寫規則文件/resource/rules/noloop.drl

//當前規則文件用于測試noloop防止規則執行時死循環問題
package testnoloop
import com.drools.Studentrule "rule_noloop"no-loop true//使用no-loop解決死循環問題when$s:Student(age == 50)thenupdate($s);//調用update方法會導致相關規則重新匹配System.out.println("規則:rule_noloop觸發了...");
end

通過控制臺可以看到,我們沒有設置no-loop屬性的值,所以發生了死循環。設置no-loop的值為true再次測試則不會發生死循環。

5、activation-group屬性

activation-group屬性是指激活分組,取值為String類型。具有相同分組名稱的規則只能有一個規則被觸發

第一步:編寫規則文件/resources/rules/activationgroup.drl

//當前規則文件用于測試activation-group屬性
package testactivationgrouprule "rule_activationgroup_1"activation-group "mygroup"//對于同一個組內的規則,只能有一個觸發salience 5when//如果條件不寫,默認為true,表示規則匹配成功thenSystem.out.println("規則:rule_activationgroup_1觸發了...");
endrule "rule_activationgroup_2"activation-group "mygroup"salience 10when//如果條件不寫,默認為true,表示規則匹配成功thenSystem.out.println("規則:rule_activationgroup_2觸發了...");
end

通過控制臺可以發現,上面的兩個規則因為屬于同一個分組,所以只有一個觸發了。同一個分組中的多個規則如果都能夠匹配成功,具體哪一個最終能夠被觸發可以通過salience屬性確定。

6、agenda-group屬性

agenda-group屬性為議程分組,屬于另一種可控的規則執行方式。用戶可以通過設置agenda-group來控制規則的執行,只有獲取焦點的組中的規則才會被觸發。

第一步:創建規則文件/resources/rules/agendagroup.drl

package testagendagroup
/*此規則文件用于測試agenda-group屬性
*/
rule "rule_agendagroup_1"agenda-group "myagendagroup_1"whenthenSystem.out.println("規則rule_agendagroup_1觸發");
end
?
rule "rule_agendagroup_2"agenda-group "myagendagroup_1"whenthenSystem.out.println("規則rule_agendagroup_2觸發");
end
//========================================================
rule "rule_agendagroup_3"agenda-group "myagendagroup_2"whenthenSystem.out.println("規則rule_agendagroup_3觸發");
end
?
rule "rule_agendagroup_4"agenda-group "myagendagroup_2"whenthenSystem.out.println("規則rule_agendagroup_4觸發");
end

第二步:編寫單元測試

KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
?
//設置焦點,對應agenda-group分組中的規則才可能被觸發
kieSession.getAgenda().getAgendaGroup("myagendagroup_1").setFocus();
?
kieSession.fireAllRules();
kieSession.dispose();

通過控制臺可以看到,只有獲取焦點的分組中的規則才會觸發。與activation-group不同的是,activation-group定義的分組中只能夠有一個規則可以被觸發,而agenda-group分組中的多個規則都可以被觸發。

7、auto-focus屬性

auto-focus屬性為自動獲取焦點,取值類型為Boolean,默認值為false。一般結合agenda-group屬性使用,當一個議程分組未獲取焦點時,可以設置auto-focus屬性來控制。

第一步:修改/resources/rules/agendagroup.drl文件內容如下

package testagendagroup
?
rule "rule_agendagroup_1"agenda-group "myagendagroup_1"whenthenSystem.out.println("規則rule_agendagroup_1觸發");
end
?
rule "rule_agendagroup_2"agenda-group "myagendagroup_1"whenthenSystem.out.println("規則rule_agendagroup_2觸發");
end
//========================================================
rule "rule_agendagroup_3"agenda-group "myagendagroup_2"auto-focus true //自動獲取焦點whenthenSystem.out.println("規則rule_agendagroup_3觸發");
end
?
rule "rule_agendagroup_4"agenda-group "myagendagroup_2"auto-focus true //自動獲取焦點whenthenSystem.out.println("規則rule_agendagroup_4觸發");
end

第二步:編寫單元測試

KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
kieSession.fireAllRules();
kieSession.dispose();

通過控制臺可以看到,設置auto-focus屬性為true的規則都觸發了。

8、timer屬性

timer屬性可以通過定時器的方式指定規則執行的時間,使用方式有兩種:

方式一:timer (int: <initial delay> <repeat interval>?)

此種方式遵循java.util.Timer對象的使用方式,第一個參數表示幾秒后執行,第二個參數表示每隔幾秒執行一次,第二個參數為可選。

方式二:timer(cron: <cron expression>)

此種方式使用標準的unix cron表達式的使用方式來定義規則執行的時間。

第一步:創建規則文件/resources/rules/timer.drl

package testtimer
import java.text.SimpleDateFormat
import java.util.Date
/*此規則文件用于測試timer屬性
*/
?
rule "rule_timer_1"timer (5s 2s) //含義:5秒后觸發,然后每隔2秒觸發一次whenthenSystem.out.println("規則rule_timer_1觸發,觸發時間為:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
end
?
rule "rule_timer_2"timer (cron:0/1 * * * * ?) //含義:每隔1秒觸發一次whenthenSystem.out.println("規則rule_timer_2觸發,觸發時間為:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
end

第二步:編寫單元測試

KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
final KieSession kieSession = kieClasspathContainer.newKieSession();
?
new Thread(new Runnable() {public void run() {//啟動規則引擎進行規則匹配,直到調用halt方法才結束規則引擎kieSession.fireUntilHalt();}
}).start();
?
Thread.sleep(10000);
//結束規則引擎
kieSession.halt();
kieSession.dispose();

注意:單元測試的代碼和以前的有所不同,因為我們規則文件中使用到了timer進行定時執行,需要程序能夠持續一段時間才能夠看到定時器觸發的效果。

9、date-effective屬性

date-effective屬性用于指定規則的生效時間,即只有當前系統時間大于等于設置的時間或者日期規則才有可能觸發。默認日期格式為:dd-MMM-yyyy。用戶也可以自定義日期格式。

第一步:編寫規則文件/resources/rules/dateeffective.drl

package testdateeffective
/*此規則文件用于測試date-effective屬性
*/
rule "rule_dateeffective_1"date-effective "2023-11-22 10:00"//date-effective屬性用于指定當前規則生效時間whenthenSystem.out.println("規則rule_dateeffective_1觸發");
end

第二步:編寫單元測試

//設置日期格式
System.setProperty("drools.dateformat","yyyy-MM-dd HH:mm");
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
kieSession.fireAllRules();
kieSession.dispose();

注意:上面的代碼需要設置日期格式,否則我們在規則文件中寫的日期格式和默認的日期格式不匹配程序會報錯。

10、date-expires屬性

date-expires屬性用于指定規則的失效時間,即只有當前系統時間小于設置的時間或者日期規則才有可能觸發。默認日期格式為:dd-MMM-yyyy。用戶也可以自定義日期格式。

第一步:編寫規則文件/resource/rules/dateexpires.drl

package testdateexpires
/*此規則文件用于測試date-expires屬性
*/
?
rule "rule_dateexpires_1"date-expires "2023-11-22 10:00" //date-expires屬性用于指定當前規則的失效時間whenthenSystem.out.println("規則rule_dateexpires_1觸發");
end

第二步:編寫單元測試

//設置日期格式
System.setProperty("drools.dateformat","yyyy-MM-dd HH:mm");
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
kieSession.fireAllRules();
kieSession.dispose();

注意:上面的代碼需要設置日期格式,否則我們在規則文件中寫的日期格式和默認的日期格式不匹配程序會報錯。

六、Drools高級語法

1、global全局變量

global關鍵字用于在規則文件中定義全局變量,它可以讓應用程序的對象在規則文件中能夠被訪問。可以用來為規則文件提供數據或服務。

語法結構為:global 對象類型 對象名稱

在使用global定義的全局變量時有兩點需要注意:

1、如果對象類型為包裝類型時,在一個規則中改變了global的值,那么只針對當前規則有效,對其他規則中的global不會有影響。可以理解為它是當前規則代碼中的global副本,規則內部修改不會影響全局的使用。

2、如果對象類型為集合類型或JavaBean時,在一個規則中改變了global的值,對java代碼和所有規則都有效。

下面我們通過代碼進行驗證:

第一步:創建UserService類

public class UserService {public void save(){System.out.println("UserService.save()...");}
}

第二步:編寫規則文件/resources/rules/global.drl

package testglobal
/*此規則文件用于測試global全局變量
*/
?
global java.lang.Integer count //定義一個包裝類型的全局變量
global com.drools.UserService userService //定義一個JavaBean類型的全局變量
global java.util.List gList //定義一個集合類型的全局變量
?
rule "rule_global_1"whenthencount += 10; //全局變量計算,只對當前規則有效,其他規則不受影響userService.save();//調用全局變量的方法gList.add("itcast");//向集合類型的全局變量中添加元素,Java代碼和所有規則都受影響gList.add("itglobal");System.out.println("count=" + count);System.out.println("gList.size=" + gList.size());
end
?
rule "rule_global_2"whenthenuserService.save();System.out.println("count=" + count);System.out.println("gList.size=" + gList.size());
end

第三步:編寫單元測試

KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
?
//設置全局變量,名稱和類型必須和規則文件中定義的全局變量名稱對應
kieSession.setGlobal("userService",new UserService());
kieSession.setGlobal("count",5);
List list = new ArrayList();//size為0
kieSession.setGlobal("gList",list);
?
kieSession.fireAllRules();
kieSession.dispose();
?
//因為在規則中為全局變量添加了兩個元素,所以現在的size為2
System.out.println(list.size());

結果:
UserService.save()…
count=15
gList.size=2
UserService.save()…
count=5
gList.size=2
2

2、query查詢

query查詢提供了一種查詢working memory中符合約束條件的Fact對象的簡單方法。它僅包含規則文件中的LHS部分,不用指定“when”和“then”部分并且以end結束。具體語法結構如下:

query 查詢的名稱(可選參數)LHS
end

具體操作步驟:

第一步:編寫規則文件/resources/rules/query.drl

package testquery
import com.drools.Student
/*此規則文件用于測試query查詢
*/
?
//不帶參數的查詢
//當前query用于查詢Working Memory中age>10的Student對象
query "query_1"$student:Student(age > 10)
end
?
//帶有參數的查詢
//當前query用于查詢Working Memory中age>10同時name需要和傳遞的參數name相同的Student對象
query "query_2"(String sname)$student:Student(age > 20 && name == sname)
end

第二步:編寫單元測試

KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
?
Student student1 = new Student();
student1.setName("張三");
student1.setAge(12);
?
Student student2 = new Student();
student2.setName("李四");
student2.setAge(8);
?
Student student3 = new Student();
student3.setName("王五");
student3.setAge(22);
?
//將對象插入Working Memory中
kieSession.insert(student1);
kieSession.insert(student2);
kieSession.insert(student3);
?
//調用規則文件中的查詢
QueryResults results1 = kieSession.getQueryResults("query_1");
int size = results1.size();
System.out.println("size=" + size);
for (QueryResultsRow row : results1) {Student student = (Student) row.get("$student");System.out.println(student);
}
?
//調用規則文件中的查詢
QueryResults results2 = kieSession.getQueryResults("query_2","王五");
size = results2.size();
System.out.println("size=" + size);
for (QueryResultsRow row : results2) {Student student = (Student) row.get("$student");System.out.println(student);
}
//kieSession.fireAllRules();
kieSession.dispose();

結果:
size=2
com.drools.Student@74cec793
com.drools.Student@ec0c838
size=1
com.drools.Student@ec0c838

3、function函數

function關鍵字用于在規則文件中定義函數,就相當于java類中的方法一樣。可以在規則體中調用定義的函數。使用函數的好處是可以將業務邏輯集中放置在一個地方,根據需要可以對函數進行修改。

函數定義的語法結構如下:

function 返回值類型 函數名(可選參數){//邏輯代碼
}

具體操作步驟:

第一步:編寫規則文件/resources/rules/function.drl

package testfunction
import com.itheima.drools.entity.Student
/*此規則文件用于測試function函數
*/
?
//定義一個函數
function String sayHello(String name){return "hello " + name;
}
?
rule "rule_function_1"when$student:Student(name != null)then//調用上面定義的函數String ret = sayHello($student.getName());System.out.println(ret);
end

第二步:編寫單元測試

KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
?
Student student = new Student();
student.setName("小明");
?
kieSession.insert(student);
?
kieSession.fireAllRules();
kieSession.dispose();

4、LHS加強

(1)復合值限制in/not in

復合值限制是指超過一種匹配值的限制條件,類似于SQL語句中的in關鍵字。Drools規則體中的LHS部分可以使用in或者not in進行復合值的匹配。具體語法結構如下:

Object(field in (比較值1,比較值2...))

舉例:

$s:Student(name in ("張三","李四","王五"))
$s:Student(name not in ("張三","李四","王五"))

(2)條件元素eval

eval用于規則體的LHS部分,并返回一個Boolean類型的值。語法結構如下:

eval(表達式)

舉例:

eval(true)
eval(false)
eval(1 == 1)

(3)條件元素not

not用于判斷Working Memory中是否存在某個Fact對象,如果不存在則返回true,如果存在則返回false。語法結構如下:

not Object(可選屬性約束)

舉例:

not Student()
not Student(age < 10)

(4)條件元素exists

exists的作用與not相反,用于判斷Working Memory中是否存在某個Fact對象,如果存在則返回true,不存在則返回false。語法結構如下:

exists Object(可選屬性約束)

舉例:

exists Student()
exists Student(age < 10 && name != null)

可能有人會有疑問,我們前面在LHS部分進行條件編寫時并沒有使用exists也可以達到判斷Working Memory中是否存在某個符合條件的Fact元素的目的,那么我們使用exists還有什么意義?

兩者的區別:當向Working Memory中加入多個滿足條件的Fact對象時,使用了exists的規則執行一次,不使用exists的規則會執行多次。

例如:

規則文件(只有規則體):

rule "使用exists的規則"whenexists Student()thenSystem.out.println("規則:使用exists的規則觸發");
end
?
rule "沒有使用exists的規則"whenStudent()thenSystem.out.println("規則:沒有使用exists的規則觸發");
end

Java代碼:

kieSession.insert(new Student());
kieSession.insert(new Student());
kieSession.fireAllRules();

上面第一個規則只會執行一次,因為Working Memory中存在兩個滿足條件的Fact對象,第二個規則會執行兩次。

(5)規則繼承

規則之間可以使用extends關鍵字進行規則條件部分的繼承,類似于java類之間的繼承。

例如:

rule "rule_1"whenStudent(age > 10)thenSystem.out.println("規則:rule_1觸發");
end
?
rule "rule_2" extends "rule_1" //繼承上面的規則when/*此處的條件雖然只寫了一個,但是從上面的規則繼承了一個條件,所以當前規則存在兩個條件,即Student(age < 20)和Student(age > 10)*/Student(age < 20) thenSystem.out.println("規則:rule_2觸發");
end

5、RHS加強

RHS部分是規則體的重要組成部分,當LHS部分的條件匹配成功后,對應的RHS部分就會觸發執行。一般在RHS部分中需要進行業務處理。

在RHS部分Drools為我們提供了一個內置對象,名稱就是drools

(1)halt 終止后續規則

halt方法的作用是立即終止后面所有規則的執行。

package testhalt
rule "rule_halt_1"whenthenSystem.out.println("規則:rule_halt_1觸發");drools.halt();//立即終止后面所有規則執行
end
?
//當前規則并不會觸發,因為上面的規則調用了halt方法導致后面所有規則都不會執行
rule "rule_halt_2"whenthenSystem.out.println("規則:rule_halt_2觸發");
end

(2)getWorkingMemory

getWorkingMemory方法的作用是返回工作內存對象。

package testgetWorkingMemory
rule "rule_getWorkingMemory"whenthenSystem.out.println(drools.getWorkingMemory());
end

(3)getRule

getRule方法的作用是返回規則對象。

package testgetRule
rule "rule_getRule"whenthenSystem.out.println(drools.getRule());
end

6、規則文件編碼規范

我們在進行drl類型的規則文件編寫時盡量遵循如下規范:

  • 所有的規則文件(.drl)應統一放在一個規定的文件夾中,如:/rules文件夾
  • 書寫的每個規則應盡量加上注釋。注釋要清晰明了,言簡意賅
  • 同一類型的對象盡量放在一個規則文件中,如所有Student類型的對象盡量放在一個規則文件中
  • 規則結果部分(RHS)盡量不要有條件語句,如if(…),盡量不要有復雜的邏輯和深層次的嵌套語句
  • 每個規則最好都加上salience屬性,明確執行順序
  • Drools默認dialect為"Java",盡量避免使用dialect “mvel”

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/161952.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/161952.shtml
英文地址,請注明出處:http://en.pswp.cn/news/161952.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

20231122給RK3399的挖掘機開發板適配Android12

20231122給RK3399的挖掘機開發板適配Android12 2023/11/22 9:30 主要步驟&#xff1a; rootrootrootroot-X99-Turbo:~$ tar --use-compress-programpigz -xvpf rk356x_android12_220722.tgz rootrootrootroot-X99-Turbo:~$ cd rk_android12_220722/ rootrootrootroot-X99-Tur…

rk3568 適配以太網(mac 2 mac)

rk3568 適配以太網(mac 2 mac) MDI(Media Dependent Interface)是以太網中的一種接口標準,用于連接物理層(PHY)和數據鏈路層(MAC)之間的傳輸介質。 在以太網中,MDI通常通過RJ-45插座來實現,用于連接網線和網絡設備。MDI接口提供了電氣和機械特性,使得PHY和MAC能夠正…

Python通過串口收發文件

單位內外網是隔離的,USB對拷線被禁用,安全優盤使用太費事,就想到了通過串口傳輸文件. import serial from xmodem import XMODEM import osdef Send_File(filepath, portCOM8, baudrate115200):bn os.path.basename(filepath)filesize os.stat(filepath).st_sizestrSendFile…

帶記憶的超級GPT智能體,能做飯、煮咖啡、整理家務!

隨著AI技術的快速迭代&#xff0c;Alexa、Siri、小度、天貓精靈等語音助手得到了廣泛應用。但在自然語言理解和完成復雜任務方面仍然有限。 相比文本的標準格式&#xff0c;語音充滿復雜性和多樣性&#xff08;例如&#xff0c;地方話&#xff09;,傳統方法很難適應不同用戶的…

【每日OJ —— 20.有效的括號(棧)】

每日OJ —— 20.有效的括號&#xff08;棧&#xff09; 1.題目&#xff1a;20.有效的括號&#xff08;棧&#xff09;2.方法講解2.1.解法2.1.1.算法講解2.1.2.代碼實現2.1.3.提交通過展示 1.題目&#xff1a;20.有效的括號&#xff08;棧&#xff09; 2.方法講解 2.1.解法 利用…

2023 年 亞太賽 APMCM (B題)國際大學生數學建模挑戰賽 |數學建模完整代碼+建模過程全解全析

當大家面臨著復雜的數學建模問題時&#xff0c;你是否曾經感到茫然無措&#xff1f;作為2022年美國大學生數學建模比賽的O獎得主&#xff0c;我為大家提供了一套優秀的解題思路&#xff0c;讓你輕松應對各種難題。 問題一&#xff1a; 建立沒有作物的玻璃溫室內的溫度和風速分…

C語言二十四彈--喝汽水問題

C語言解決喝汽水問題 題目&#xff1a;喝汽水&#xff0c;1瓶汽水1元&#xff0c;2個空瓶可以換一瓶汽水&#xff0c;給20元&#xff0c;可以喝多少汽水&#xff1f; 方法一、逐瓶購買法 思路&#xff1a;一瓶瓶的買 當空瓶有兩個時&#xff0c;汽水數加1即可。 #include &…

MacOS 成為惡意軟件活動的目標

Malwarebytes 警告稱&#xff0c;一個針對 Mac 操作系統 (OS) 的數據竊取程序正在通過虛假的網絡瀏覽器更新分發給毫無戒心的目標。 Atomic Stealer&#xff0c;也稱為 AMOS&#xff0c;是 Mac OS 上流行的竊取程序。 Atomic Stealer (AMOS) 惡意軟件最近被發現使用“ClearFa…

ImportError: cannot import name ‘contextfilter‘ from ‘jinja2‘解決方案

大家好,我是愛編程的喵喵。雙985碩士畢業,現擔任全棧工程師一職,熱衷于將數據思維應用到工作與生活中。從事機器學習以及相關的前后端開發工作。曾在阿里云、科大訊飛、CCF等比賽獲得多次Top名次。現為CSDN博客專家、人工智能領域優質創作者。喜歡通過博客創作的方式對所學的…

匯編-pop出棧指令

32位匯編 執行動作分為兩步&#xff1a; 第一步&#xff1a;讀出數據 第二步&#xff1a;改變棧地址 如果操作數是16位&#xff0c; 則ESP加2&#xff1b; 如果操作數是32位&#xff0c; 則ESP加4 espesp2 或 espesp4 格式&#xff1a;

九、sdl顯示bmp圖片

前言 SDL中內置加載BMP的API&#xff0c;使用起來會更加簡單&#xff0c;便于初學者學習使用SDL 如果需要加載JPG、PNG等其他格式的圖片&#xff0c;可以使用第三方庫&#xff1a;SDL_image 測試環境&#xff1a; ffmpeg的4.3.2自行編譯版本windows環境qt5.12sdl2.0.22&…

力扣第462題 最小操作次數使數組元素相等 II C++ 排序基礎 附Java代碼

題目 462. 最小操作次數使數組元素相等 II 中等 相關標簽 數組 數學 排序 給你一個長度為 n 的整數數組 nums &#xff0c;返回使所有數組元素相等需要的最小操作數。 在一次操作中&#xff0c;你可以使數組中的一個元素加 1 或者減 1 。 示例 1&#xff1a; 輸入&a…

Python深入分享之閉包

閉包(closure)是函數式編程的重要的語法結構。函數式編程是一種編程范式 (而面向過程編程和面向對象編程也都是編程范式)。在面向過程編程中&#xff0c;我們見到過函數(function)&#xff1b;在面向對象編程中&#xff0c;我們見過對象(object)。函數和對象的根本目的是以某種…

substr()與substring()的區別

在 JavaScript 編程語言中&#xff0c;substr() 和 substring() 都是字符串函數&#xff0c;用于截取指定位置的子字符串。雖然這兩個函數都可以用于截取字符串&#xff0c;但它們之間存在一些區別。 substr() 語法&#xff1a;string.substr(start,length) 參數值&#xff1a…

IDEA中 java: 警告: 源發行版 11 需要目標發行版 11 如何解決

步驟1找到項目結構&#xff0c;下面有兩種方式 步驟2找到 模塊中對應的項目&#xff0c;修改對應的源的語言級別和依賴的模塊SDK(M) 步驟3&#xff0c;啟動一下&#xff0c;看有無問題&#xff0c; 步驟4&#xff0c;去文件-->設置-->構建、執行、部署-->編譯器-->…

中職組網絡安全B模塊-滲透提權2

任務五&#xff1a;滲透提權2 任務環境說明&#xff1a; 僅能獲取xxx的IP地址 用戶名&#xff1a;test&#xff0c;密碼&#xff1a;123456 訪問服務器主機&#xff0c;找到主機中管理員名稱&#xff0c;將管理員名稱作為Flag值提交&#xff1b; Flag:doyoudoyoudo 訪問服…

C語言二十三彈---求第N項斐波那契數列的值

C語言求第N項斐波那契數列的值 定義&#xff1a;斐波那契數列指的是這樣一個數列&#xff1a;1&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;5&#xff0c;8&#xff0c;13&#xff0c;21&#xff0c;34&#xff0c;55&#xff0c;89…自然中的斐波那契數列&#xff0…

感恩三十載 再創新輝煌——中國音樂著作權協會成立30周年暨著作權集體管理制度實施30周年紀念大會在京召開

感恩三十載 再創新輝煌 2023年11月19日&#xff0c;中國音樂著作權協會成立30周年暨著作權集體管理制度實施30周年紀念大會在北京舉行。中宣部副部長張建春&#xff0c;國際作者和作曲者協會聯合會&#xff08;CISAC&#xff09;總干事甘迪奧龍&#xff08;Gadi Oron&#xff0…

深入了解批處理文件:從基礎到實例

1. 什么是批處理文件&#xff1f; 批處理文件是一種包含一系列命令的文本文件&#xff0c;通常用于自動化執行一系列任務。在不同操作系統中&#xff0c;批處理也有不同的名稱&#xff0c;如在Windows中被稱為批處理文件&#xff08;.bat&#xff09;&#xff0c;而在Linux中則…

【MISRA C 2012】Rule 5.1 外部標識符應該是不同的

1. 規則1.1 原文1.2 分類 2. 關鍵描述3. 代碼實例 1. 規則 1.1 原文 Rule 5.1 External identifiers shall be distinct Category Required Analysis Decidable, System Applies to C90, C99 1.2 分類 規則5.1&#xff1a;外部標識符應該是不同的 Required必須類規范。 2.…