2016年4月11日 星期一

解決 geany 無法使用 gcin 的問題

在 linux mint 上已經裝了 gcin, geany, 但發現在 geany 無法使用 gcin, 他真正的問題是因為快捷鍵 ctrl-space 相衝, 解決的辦法是將它改掉就可以了.

1. 將主選單的  求助(H) -> 快速鍵(K) 叫出來, 往下拉到編輯器,再往下找有個項目 "補完字詞" 所設定的按鍵, 他正好是 Ctrl+Space, 點選 Edit 按鈕

2. 接著會跳出快速鍵變更的選單, 往下拉到編輯器,再往下找有個項目 "補完字詞" 已經反白, 直接點下去再按 變更(H) 按鈕

3. 接著它會跳出視窗訊息, 跟著訊息做, 直接敲下別的組合鍵,讓他不再是 Ctrl-Space 就好. 當然也不要跟別的功能鍵互相衝突, 敲完組合鍵, 他會顯示你所敲的組合鍵,確認後再按 OK 按鈕,變更設定完成

4. 關掉重新打開 geany, 應該就可用 gcin 來切換輸入法了 


swift 學習筆記 3: Dictionary

字典型別是用成對 key:value 元素所組成的集合, 各元素以逗點分開, 使用 [:,:,...] 組成集合, 它其實也沒有順序可言, 但很重要的特性是 key 的值絕對不能有重複, 字典的型別宣告使用Dictionary<TYPE of key:TYPE of value> 來敘述, 簡單的也可用 [TYPE of key:TYPE of value] 來敘述, 例如:
let mydic:[Int:String]=[3:"a",2:"b",1:"CC"]

當然 swift 也可自動推斷出上述的型別, 因此 TYPE 其實也可以省略不寫,下面字典宣告也是符合語法的
var vardic=[2:"a",1:"b",3:"CC"]

字典型別可以透過 key 當索引值, 直接取用 value, 例如
vardic[1]="SDSD"  // 直接更改 key=1 的值, 現在 vardic 將變成是  [2:"a",1:"SDSD",3:"CC"]

如果要清空字典. 可用 [:] 來直接賦予便可, 前提當然該 instance 必須之前就已宣告成變數
var dic=[2:"DD",4:"ww",5:"DDD"] // 宣告字典變數並實體化 instance
dic=[:] // 清空字典內容

透過 key 來取用字典內其所對應的值(value)時, 有可能該 key 並不存在, 因此可運用 optional binding (if let) 來運作較保險


如果要刪除字典內的成員(成對元素), 可以透過將 nil 值賦予字典 key 所對應的成員, 例如
vardic[3]=nil   // 刪除 key=3 的成員


如要列出字典內所有 key, 可以用 for-in 迴圈搭配字典的 .keys 來一一列出, 例如
var vardic=[2:"a",1:"b",3:"CC"]
for i in vardic.keys {
   print("Key:\(i)")
}

如要列出字典內所有 value, 可以用 for-in 迴圈搭配字典的 .values 來一一列出, 例如
var vardic=[2:"a",1:"b",3:"CC"]
for i in vardic.values {
   print("Value:\(i)")
}


字典的屬性及工具:
isEmpty: 驗證是否是空字典
updateValue(,forkey:)
removeValueForKey()



swift 學習筆記 2: Set

集合(Set)型別適合用在秩序並不是很重要的搜集(collection)上, 它最重要的特性是其成員都是唯一, 並不會重複, 如有重複的值, 將會被自動剔除掉只剩一個. Character,  StringIntDouble, and Bool等型態的元素等都可當作集合內的元素(value), 由於 Set 無簡單的宣告形式, 只能用 :Set<TYPE>的方式來宣告集合的類型. 例如字串的集合:
let myset:Set<String> =["a", "bb", "ccc"]

集合不同於 Array, 他並沒有順序, 但可以利用 sort() 來排序. 降羃排序用 sort(>) , 升羃排序(預設由小到大排序)用 sort(<) 因此 sort()等同於 sort(<)例如:
myset.sort(>)

Set 重要的工具(method)及屬性(property):
count : 計錄內部成員個數
isEmpty: 當集合內無成員時,其值為 true
insert() : 插入新成員, 如新成員已存在, 將會忽略此運作
remove(): 移除舊成員, 避免成員不存在可以使用 optional binding ( if let ) 來運作.
contains(): 檢視成員是否存在

集合的算術運算:
intersect(): 兩者交集後產生新集合
union(): 聯集後產生新集合
exclusiveOr(): 聯集並移除兩者的交集後產生新集合
subtract(): 相減後產生新集合

