正規表達式 Regular Expression

本篇 ShengYu 介紹規則表達式 Regular Expression 來尋找字串或取代字串,學會後便能善用規則表達式來尋找字串跟取代字串。

範例1:目標字串(.+)

給定字串為:This is a book.
要搜尋字串為:This is 開頭,後面配上任意字元的多次組合,
正則表達式為:This is(.+)

.:表示任意字元,除了 \n 之外
+:表示多次批配

範例2:(.+)目標字串(.+)

給定字串為:My name is ShengYu.
要搜尋字串為:任意字元的多次組合配上 name,後面配上任意字元的多次組合,
正則表達式為:(.+)name(.+)

正規表示式的符號意義

表達式 說明
^ 行首
$ 行尾
\s 空白
. 匹配任何單個字元
[0-9]+ 整數
+ 配運算式一次或多次
[A-Za-z]+ 英文單字

其它範例

範例 說明
^\s 匹配行首的空格
\s$ 匹配行末的空格
^cat 行首以cat開頭
^\s[0-9]+\sfiles…+ 行首 空格 數字多個以上 空格 files

其它參考
NotePad++ 正則表示式替換 高階用法 - IT閱讀
https://www.itread01.com/content/1549641605.html
notepad 正則表示式 規則運算式 範例 筆記
http://procedurenotes.blogspot.com/2017/05/notepad.html
正規表示式 Regular Expression
http://ccckmit.wikidot.com/regularexpression

Python 寫藍芽 RFCOMM 通訊程式

以下範例 ShengYu 將會介紹如何使用 Python 來寫 RFCOMM 藍芽通訊程式,內容包含使用 bluetooth socket 建立一個連線,傳輸資料與斷線。

server 端程式

server 端的程式一開始 bind 在 port 1,
listen 指的是最多可以接受多少連線,
接下來 accept,這裡 accept 會 block 不會立即返回,
直到 client 連上才返回,之後接收 client 的資訊並印出來,然後關閉連線。

rfcomm-server.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import bluetooth

server_sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )

port = 1
server_sock.bind(("", port))
server_sock.listen(1)

client_sock,address = server_sock.accept()
print "Accepted connection from ",address

data = client_sock.recv(1024)
print "received [%s]" % data

client_sock.close()
server_sock.close()

client 端程式

client 端的程式需將 server 端的 addr 填入 bd_addr 內,才能成功連上,
怎麼查詢藍芽 addr 請看這篇
如下範例, connect 嘗試連上 addr 為 “01:23:45:67:89:AB”, port 為 1 的裝置,
connect 連上 server 後,送出一個 hello!! 就斷線。

rfcomm-client.py
1
2
3
4
5
6
7
8
9
10
11
12
import bluetooth

bd_addr = "01:23:45:67:89:AB" # server 端的 addr

port = 1

sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )
sock.connect((bd_addr, port))

sock.send("hello!!")

sock.close()

以上的兩個基本範例就能夠使兩個藍芽裝置進行溝通了!

ShengYu 將會在下一篇介紹 如何用Python的藍芽 L2CAP 協定來通訊

參考
https://people.csail.mit.edu/albert/bluez-intro/x232.html

std::thread 怎麼實作的?

本篇介紹一下一般各個作業系統的 C++ 編譯器是怎麼實作 std::thread 的,
在一番 trace code 的結果後,llvm 的 libc++ 實作是這樣的,
在 unix 平台下開 thread 就是轉換到 pthread 的 pthread_create。
在 windows 平台下開 thread 就是轉換到 win32 的 _beginthreadex。
gcc 的 libstdc++ 實作也是如此。

簡單介紹這兩種 c++ 庫差異:

  • libc++ (LLVM C++ standard library with C++ 11 support)
  • libstdc++ (GNU C++ standard library)

以下是 llvm 下 libc++ 怎麼實作的 code snippet,

1. std::thread::thread 的實作

建構子 thread 轉換成內部的 __libcpp_thread_create

libcxx/include/threadlink
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
template <class _Fp, class ..._Args,
class
>
thread::thread(_Fp&& __f, _Args&&... __args)
{
typedef unique_ptr<__thread_struct> _TSPtr;
_TSPtr __tsp(new __thread_struct);
typedef tuple<_TSPtr, typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp;
_VSTD::unique_ptr<_Gp> __p(
new _Gp(std::move(__tsp),
__decay_copy(_VSTD::forward<_Fp>(__f)),
__decay_copy(_VSTD::forward<_Args>(__args))...));
int __ec = __libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get());
if (__ec == 0)
__p.release();
else
__throw_system_error(__ec, "thread constructor failed");
}

