Gradle 入門之 Groovy 語言詳解
Gradle 核心是基於 Groovy 指令碼語言,Groovy 指令碼基於 Java 且拓展了 Java。因此 Gradle 需要依賴 JDK 和 Groovy 庫。
快速安裝 Groovy 可以通過 Bash,命令如下:
$ curl -s get.sdkman.io | bash
$ source "$HOME/.sdkman/bin/sdkman-init.sh"
$ sdk install groovy
// 檢視版本,判斷是否成功
$ groovy -version
關鍵字:
as、assert、break、case、catch、class、const、continue、def、default、do、else、enum、extends、false、finally、for、goto、if、implements、import、in、instanceof、interface、new、null、package、return、super、switch、this、throw、throws、trait、true、try、while
Hello Groovy
#!/usr/bin/env groovy
println "Hello Groovy."
一、型別定義
1,識別符號
- 普通識別符號:只能以字母、美元符、下劃線開始,不能以數字開頭。
引用識別符號:引用識別符號出現在點後的表示式中。
// 定義一個空的 map 集合 def map = [:] // 引用標示符中可以出現空格、橫杆等 map."a b-c" = "ALLOWED" // 斷言,map 中識別符號的值與右邊的字串相等 assert map."a b-c" == "ALLOWED"
注:Groovy 中所有的字串都可以當引用識別符號。
2,字串
Groovy 有 java.lang.String
和 groovy.lang.GString
兩中字串物件型別。
單引號字串
是
java.lang.String
型別,不支援站位符插值操作。雙引號字串
是
groovy.lang.GString
型別,支援站位符插值操作。其中插值佔位符我們可以用${}
或者$
來標示,${}
用於一般替代字串或者表示式,$
主要用於A.B的形式中。三重單引號字串
是
java.lang.String
型別,不支援站位符插值操作,可以標示多行字串。多重雙引號字串
支援站位插值操作,可以標示多行字串。
斜線字串
和雙引號字串很類似,通常用在正則表示式中。
def name = 'Test Groovy!' def body = 'Test $name' // 單引號字串中,佔位符不會被替換 assert body == 'Test $name' // 雙引號字串,*${}* 標識,括號內面的表示式會被計算,變數會被替換 def sum = "The sum of 2 and 3 equals ${2 + 3}" assert sum.toString() == 'The sum of 2 and 3 equals 5' // 雙引號字串,*$* 標識,只對 A.B 有效,對括號、閉包等無效,會丟擲 groovy.lang.MissingPropertyException 異常 def person = [name: 'Guillaume', age: 36] assert "$person.name is $person.age years old" == 'Guillaume is 36 years old' // 三重單引號字串,不支援站位符插值操作 def aMultilineString = '''line one line two line three''' // 多重雙引號字串,支援站位符插值操作 def name = 'Groovy' def template = """ Hello, ${name} Welcome. """ // 斜線字串 def fooPattern = /.*foo.*/ assert fooPattern == '.*foo.*' // 多行支援 def multilineSlashy = /one two three/ // 含站位符使用支援 def color = 'blue' def interpolatedSlashy = /a ${color} car/
3,字元 Characters
Groovy沒有明確的Characters。但是我們可以有如下三種不同的方式來將字串作為字元處理,譬如:
char c1 = 'A'
assert c1 instanceof Character
def c2 = 'B' as char
assert c2 instanceof Character
def c3 = (char)'C'
assert c3 instanceof Character
4,數字 Numbers
整型
和 Java 一樣,支援 byte、char、short、int、long、java.lang.BigInteger
浮點型
和 Java 一樣,支援 float、double、java.lang.BigDecimal
// 整型,‘0’開頭,八進位制表示 int xInt = 077 // 整型,‘0x’開頭,十六進位制表示 int xInt = 0x77 // 整型,‘0b’開頭,二進位制表示 int xInt = 0b10101111 // 浮點型,科學計數表示法 assert 1e3 == 1_000.0 assert 2E4 == 20_000.0 assert 3e+1 == 30.0 assert 4E-2 == 0.04
5,Booleans 型別
def myBooleanVariable = true
boolean untypedBooleanVar = false
booleanField = true
6,Lists 集合
支援 java.util.List, 可以增刪改物件,列表中型別不受限制,可以用超出列表範圍的數來索引列表。
//使用動態List
def numbers = [1, 2, 3]
assert numbers instanceof List
assert numbers.size() == 3
//List中儲存任意型別
def heterogeneous = [1, "a", true]
//判斷List預設型別
def arrayList = [1, 2, 3]
assert arrayList instanceof java.util.ArrayList
//使用as強轉型別
def linkedList = [2, 3, 4] as LinkedList
assert linkedList instanceof java.util.LinkedList
//定義指定型別List
LinkedList otherLinked = [3, 4, 5]
assert otherLinked instanceof java.util.LinkedList
//定義List使用
def letters = ['a', 'b', 'c', 'd']
//判斷item值
assert letters[0] == 'a'
assert letters[1] == 'b'
//負數下標則從右向左index
assert letters[-1] == 'd'
assert letters[-2] == 'c'
//指定item賦值判斷
letters[2] = 'C'
assert letters[2] == 'C'
//給List追加item
letters << 'e'
assert letters[ 4] == 'e'
assert letters[-1] == 'e'
//獲取一段List子集
assert letters[1, 3] == ['b', 'd']
assert letters[2..4] == ['C', 'd', 'e']
//多維List支援
def multi = [[0, 1], [2, 3]]
assert multi[1][0] == 2
7,Arrays 陣列
和 Java 陣列類似。
//定義初始化String陣列
String[] arrStr = ['Ananas', 'Banana', 'Kiwi']
assert arrStr instanceof String[]
assert !(arrStr instanceof List)
//使用def定義初始化int陣列
def numArr = [1, 2, 3] as int[]
assert numArr instanceof int[]
assert numArr.size() == 3
//宣告定義多維陣列指明寬度
def matrix3 = new Integer[3][3]
assert matrix3.size() == 3
//宣告多維陣列不指定寬度
Integer[][] matrix2
matrix2 = [[1, 2], [3, 4]]
assert matrix2 instanceof Integer[][]
//陣列的元素使用及賦值操作
String[] names = ['Cédric', 'Guillaume', 'Jochen', 'Paul']
assert names[0] == 'Cédric'
names[2] = 'Blackdrag'
assert names[2] == 'Blackdrag'
8,Maps 鍵值對
在Groovy中鍵key不一定是String,可以是任何物件(實際上 Groovy 中的 Map 就是java.util.LinkedHashMap
)。
//定義一個Map
def colors = [red: '#FF0000', green: '#00FF00', blue: '#0000FF']
//獲取一些指定key的value進行判斷操作
assert colors['red'] == '#FF0000'
assert colors.green == '#00FF00'
//給指定key的對賦值value操作與判斷
colors['pink'] = '#FF00FF'
colors.yellow = '#FFFF00'
assert colors.pink == '#FF00FF'
assert colors['yellow'] == '#FFFF00'
//判斷Map的型別
assert colors instanceof java.util.LinkedHashMap
//訪問Map中不存在的key為null
assert colors.unknown == null
//定義key型別為數字的Map
def numbers = [1: 'one', 2: 'two']
assert numbers[1] == 'one'
對於Map需要特別注意一種情況,如下:
//把一個定義的變數作為Map的key,訪問Map的該key是失敗的
def key = 'name'
def person = [key: 'Guillaume']
assert !person.containsKey('name')
assert person.containsKey('key')
//把一個定義的變數作為Map的key的正確寫法---新增括弧,訪問Map的該key是成功的
person = [(key): 'Guillaume']
assert person.containsKey('name')
assert !person.containsKey('key')
二、運算子
下面介紹與 Java 不同的運算子,其它請參照 Java。
1,次方運算子(**)
assert 2 ** 3 == 8
def f = 3
f **= 2
assert f == 9
2,非運算子(!)
assert (!true) == false
// 支援字串的判斷,為空時返回 false,不為空時返回 true
assert (!'foo') == false
assert (!'') == true
3,安全佔位符(?.)
這個運算子主要用於避免空指標異常。
def person = Person.find { it.id == 123 }
def name = person?.name
assert name == null
4,直接域訪問操作符([email protected])
因為Groovy自動支援屬性getter方法,但有時候我們有一個自己寫的特殊getter方法,當不想呼叫這個特殊的getter方法則可以用直接域訪問操作符。
class User {
public final String name
User(String name) { this.name = name}
String getName() { "Name: $name" }
}
def user = new User('Bob')
assert user.name == 'Name: Bob'
assert user.@name == 'Bob'
5,方法指標操作符(.&)
因為閉包可以被作為一個方法的引數,如果想讓一個方法作為另一個方法的引數則可以將一個方法當成一個閉包作為另一個方法的引數。
def list = ['a','b','c']
//常規寫法
list.each{
println it
}
String printName(name){
println name
}
// 方法指標操作符寫法,將迭代出的每一個值作為方法的引數
list.each(this.&printName)
6,三目運算子(?:)
displayName = user.name ? user.name : 'Anonymous'
// 簡化為二目運算子,邏輯同上一樣
displayName = user.name ?: 'Anonymous'
7,展開運算子(*.)
一個集合使用展開運算子可以得到一個元素為原集合各個元素執行後面指定方法所得值的集合。
cars = [
new Car(make: 'Peugeot', model: '508'),
null,
new Car(make: 'Renault', model: 'Clio')]
assert cars*.make == ['Peugeot', null, 'Renault']
assert null*.make == null
三、程式結構
1,包名
和 Java 一致。
// defining a package named com.yoursite
package com.yoursite
2,Imports 引入
常規的導包和 Java 一致,有一個特殊。
//例1:
import groovy.xml.MarkupBuilder
// using the imported class to create an object
def xml = new MarkupBuilder()
assert xml != null
//例2:
import groovy.xml.*
def markupBuilder = new MarkupBuilder()
assert markupBuilder != null
assert new StreamingMarkupBuilder() != null
//例3:
import static Boolean.FALSE
assert !FALSE
//例4:特殊的,相當於用as取別名
import static Calendar.getInstance as now
assert now().class == Calendar.getInstance().class
注意:Groovy與Java類似,已經幫我們預設匯入了一些常用的包,所以在我們使用這些包的類時就不用再像上面那樣匯入了,如下是自動匯入的包列表:
import java.lang.*
import java.util.*
import java.io.*
import java.net.*
import groovy.lang.*
import groovy.util.*
import java.math.BigInteger
import java.math.BigDecimal
3,指令碼與類
相對於傳統的Java類,一個包含main方法的Groovy類可以如下書寫:
class Main {
static void main(String... args) {
println 'Groovy world!'
}
}
和Java一樣,程式會從這個類的main方法開始執行,這是Groovy程式碼的一種寫法,實際上執行Groovy程式碼完全可以不需要類或main方法,所以更簡單的寫法如下:
println 'Groovy world!'
上面這兩中寫法其實是一樣的,具體我們可以通過如下命令進行編譯為class檔案:
groovyc demo.groovy //編譯Groovy原始碼為class
我們使用反編譯工具可以檢視到這個demo.groovy類原始碼如下:
import org.codehaus.groovy.runtime.InvokerHelper
class Main extends Script {
def run() {
println 'Groovy world!'
}
static void main(String[] args) {
InvokerHelper.runScript(Main, args)
}
}
可以看見,上面我們寫的groovy檔案編譯後的class其實是Java類,該類從Script類派生而來(查閱API);可以發現,每個指令碼都會生成一個static main方法,我們執行groovy指令碼的實質其實是執行的這個Java類的main方法,指令碼原始碼裡所有程式碼都被放到了run方法中,指令碼中定義的方法(該例暫無)都會被定義在Main類中。
通過上面可以發現,Groovy的實質就是Java的class,也就是說他一定會和Java一樣存在變數作用域!對哦,前面我們解釋變數時竟然沒說到這個東東,這裡說下吧。看下面例子:
//單個Groovy原始碼檔案,執行會報錯找不到num變數
def num = 1
def printNum(){
println num
}
//單個Groovy原始碼檔案,執行會報錯找不到num變數
int num = 1
def printNum(){
println num
}
//單個Groovy原始碼檔案,執行OK成功
num = 1
def printNum(){
println num
}
上面的例子可以發現,我們如果想要在Groovy的方法中使用Groovy的變數則不能有修飾符。然而,如果我們想在B.groovy檔案訪問A.groovy檔案的num變數咋辦呢,我們可以使用Field註解,具體操作如下:
import groovy.transform.Field;
@Field num = 1
哈哈,這就是Groovy的變數作用域了,如果你想知道上面這些寫法為啥出錯,很簡單,自己動手整成Java原始碼相信你一定可以看懂為啥鳥。
四、閉包
1,語法
定義一個閉包:
// [closureparameters -> ]是可選的逗號分隔的引數列表
{ [closureParameters -> ] statements }
引數可以定義,也可以不定義,如果不定義預設有一個 it 的引數。
//使用顯示的名為引數
{ name -> println name }
//接受兩個引數的閉包
{ String x, int y ->
println "hey ${x} the value is ${y}"
}
//包含一個引數多個語句的閉包
{ reader ->
def line = reader.readLine()
line.trim()
}
一個閉包其實就是一個groovy.lang.Closure型別的例項,因此可以如下定義:
//定義一個Closure型別的閉包
def listener = { e -> println "Clicked on $e.source" }
assert listener instanceof Closure
//定義直接指定為Closure型別的閉包
Closure callback = { println 'Done!' }
Closure<Boolean> isTextFile = {
File it -> it.name.endsWith('.txt')
}
呼叫閉包,可以呼叫 call,也可以不
def isOdd = { int i-> i%2 == 1 }
assert isOdd(3) == true
assert isOdd.call(2) == false
2,引數
引數有如下規則:引數型別可選,引數預設值可選,多個引數必須用逗號隔開。
def closureWithOneArg = { str -> str.toUpperCase() }
assert closureWithOneArg('groovy') == 'GROOVY'
def closureWithOneArgAndExplicitType = { String str -> str.toUpperCase() }
assert closureWithOneArgAndExplicitType('groovy') == 'GROOVY'
def closureWithTwoArgs = { a,b -> a+b }
assert closureWithTwoArgs(1,2) == 3
def closureWithTwoArgsAndExplicitTypes = { int a, int b -> a+b }
assert closureWithTwoArgsAndExplicitTypes(1,2) == 3
def closureWithTwoArgsAndOptionalTypes = { a, int b -> a+b }
assert closureWithTwoArgsAndOptionalTypes(1,2) == 3
def closureWithTwoArgAndDefaultValue = { int a, int b=2 -> a+b }
assert closureWithTwoArgAndDefaultValue(1) == 3
當一個閉包沒有顯式定義一個引數列表時,閉包總是有一個隱式的it引數。
def greeting = { "Hello, $it!" }
assert greeting('Patrick') == 'Hello, Patrick!'
當然,如果你想宣告一個不接受任何引數的閉包,且必須限定為沒有引數的呼叫,那麼你必須將它宣告為一個空的引數列表,如下:
def magicNumber = { -> 42 }
// this call will fail because the closure doesn't accept any argument
magicNumber(11)
Groovy的閉包支援最後一個引數為不定長可變長度的引數,具體用法如下:
def concat1 = { String... args -> args.join('') }
assert concat1('abc','def') == 'abcdef'
def concat2 = { String[] args -> args.join('') }
assert concat2('abc', 'def') == 'abcdef'
def multiConcat = { int n, String... args ->
args.join('')*n
}
assert multiConcat(2, 'abc','def') == 'abcdefabcdef'
3,閉包省略呼叫
很多方法的最後一個引數都是一個閉包,我們可以在這樣的方法調運時進行略寫括弧。比如:
def debugClosure(int num, String str, Closure closure){
//dosomething
}
debugClosure(1, "groovy", {
println"hello groovy!"
})
可以看見,當閉包作為閉包或方法的最後一個引數時我們可以將閉包從引數圓括號中提取出來接在最後,如果閉包是唯一的一個引數,則閉包或方法引數所在的圓括號也可以省略;對於有多個閉包引數的,只要是在引數宣告最後的,均可以按上述方式省略。
四、GDK(Groovy Development Kit)
Groovy除了可以直接使用Java的JDK以外還有自己的一套GDK,其實也就是對JDK的一些類的二次封裝罷了;一樣,這是GDK官方API文件,寫程式碼中請自行查閱。
1,I/O 操作
Groovy提供了很多IO操作的方法,你可以使用Java的那寫IO方法,但是沒有Groovy的GDK提供的簡單牛逼。
//讀檔案列印指令碼
new File('/home/temp', 'haiku.txt').eachLine { line ->
println line
}
//讀檔案列印及列印行號指令碼
new File(baseDir, 'haiku.txt').eachLine { line, nb ->
println "Line $nb: $line"
}
可以看見,這是一個讀檔案列印每行的指令碼,eachLine方法是GDK中File的方法,eachLine的引數是一個閉包,這裡採用了簡寫省略括弧。
當然了,有時候你可能更加喜歡用Reader來操作,使用Reader時即使丟擲異常也會自動關閉IO。如下:
def count = 0, MAXSIZE = 3
new File(baseDir,"haiku.txt").withReader { reader ->
while (reader.readLine()) {
if (++count > MAXSIZE) {
throw new RuntimeException('Haiku should only have 3 verses')
}
}
}
接著我們再看幾個關於讀檔案的操作使用,如下:
//把讀到的檔案行內容全部存入List列表中
def list = new File(baseDir, 'haiku.txt').collect {it}
//把讀到的檔案行內容全部存入String陣列列表中
def array = new File(baseDir, 'haiku.txt') as String[]
//把讀到的檔案內容全部轉存為byte陣列
byte[] contents = file.bytes
//把讀到的檔案轉為InputStream,切記此方式需要手動關閉流
def is = new File(baseDir,'haiku.txt').newInputStream()
// do something ...
is.close()
//把讀到的檔案以InputStream閉包操作,此方式不需要手動關閉流
new File(baseDir,'haiku.txt').withInputStream { stream ->
// do something ...
}
上面介紹了一些常用的檔案讀操作,其它的具體參見API和GDK吧。
寫檔案操作:
有了上面的讀操作,接下來直接看幾個寫操作的例子得了,如下:
//向一個檔案以utf-8編碼寫三行文字
new File(baseDir,'haiku.txt').withWriter('utf-8') { writer ->
writer.writeLine 'Into the ancient pond'
writer.writeLine 'A frog jumps'
writer.writeLine 'Water’s sound!'
}
//上面的寫法可以直接替換為此寫法
new File(baseDir,'haiku.txt') << '''Into the ancient pond
A frog jumps
Water’s sound!'''
//直接以byte陣列形式寫入檔案
file.bytes = [66,22,11]
//類似上面讀操作,可以使用OutputStream進行輸出流操作,記得手動關閉
def os = new File(baseDir,'data.bin').newOutputStream()
// do something ...
os.close()
//類似上面讀操作,可以使用OutputStream閉包進行輸出流操作,不用手動關閉
new File(baseDir,'data.bin').withOutputStream { stream ->
// do something ...
}
上面介紹了一些常用的檔案寫操作,其它的具體參見API和GDK吧。
檔案樹操作:
在指令碼環境中,遍歷一個檔案樹是很常見的需求,Groovy提供了多種方法來滿足這個需求。如下:
//遍歷所有指定路徑下檔名列印
dir.eachFile { file ->
println file.name
}
//遍歷所有指定路徑下符合正則匹配的檔名列印
dir.eachFileMatch(~/.*\.txt/) { file ->
println file.name
}
//深度遍歷列印名字
dir.eachFileRecurse { file ->
println file.name
}
//深度遍歷列印名字,只包含檔案型別
dir.eachFileRecurse(FileType.FILES) { file ->
println file.name
}
//允許設定特殊標記規則的遍歷操作
dir.traverse { file ->
if (file.directory && file.name=='bin') {
FileVisitResult.TERMINATE
} else {
println file.name
FileVisitResult.CONTINUE
}
}
執行外部程式:
Groovy提供一種簡單方式來處理執行外部命令列後的輸出流操作。如下:
def process = "ls -l".execute()
println "Found text ${process.text}"
execute方法返回一個java.lang.Process物件,支援in、out、err的資訊反饋。在看一個例子,如下:
def process = "ls -l".execute()
process.in.eachLine { line ->
println line
}
上面使用閉包操作打印出執行命令列的輸入流資訊。
二、有用的工具類操作
ConfigSlurper配置:
ConfigSlurper是一個配置管理檔案讀取工具類,類似於Java的*.properties檔案,如下:
def config = new ConfigSlurper().parse('''
app.date = new Date()
app.age = 42
app {
name = "Test${42}"
}
''')
assert config.app.date instanceof Date
assert config.app.age == 42
assert config.app.name == 'Test42'
上面介紹了一些常用的屬性配置操作,其它的具體參見API和GDK吧。
Expando擴充套件:
def expando = new Expando()
expando.toString = { -> 'John' }
expando.say = { String s -> "John says: ${s}" }
assert expando as String == 'John'
assert expando.say('Hi') == 'John says: Hi'
上面介紹了一些常用的拓展操作,其它的具體參見API和GDK吧。
還有很多其他操作,這裡就不一一列舉,詳情參考官方文件即可,譬如JSON處理、XML解析啥玩意的,自行需求摸索吧。
五,DSL(Domain Specific Languages)領域相關語言
這個就不特殊說明了,只在這裡提一下,因為我們前邊很多地方已經用過它了,加上我們只是乾貨基礎掌握,所以不做深入探討。
DSL是一種特定領域的語言(功能領域、業務領域),Groovy是通用的程式語言,所以不是DSL,但是Groovy卻對編寫全新的DSL提供了很好的支援,這些支援來自於Groovy自身語法的特性,如下:
- Groovy不需用定義CLASS類就可以直接執行指令碼;
- Groovy語法省略括弧和語句結尾分號等操作;
所以說這個基礎入門沒必要特別深入理解,簡單的前面都用過了,理解DSL作用即可,點到為止,詳情參考官方文件。
Gradle 外掛解析:
相關推薦
Gradle 入門之 Groovy 語言詳解
Gradle 核心是基於 Groovy 指令碼語言,Groovy 指令碼基於 Java 且拓展了 Java。因此 Gradle 需要依賴 JDK 和 Groovy 庫。 快速安裝 Groovy 可以通過 Bash,命令如下: $ curl -s get.
大數據hadoop入門之hadoop家族詳解
集成 查詢工具 人員 進一步 容錯 基礎知識 不同的 ima nbsp 大數據hadoop入門之hadoop家族詳解 大數據這個詞也許幾年前你聽著還會覺得陌生,但我相信你現在聽到hadoop這個詞的時候你應該都會覺得“熟悉”!越來越發現身邊從事hadoop開發或者是正在學習
鄰接矩陣有向圖(一)之 C語言詳解
/* * 建立圖(自己輸入) */ Graph* create_graph() { char c1, c2; int v, e; int i, p1, p2; Graph* pG; // 輸入"頂點數"和"邊數" printf("
ROS入門之基礎功能詳解(二)
前言:本部分主要介紹ros一些基礎功能的使用,包括建立和編譯工作空間,建立和編譯功能包,建立和編譯節點,建立和編譯訊息,建立和編譯服務以及建立launch檔案。 一、建立和編譯工作空間 1.檢視正在使用的工作空間: echo $ROS_PACKAGE_PATH -------------
拓撲排序(一)之 C語言詳解
/* * 拓撲排序 * * 引數說明: * G -- 鄰接表表示的有向圖 * 返回值: * -1 -- 失敗(由於記憶體不足等原因導致) * 0 -- 成功排序,並輸入結果 * 1 -- 失敗(該有向圖是有環的) */ int to
Prim演算法(一)之 C語言詳解
/* * prim最小生成樹 * * 引數說明: * G -- 鄰接矩陣圖 * start -- 從圖中的第start個元素開始,生成最小樹 */ void prim(Graph G, int start) { int min,i,j,k,m,n,su
哈夫曼樹(一)之 C語言詳解
/* * 建立Huffman樹 * * 引數說明: * a 權值陣列 * size 陣列大小 * * 返回值: * Huffman樹的根 */ HuffmanNode* create_huffman(Type a[], int size) {
鄰接表無向圖(一)之 C語言詳解
/* * 建立鄰接表對應的圖(自己輸入) */ LGraph* create_lgraph() { char c1, c2; int v, e; int i, p1, p2; ENode *node1, *node2; LGraph* pG;
鄰接矩陣無向圖(一)之 C語言詳解
/* * 建立圖(用已提供的矩陣) */ Graph* create_example_graph() { char vexs[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G'}; char edges[][2] = { {'A'
Dijkstra演算法(一)之 C語言詳解
/* * Dijkstra最短路徑。 * 即,統計圖(G)中"頂點vs"到其它各個頂點的最短路徑。 * * 引數說明: * G -- 圖 * vs -- 起始頂點(start vertex)。即計算"頂點vs"到其它頂點的最短路徑。 * pre
Floyd演算法(一)之 C語言詳解
/* * floyd最短路徑。 * 即,統計圖中各個頂點間的最短路徑。 * * 引數說明: * G -- 圖 * path -- 路徑。path[i][j]=k表示,"頂點i"到"頂點j"的最短路徑會經過頂點k。 * dist -- 長度陣列。即,
鄰接表有向圖(一)之 C語言詳解
/* * 建立鄰接表對應的圖(自己輸入) */ LGraph* create_lgraph() { char c1, c2; int v, e; int i, p1, p2; ENode *node1, *node2; LGraph* pG;
Kruskal演算法(一)之 C語言詳解
/* * 克魯斯卡爾(Kruskal)最小生成樹 */ void kruskal(Graph G) { int i,m,n,p1,p2; int length; int index = 0; // rets陣列的索引 int vends
嵌入式C語言之位操作詳解
1.位操作符: 位操作直接將兩個運算元按照二進位制對應進行操作; 例:0xaa&(位與)0xf0=0xa0; 邏輯操作是 兩個運算元整體來操作; 例
高併發之併發容器詳解(從入門到超神)
一、ConcurrentHashMap 在上面已經提到過ConcurrentHashMap,ConcurrentHashMap相比Hashtable能夠進一步提高併發性,其原理圖如下: HashMap,Hashtable與ConcurrentHashMap都是
Docker入門與實踐之 Dockerfile 語法詳解
二、指令詳解 2.1 From 指令 FROM <image> FROM <image>:<tag> FROM <image>@<digest> FROM指定構建映象的基礎源映象,如果本地沒有指定的映象,則會自動從 D
C語言之#include用法詳解
學習Linux C,必須要理解include,只要弄清以下幾個問題,就能完全理解include了! 1.#include 實質是什麼? 預編譯的時候copy include標頭檔案的內容到當前行 (疑問:預編譯命令 $gcc -E test.c -o test.i) 2.
OpenCV+CUDA入門教程之五---GpuMat詳解
目錄 一、簡介 一、簡介 GpuMat可以從其命名看出,它是“GPU”版本的Mat,絕大部分介面和Mat相同,功能也類似。 和Mat相比,GpuMat多了兩個成員函式upload和download,分別用於把資料從記憶體上傳(通過匯流排傳輸)到
C語言之預處理詳解
C語言之預處理詳解 綱要: 預定義符號 #define #define定義識別符號 #define定義巨集 #define的替換規則 #與## 幾點注意#undef 帶副作用的巨集引數 巨集和函式的對比 命名約定 命令列定義 條件編譯 單分支條件編譯 多分支條件編譯 判斷是否被定義 巢狀指令
linux 之awk命令詳解
數學函數 mat loop 多次 finished 數組結構 save pre 新的 awk是一種程序語言,對文檔資料的處理具有很強的功能。awk名稱是由它三個最初設計者的姓氏的第一個字母而命名的: Alfred V. Aho、Peter J. We i n b e rg