集合的邏輯運算
== : 比較兩個集合是否相同
isSubsetOf(): 判斷是否是括符內集合的子集合
isSupersetOf(): 判斷是否是括符內集合的父集合
isStrictSubsetOf()
isDisjointWith()


var c:Set<Int>=[1,6,5,6,1,6,6,7]    // in fact, c will be {5,6,7,1}
if let c.remove(9) {
      printf("Found and remove it")
} else {
      printf("Member is not exist")
}

c.insert(8) // c will be {5,6,7,1,8 }








2016年4月10日 星期日

swift 學習筆記 1: enum

enum 是用來自訂"列舉型別", 列舉成員屬性用 case 來宣告. 如下所述:

enum Myenum {
case head, body, leg, hand
}

宣告變數隸屬 Mynum 型別, 初始值為 head:
var a: Myenum = Myenum.head

上述型別(:Myenum)其實 swift 可以推論出來, 可以不寫, 同樣合語法.
var a=Myenum.head
// 一旦 type 確認後, 修改值直接用具句號取值就可
a=.body

變數 a 經上述型別設定後, 則只能賦予 Myenum.head Myenum.body, Myenum.leg, Myenum.hand 等四種值. 而將變數 a 列印出來會發現, 它只可能是集合 { head, body, leg, hand } 中的成員之一.

利用協議(protocol) 來定義自體特異功能 (Mutating Method)

protocol Myprotocol {
mutating func toggle()
}

也些時候 instance (實體, 實例, ...?) 的自體內容需要被改變, 它可透過自我 method (方法, 工具, 功能, 運功, 特異功能 ...?) 來改變. 如要強制用此種方式修改就稱作協定, 而型別如果運用(遵循)此協議的必須將它實現, 由於它可能會動用到自體內容, 因此該 method 必須加上 mutating 的前置字眼

底下定義了一個列舉型別 Myswitch{Off, On}, 須遵循 Myprotocol, Myprotocol 裏面只有一個用來切換 (toggle) 的功能需要被實現, 而該切換的動作會改變到本身(instance self), 故此方法必須標明是 mutating, 否則 compile 會報出錯誤訊息

  1. enum Myswitch: Myprotocol {
  2. case Off, On
  3. mutating func toggle() {
  4. switch self {
  5. case Off:
  6. self = On
  7. case On:
  8. self = Off
  9. }
  10. }
  11. }
  12. var sw=Myswitch.On         // instantiate sw 被實體法, 它隸屬 Myswich 型別
  13. print("Now sw state is:\(sw)") // sw=On
  1. sw.toggle() // 使用特異功能來切換 sw 的值
  2. print("Now sw state is:\(sw)") // sw=Off
  3. // mutating func --> 我把它翻譯成特異功能, 因為它會改變 self.







2016年4月9日 星期六

玩玩 swift

swift 是開發 iOS 程式重要的語言工具之一, 目前是 open source,

官方網站:  https://swift.org/

首先在 linux 下需架好環境:

參考網址
https://swift.org/getting-started/#installing-swift
https://linuxmint.tumblr.com/post/135280204927/how-to-use-swift-programming-language-in-ubuntu


1.  swift 官方下載: https://swift.org/download/#releases
    https://swift.org/builds/development/ubuntu1510/swift-DEVELOPMENT-SNAPSHOT-2016-01-25-a/swift-DEVELOPMENT-SNAPSHOT-2016-01-25-a-ubuntu15.10.tar.gz.sig
https://swift.org/builds/development/ubuntu1404/swift-DEVELOPMENT-SNAPSHOT-2016-01-25-a/swift-DEVELOPMENT-SNAPSHOT-2016-01-25-a-ubuntu14.04.tar.gz
     p.s. 因 release 版未將 swift-build 放入, 最好下載上述開發版
2. 使用 tar 解出swift 套件:  tar -zxvf  xxxx-xxx.xz
3. 設定好環境變數 PATH 指向swift 編譯程式的 bin 目錄: export PATH= ....:$PATH
4. 安裝開發 swift 所需要的相關套件:   apt-get install clang   libicu-dev
5. 驗證是否安裝成功:  swift -version
6. swift 交談命令程式(REPL), 直接執行 swift 就可看到:  swift
     在 REPL 中鍵入 :q 離開 swift 交談視窗
7. 建立編譯環境
     a. 建立一個目錄當專案:  mkdir Hello
     b. 進入該專案目錄:  cd Hello
     c. 建立 Package.swift 檔案: touch Package.swift
     d. 建立原始碼目錄: mkdir Sources
     e. 建立原始碼主檔: touch Sources/main.swift
     f. 編輯主檔: gedit Source/main.swift
         將程式碼 print("Hello World") 鍵入主檔(main.swift)中
     g. 開始編譯: swift build

         編譯程式將 Source/main.swift 加以編譯程可執行檔,使用 Package.swift 所在的目錄名稱來命名可執行檔, 編譯好的執行檔將會放在 .build/debug 目錄內

     h. 執行編譯過的程式:      .build/debug/Hello