1-1. std::thread::thread 在 unix 平台的實作內容

__libcpp_thread_create 在 unix 平台是呼叫 pthread_create

libcxx/include/__threading_supportlink
1
2
3
4
5
6
7
typedef pthread_t __libcpp_thread_t;
...
int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
void *__arg)
{
return pthread_create(__t, 0, __func, __arg);
}

1-2. std::thread::thread 在 windows 平台的實作內容

__libcpp_thread_create 在 windows 平台是呼叫 _beginthreadex

libcxx/src/support/win32/thread_win32.cpplink
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
void *__arg)
{
auto *__data = new __libcpp_beginthreadex_thunk_data;
__data->__func = __func;
__data->__arg = __arg;

*__t = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0,
__libcpp_beginthreadex_thunk,
__data, 0, nullptr));

if (*__t)
return 0;
return GetLastError();
}

2. std::thread::join 的實作

join 轉換成內部的 __libcpp_thread_join

libcxx/src/thread.cpplink
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void
thread::join()
{
int ec = EINVAL;
if (!__libcpp_thread_isnull(&__t_))
{
ec = __libcpp_thread_join(&__t_);
if (ec == 0)
__t_ = _LIBCPP_NULL_THREAD;
}

if (ec)
__throw_system_error(ec, "thread::join failed");
}

2-1. std::thread::join 在 unix 平台的實作內容

__libcpp_thread_join 在 unix 平台是呼叫 pthread_join

libcxx/include/__threading_supportlink
1
2
3
4
int __libcpp_thread_join(__libcpp_thread_t *__t)
{
return pthread_join(*__t, 0);
}

2-2. std::thread::join 在 windows 平台的實作內容

__libcpp_thread_join 在 windows 平台是呼叫 WaitForSingleObjectExCloseHandle

libcxx/src/support/win32/thread_win32.cpplink
1
2
3
4
5
6
7
8
int __libcpp_thread_join(__libcpp_thread_t *__t)
{
if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED)
return GetLastError();
if (!CloseHandle(*__t))
return GetLastError();
return 0;
}

總結

在一番 trace code 的結果後,std::thread 在 llvm 的 libc++ 實作是這樣的,
在 unix 下
std::thread::thread 轉換成 pthread_create
std::thread::join 轉換成 pthread_join
在 windows 下
std::thread::thread 轉換成 _beginthreadex
std::thread::join 轉換成 WaitForSingleObjectExCloseHandle

線上 trace code 工具

介紹一下 Woboq 這個線上 trace code 網頁,可以點擊關鍵字跳至定義處,trace code 起來很方便,減少很多搜尋的時間。
thread::thread()
__libcpp_thread_create()

相關主題
C/C++ 新手入門教學懶人包
std::condition_variable 怎麼實作的?
std::mutex 怎麼實作的?
C++11 在各平台下如何實現?

在 Windows 下編譯安裝 Boost 1.70.0

本篇 ShengYu 將介紹如何在 Windows 下編譯安裝 Boost 1.70.0,
這版 boost 1.70.0 釋出日期是 2019/04/12,開始動手編譯原始碼安裝吧!

以下為我的系統環境:
作業系統:Windows 10
編譯器:Visual Studio 2015 (Version 14)
使用版本:boost 1.70.0 下載處 / 7z / tar.gz

使用指令下載

1
2
3
wget https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz
tar xvf boost_1_70_0.tar.gz
cd boost_1_70_0

Read More

開源專案ScreenCapture-螢幕截圖自動存檔小工具

介紹

ScreenCapture 是一個支援 win7/win10 螢幕截圖並且自動存檔小工具,讓你可以在短時間擷取多張圖片。

故事起源

這是大學時期寫的小工具了,直到工作後才想說拿出來翻修更新一下,也順便開源一下,在一些情況下使用時真的很好用。

特色

  • 截圖時立馬自動存檔,根據當下的時間作為檔案名稱,這樣可以節省時間,可以短時間內按截圖快捷鍵擷取多次截圖。
  • 支援內建的 PrintScreen key,即使 ScreenCapture 沒有在前景執行,照樣可以按下 PrintScreen key 就自動完成了存檔動作。