基礎知識:
常數宣告 let  a=...
變數宣告 var a=...

常數型別(TYPE)宣告   let a:TYPE=...
變數型別(TYPE)宣告  var a:TYPE=...
其中 TYPE 可以是: Int, Uint, Float, Double, String
(整數, 浮點數, 更精密浮點數, 字串)

許多型別, 其實swift 會自行推論出正確的型別,
例如 var a=1   ---> a 是整數
         var b="sasds"  --->  b 是字串
         var c=1.23       --->  c 是 Double
...等等, 因此上述的 a,b,c 其實不需宣告型別(TYPE) 也可以


何謂 Tuples: 將各種型別組合成一個集合, 例如 let a=("1",2,3.1415)
其中 a.0 等於字串 "1", a.1  等於整數 2, a.2 等於浮點數 3.1415
將Tuple 值用括號可以分離出各元素:
例如  let a=("1",2,3.1415);  let  (a0,_,a2)=a , 其中 a0="1", 第二個使用底線忽略, a2=3.1415

陣列型別使用相同型別的元素用 [,,] 來構成, 例如 let a=[1,2,3]
字典型別用key:value成對元素陣列所構成 let dic=["a":"dsd","2":"kiki"]; let b=dic["a"];
其中 key 與 value 型別必須分別統一使用相同型別  let dic=[1:"dsd",2:"kiki"]; let b=dic[1];

何謂 optionals (可有可無)變數, 例如宣告 var a:Int? =404, 其中後面 '?' 就已代表 a 宣告成可有可無的整數型別, 可有可無意味著:變數未指定也可, 此例 a=nil, 或已指定完, 此例 a=404
但不指定 optionals 的變數, 則不能付與 nil 值

當一個可有可無變數要強制取用其值時,可以再後面加上驚嘆號 '!',強制取用,但一旦此變數若未指定.則程式可能會當掉
因此可以透過 optional binding 敘述來檢查 , 避免錯誤
if let  constantname = someOptionalvalue {
//   ...
}

錯誤處理程式
func catThrowAnError() throws {
 // ..程式可能會丟出依些錯誤訊息
}


do {
          try catThrowAnError()
       
          // ... No error, continue
     }   catch  Error1.xxx {        
          // ...
     } catch  Error2.xxx {        
          // ...
      }
自訂驗證程序宣告, 當 condition 有錯誤時, 則停止程式, 並丟出錯誤訊息:
   assert(condition,"Error message");

字串可以相加  "Hello" + "World"
餘數  (a%b)
範圍 1...5     指的是 1 到 5
範圍 0..<10 指的是 0 到 9 ( 從0 開始, 小於 10)

the nil coalescing operator ??
let a:Int?=nil      // define an optional Interger constant, assign it to nil
// if a is not nil return a , else return 0
let b= ( a != nil ?  a!: 0 )
// same as expression    a ?? 0
let b=( a ?? 0 )

Type casting: 成型

字串的method
1. characters.count
2. append
3. insert

var a="SDSD"
a.characters.map {$0} // list all the character

單一字元(single character)並不等於單一字元的字串(a string with single character), 在於它是不同型別, 字元用 Character 來宣告, 字串用 String 來宣告, 使用前後雙引號時將自動判斷為字串型別