以上兩大特色功能為我最想要用到的功能,也是很常遇到的狀況。
如果你對我的工具有興趣的話可以透過下面網址瞭解或下載:
專案首頁:https://shengyu7697.github.io/ScreenCapture/

Demo

如果你覺得這工具很讚,可以幫我按個星星,也可以透過贊助我讓我更有動力開發新功能唷!

其它相關文章推薦
開源專案CursorJail-滑鼠鎖定工具
開源專案-2048
開源專案-tetris俄羅斯方塊
開源專案-數獨sudoku
開源專案-金庸群俠傳
開源專案-仙劍奇俠傳

開源專案CursorJail-滑鼠鎖定工具

介紹

CursorJail 是一個支援 win7/win10 滑鼠鎖定的工具,設定滑鼠的移動範圍按下快捷鍵後,滑鼠便只能在這個範圍內移動,目前只支援 windows。

故事起源

以前學生時期很愛玩魔獸,當時喜歡用視窗模式玩,過程中很容易讓滑鼠滑到視窗外,導致遊戲沒有收到滑鼠的事件,在即時遊戲中角色很容易就因此而死亡回家泡溫泉,後來從網路上知道竟然有這種視窗鎖定工具後,便覺得超級方便的,但是大多是對岸寫的工具,裡面有沒有病毒後門都不知道,又因為大學專題有接觸 windows 視窗程式設計便知道有這種 API,心中便燃起了自己也寫一個想法,沒多久這工具就寫好了,之後它便陪著我度過那些魔獸爭霸的日子了~~~
那時並沒有把這工具分享出來的想法,只有自己用得很爽!工作後思想變不同了,便在空閑日子時把這個過往的工具挖出來翻修並開源,以上就是這個小工具的故事起源了。

若你對我這個工具感興趣的話,可以透過下面 github 去下載,也可以給個星星唷!
Github 連結:https://github.com/shengyu7697/CursorJail

其它相關文章推薦
開源專案ScreenCapture-螢幕截圖自動存檔小工具
開源專案-2048
開源專案-tetris俄羅斯方塊
開源專案-數獨sudoku
開源專案-金庸群俠傳
開源專案-仙劍奇俠傳

事件驅動框架列表

事件驅動程式設計 (Event-driven programming) 是一種電腦程式設計模型。

以下列出幾個代表性的事件驅動框架,有空時可以多多拜讀。

名稱 語言 License 代碼 說明
Libevent C BSD github 維基
Twisted Python MIT github 維基
Node.js JavaScript MIT github 維基
Boost.Asio C++ github
Asio C++ Library C++ github
libuv C github 給Node.js用
muduo C++ gtihub 陳碩 (linux only)

GitHub 建立專案首頁 project page

使用 Github Pages 功能可以免費地為專案建立首頁。
以下介紹直接將專案下 README.md 來作為專案首頁的方法。

先到你的專案的 repository 下建立 gh-pages 分支,
這個 gh-pages 分支就是擺放靜態網頁相關的分支,
我是放 github jekyll 模板支援的主題,所以只要放 README.md 和 _config.yml 就可以了

Read More

在 Ubuntu 下編譯安裝 Boost 1.70.0

本篇 ShengYu 將介紹如何在 Ubuntu 下編譯安裝 Boost 1.70.0,
這版 boost 1.70.0 釋出日期是 2019/04/12,開始動手編譯原始碼安裝吧!

以下為我的系統環境:
作業系統:Ubuntu 16.04
GCC:5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.11)
G++:5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.11)
使用版本:boost 1.70.0 下載處 / 7z / tar.gz

使用 wget 指令下載原始碼

1
2
3
wget https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz
tar xvf boost_1_70_0.tar.gz
cd boost_1_70_0

Read More

boost::asio epoll_reactor 源碼分析

asio 的菁華可以從 epoll reactor 開始看起。
epoll_reactor.hpp
epoll_reactor.ipp

有寫過 epoll 代碼的都知道 epoll_create(), epoll_ctl(), epoll_wait() 這幾個關鍵的 API, 可以從代碼去循跡大神是怎麼封裝這些東西的。

再來一個蠻重要的,通常這種反應爐事件驅動模型是怎麼中斷就結束的,為什麼這樣說呢?因為這種等待是 Block 的,沒有東西進來是不會從 epoll_wait() 返回的,

Read More