swift 語言有3種主要的收集型別(collection type): 陣列(Array),  集合(Set), 字典(Dictionary, 這些行別都是 mutable, 可修改的. 但若宣告程常數就不得修改了

在 swift 裡的條列式流程 switch .. case, 在case 執行完後將會自動跳離, 不像 c 語言要加入 bread 來跳開. 但可以用 fallthrough 讓它往下繼續執行, switch 可以用 tuple 當成多變數條件式, 如果無關係的條件, 可以用底線 '_' 讓它忽略該條件

switch (a,b) {
    case (_,0) :
                      ...
    case (0,_) :
                       ...
    default:
                       ...
}

value binding: 數值綁定
在switch-case 的條件式裡可以用 let 語法來綁定數值(value binding)讓他可以在該條件成立下取用,例如:
var a=(2,3)
// ...
 switch  a {
   case (let b,_) :
       print("\(b)")
   case (_,let c) :
       print("\(c)")
   default:
      print("OK")
 }

label: 標籤可以用名稱加帽號 lableName: 加註在程式迴圈上, 之後用 break lableName, 或 continue lableName 來控制程式流程, break lableName 用來結束迴圈內程序而跳到所標註迴圈外再往下執行. 而 continue lableName 除了放棄迴圈程序外, 並重新跳到所標註迴圈開頭地方再執行

guard  指令類似 if 的語法, 但 guide 必須要有 else 指令附加在後面, 而且他通常是用在func裏面,最後要有 return, 它預期條件式是對的,一旦不對才執行後面 else 內的指令,可以減少在對的條件成立時再寫指令
func my(b:Int) ->  {
     guard  b>3 else { print("OK"); return; }  
}
my(4)  // OK
my(3)  //

初始化消滅:當抽象型別像分類(class),結構(struc)及列舉(enum)要實體化成個體時, 他會執行該型別的的初始化程序叫 init(). 只有分類所產生的個體, 當要消滅時才會執行消滅程序叫作 deinit(), 對於儲存式屬性, 可以在型別宣告時就直接給初始值, 也可以透過初始化參數設定該屬性.初始化參數的語法與 func 裏面的參數語法是相同的. 對於常數型態的屬性仍然可以透過上述初始化程序重新設定它, 之後常數就不得再更改了. 對於分類所產生的個體而言, 常數屬性不能被子類別的繼承者所修改









改用 Tor browser 匿名瀏覽, 真正隱私不被追蹤的瀏覽器

只要身處在網際網路的世界, 其實行蹤早已暴露, 只要有心人士要追蹤,其實是逃不掉的,最近看到一個瀏覽器宣稱可以防止這樣的事情,當用的人愈多,其實行蹤愈安全,他的封包是透過
Tor節點來加密保護, 算是相當安全的連線. 可有效防止像 "traffic analysis" 分析軟體解析出瀏覽者的網路使用行為
參考 Tor 的官方文章: https://www.torproject.org/about/overview.html.en
他闡述了 Tor 的運作方式,且它本身是一個 open source, 由一群自願者所開發,值得推荐使用
官方下載區:
https://www.torproject.org/projects/torbrowser.html.en#linux

2016年4月5日 星期二

玩玩 NDK

NDK 是用 c 或 c++ 來寫 android  app.
很容易用來開發手機上使用的執行檔, 像是簡單的 hello world 等.
下載程式:  http://developer.android.com/ndk/downloads/index.html
我目前試用的是 r11c linux x86 64 bit 版 android-ndk-r11c-linux-x86_64.zip
但該網站建議大家還是用 SDK 開發 android app 較適合.

目錄 helloworld 內容共含 3 個檔案
main.cpp          --- 主程式
Android.mk      ---  給 ndk compliler 用的 makefile
Application.mk --- 給 ndk 產生一些平台要用的指示檔


main.cpp 主程式內容:
// begin of main.cpp
#include "iostream"
#include "stdio.h"
using namespace std;
int main(int argc, char **argv)
{
int i;
   cout << "Hello world" <<  endl;
   printf("Hi printf\n");
   for(i=0;i
<argc;i++)   {
       printf("argv[%d]:%s\n",i,argv[i]);
    }
    return 0;
}
// end of main.cpp 

Android.mk 檔案內容:
# begin of Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := main.out
LOCAL_C_INCLUDES +=
LOCAL_SRC_FILES := main.cpp
include $(BUILD_EXECUTABLE)
# end of  Android.mk

Application.mk 檔案內容:
#  begin of Application.mk
APP_STL := stlport_static
APP_PLATFORM := android-19
APP_BUILD_SCRIPT := Android.mk
#  end of Application.mk


使用 bash 執行以下 2 行 shell script 來設定好環境變數, 假設 ndk 掛在 /mnt/rw/ndk 上
export PATH=/mnt/rw/ndk/android-ndk-r11c:$PATH
export NDK_PROJECT_PATH=.

cd 到 helloworld 目錄內, 使用 bash 執行以下 shell script 來編譯程式:
ndk-build NDK_APPLICATION_MK=./Application.mk
NDK 會把輸出檔  main.out 放在 libs\armeabi 目錄下, 將他上傳到手機上或模擬器上設成可執行檔, 並開啟 terminal 執行即可.
 
假設手機的 ip address 為 192.168.0.5,且手機要開啟 adbd, listen port 預設為 5555.  底下使用 adb 來連接手機並上傳檔案到手機上讓 shell 去執行:
adb connect 192.168.0.5:5555
adb push libs/armeabi/main.out /data/local
adb shell  chmod 755 /data/local/main.out
adb shell /data/local/main.out 1 2 3

輸出:
Hello World
Hi printf
argv[0]:/data/local/main.out
argv[1]:1
argv[2]:2
argv[3]:3