Windows 10 測試搖桿的工具

本篇 ShengYu 要介紹在 Windows 10 下測試搖桿的工具,我自己的話是會拿來測試我的 PS2 搖桿功能是否正常,

在 Windows 10 測試搖桿

按鍵盤上按下 Window+R 鍵進入 執行 →在開啟右欄輸入 joy.cpl,按確定後就可以進到 遊戲控制器 畫面,

使用畫面如下,找到 joy.cpl 並執行,

joy.cpl 執行後可以看到 遊戲控制器 的視窗,
請點 Generic USB Joystick 再點選右下角的 內容,以我的一對二轉接頭的話,是顯示兩個 Twin USB Joystick,那就點選其中一個再按右下角的 內容

接下來在內容頁面(下圖右方視窗)的 測試 頁面可以測試搖桿的各按鍵有無問題,搖桿軸心位置不在中心點的話,請至 設定 頁面按 校正 進行校正。

以上就是 Windows 10 測試搖桿的工具的介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

Xbox One 搖桿

在 PC 電腦上用搖桿玩遊戲最推薦使用 Xbox One 搖桿,原因是因為很多遊戲都有原生支援(因為 Xbox 是微軟自己的嘛!),不用在另外設定按鍵,隨插即用真的是很方便,非常適合只想專心好好打電動的懶人族。

對 Xbox One 搖桿有興趣的可以到以下通路購買,
蝦皮商城

其它相關文章推薦
Ubuntu/Linux 測試搖桿的工具

Linux uniq 去除連續重複用法與範例

本篇 ShengYu 介紹 Linux uniq 指令去除連續重複資料用法與範例。

Linux uniq 指令將檔案內容去除連續重複

以每一行為單位,相鄰兩行內容重複的話,uniq 將會去除重複的行,以數字為例,檔案內容如下,

input.txt
1
2
3
4
5
6
7
8
1
1
5
2
2
2
4
3

可以用 Linux uniq 的指令輕鬆達成去除連續重複資料,指令如下,會將結果輸出標準輸出,

1
2
3
4
5
6
$ uniq input.txt
1
5
2
4
3

Linux uniq 指令將檔案內容去除重複(非連續)

如果是非連續的重複資料直接用 uniq 是沒有效果的,可以先用 sort 指令將內容排序後,這樣重複的資料就會出現在相鄰的位置,
這時再用 uniq 指令去除這些連續重複資料即可,

input2.txt
1
2
3
4
5
6
7
8
4
1
4
3
5
4
2
3

先用 sort 指令再用 uniq 去除連續重複資料指令如下,

1
2
3
4
5
6
$ sort input2.txt | uniq
1
2
3
4
5

其它相關文章推薦
Linux 常用指令教學懶人包
Linux cut 字串處理用法與範例
Linux find 尋找檔案/尋找資料夾用法與範例
Linux grep/ack/ag 搜尋字串用法與範例
Linux tee 同時螢幕標準輸出和輸出到檔案用法與範例
Linux xargs 參數列表轉換用法與範例
Linux tail 持續監看檔案輸出用法與範例
Linux du 查詢硬碟剩餘空間/資料夾容量用法與範例
Linux wget 下載檔案用法與範例

C++ std::unique_ptr 用法與範例

本篇 ShengYu 介紹 C++ 的 std::unique_ptr 用法與範例,unique_ptr 跟 shared_ptr 用法一樣,只是他的指標不能共享,是唯一無二的,

  • 初始化用法
  • 函式傳遞 unique_ptr
  • 使用 move 轉移 unique_ptr 擁有權
  • 函式回傳 unique_ptr
  • unique_ptr 轉 shared_ptr

需要引入的標頭檔<memory>,編譯需要支援 C++11

初始化用法

使用 unique_ptr 初始化一個實體的範例如下,

1
unique_ptr<Student> s = make_unique<Student>();

要注意的是 make_unique 這個輔助函式是在 C++14 才加入的,所以如果編譯器未支援 C++14 而使用了 make_unique 會出現編譯錯誤唷!

不使用 make_unique 的寫法如下,但是比較不建議,因為會產生不連續記憶體區塊,比起一次分配連續記憶體區塊效能較差,

1
unique_ptr<Student> s = unique_ptr<Student>(new Student());

函式傳遞 unique_ptr

根據 unique_ptr 是唯一性的原則(不能被複製),所以在參數傳遞時不能使用傳值 call by value,而是要傳參考 call by reference,否則會編譯錯誤,範例如下,

1
2
3
4
5
6
7
8
9
10
11
12
13
void func1(unique_ptr& a) {
// ...
}

void func2(unique_ptr b) {
// ...
}

int main() {
func1(a);
func2(b); // 編譯錯誤
return 0;
}

使用 move 轉移 unique_ptr 擁有權

前面提到說不能複製,但移動總可以了吧!可以的

1
2
3
4
5
6
7
//class Student;

unique_ptr<Student> s1 = make_unique<Student>();

unique_ptr<Student> s2 = s1; // 編譯錯誤

unique_ptr<Student> s3 = move(s1); // 移動到 s2, 之後不能去使用 s1

函式回傳 unique_ptr

前面提到 unique_ptr 不能複製,那函式要回傳 unique_ptr 要怎麼使用?
直接回傳 unique_ptr,如下範例,詳細討論可以看這篇

1
2
3
4
5
6
7
8
9
10
11
unique_ptr<Student> func1() {
auto s = make_unique<Student>();
// or
// unique_ptr<Student> s = unique_ptr<Student>(new Student());
return s;
}

int main() {
auto s = func1();
return 0;
}

unique_ptr 轉 shared_ptr

unique_ptr 轉 shared_ptr 有兩種方式,一種是

1
shared_ptr<Size> s = make_unique<Size>();

另一種是使用 move,

1
2
unique_ptr<Size> s1 = make_unique<Size>();
shared_ptr<Size> s2 = move(s1);

反過來 shared_ptr 轉 unique_ptr 則不行。

其他參考文章
std::unique_ptr - cppreference.com
https://en.cppreference.com/w/cpp/memory/unique_ptr
c++ - Returning unique_ptr from functions - Stack Overflow
https://stackoverflow.com/questions/4316727/returning-unique-ptr-from-functions

其它相關文章推薦
如果你想學習 C++ 相關技術,可以參考看看下面的文章,
C/C++ 新手入門教學懶人包
std::shared_ptr 用法與範例

統計 count vector 元素出現次數

本篇 ShengYu 介紹如何統計 count vector 元素出現次數,

要統計 vector 裡某元素出現的次數或者某元素重複的次數,可以使用 std::count() 這個函式,
以下範例示範用 std::count() 統計 vector 裡某元素出現的次數,

cpp-count-vector.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// g++ cpp-count-vector.cpp -o a.out
#include <iostream>
#include <vector>
using namespace std;

int main() {
vector<int> v1 = {1,0,1,1,0};
vector<int> v2 = {1,2,3,3,4};

cout << count(v1.begin(), v1.end(), 1) << "\n";
cout << count(v2.begin(), v2.end(), 3) << "\n";
cout << count(v2.begin(), v2.end(), 5) << "\n";

return 0;
}

輸出如下,第一個是統計 v1 裡出現 1 的次數,結果是出現 3 次,
第二個是統計 v2 裡出現 3 的次數,結果是出現 2 次,
第三個是統計 v2 裡出現 5 的次數,結果是出現 0 次,

1
2
3
3
2
0

其他參考
count - C++ Reference
https://www.cplusplus.com/reference/algorithm/count/

Ubuntu 關閉自動更新

這篇 ShengYu 介紹如何在 Ubuntu 關閉停用自動更新,
Ubuntu 關閉停用自動更新分為兩種,分別為

  • 使用圖形化介面 gui 關閉自動更新
  • 使用 command line 關閉自動更新

有時 ubuntu 要使用 apt 安裝東西時會發現 apt 被鎖住的提示訊息,

1
2
E: Could not get lock /var/lib/dpkg/lock - open (11: Resource temporarily unavailable)
E: Unable to lock the administration directory (/var/lib/dpkg/), is another process using it?

使用 ps aux | grep apt 指令後會發現 apt 在背景執行著,

1
2
root       752  0.0  0.0   4628   828 ?        Ss   21:19   0:00 /bin/sh /usr/lib/apt/apt.systemd.daily update
root 759 0.0 0.0 4628 1672 ? S 21:19 0:00 /bin/sh /usr/lib/apt/apt.systemd.daily lock_is_held update

這時就會懷疑是不是正在執行軟體更新,

這邊就來介紹怎麼關閉 Ubuntu 的自動更新,

使用圖形化介面 gui 關閉自動更新

搜尋 software 找到 Software & Updates

開啟 Software & Updates 後切換到 Updates 頁面,
Automatically check for updates 的選項改成 Never,表示不自動檢查更新
When there are security updates 的選項改成 Display immediately ,表示有安全性更新時會先顯示出來,而不是直接下載自動安裝,
原本設定如下圖,

更改後的設定如下圖,

使用 command line 關閉自動更新

使用 vim 編輯設定檔 sudo vim /etc/apt/apt.conf.d/20auto-upgrades
將 Update-Package-Lists 與 Unattended-Upgrade 改成 0

/etc/apt/apt.conf.d/20auto-upgrades
1
2
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";

改完後設定如下,

/etc/apt/apt.conf.d/20auto-upgrades
1
2
3
4
APT::Periodic::Update-Package-Lists "0";
APT::Periodic::Download-Upgradeable-Packages "0";
APT::Periodic::AutocleanInterval "0";
APT::Periodic::Unattended-Upgrade "0";

這樣就搞定了!
如果本來背景就有 apt 在更新的話,做完以上設定會發現 apt 還在背景繼續執行,這時候重開機後就解決了。

Linux sort 排序用法與範例

本篇 ShengYu 介紹 Linux sort 排序用法與範例。

Linux sort 指令將檔案內容排序

假設有個檔案內容 input.txt,需要將它排序,檔案內容如下,由數字所組成,

input.txt
1
2
3
4
5
6
4
1
3
5
2
3

那麼可以用 Linux sort 的指令輕鬆達成,指令如下,會將結果輸出標準輸出,

1
2
3
4
5
6
7
$ sort input.txt
1
2
3
3
4
5

要輸出到檔案的話,可以這樣寫就輸出到 output.txt 了,

1
$ sort input.txt > output.txt

這邊換成英文字母試試看 sort 來排序,input2.txt 檔案內容如下,

input2.txt
1
2
3
4
5
6
7
E
B
E
B
A
C
D

輸出結果如下,英文字母也是可以排序的,

1
2
3
4
5
6
7
8
$ sort input2.txt 
A
B
B
C
D
E
E

Linux sort 指令排序並去除重複

如果要用 sort 指令排序並去除重複,可以加上 -u--unique 的選項,

1
2
3
4
5
6
$ sort input2.txt -u
A
B
C
D
E

Linux sort 指令由大排到小 / 反向排序

如果要用 sort 指令由大排到小或者是反向排序的話,可以加上 -r--reverse 的選項,

1
2
3
4
5
6
7
8
$ sort input2.txt -u
E
E
D
C
B
B
A

其它相關文章推薦
Linux 常用指令教學懶人包
Linux cut 字串處理用法與範例
Linux find 尋找檔案/尋找資料夾用法與範例
Linux grep/ack/ag 搜尋字串用法與範例
Linux tee 同時螢幕標準輸出和輸出到檔案用法與範例
Linux xargs 參數列表轉換用法與範例
Linux tail 持續監看檔案輸出用法與範例
Linux du 查詢硬碟剩餘空間/資料夾容量用法與範例
Linux wget 下載檔案用法與範例

cmake if 用法教學

本篇 ShengYu 介紹 cmake 的 if 語法、if else 語法以及 if else 語法與範例,後半部會介紹 if 語句搭配 not、and、or 邏輯運算子。

以下內容分為這幾個部份,

  • CMake if 語法
  • CMake if else 語法
  • CMake if elseif 語法
  • CMake NOT 邏輯運算子
  • CMake AND 邏輯運算子
  • CMake OR 邏輯運算子

CMake if 語法

CMake if 語法為

1
2
3
if(condition)
# ...
endif()

CMake if else 語法

CMake if else 語法為

1
2
3
4
5
if(condition)
# ...
else()
# ...
endif()

CMake if elseif 語法

CMake if elseif 語法為

1
2
3
4
5
6
7
if(condition)
# ...
elseif(condition)
# ...
else()
# ...
endif()

CMake NOT 邏輯運算子

CMake AND 運算子語法為

1
2
3
if(NOT condition)
# ...
endif()

CMake AND 邏輯運算子

CMake AND 運算子語法為

1
2
3
if((condition) AND (condition))
# ...
endif()

實際範例,以字串為例,

1
2
3
if((VALUE1 STREQUAL "foo") AND (VALUE2 STREQUAL "bar"))
message("foo and bar")
endif

CMake OR 邏輯運算子

CMake OR 運算子語法為

1
2
3
if((condition) OR (condition))
# ...
endif()

實際範例,以字串為例,

1
2
3
if((VALUE1 STREQUAL "foo") OR (VALUE2 STREQUAL "bar"))
message("foo or bar")
endif

AND OR 運算子混用範例為

1
2
3
if((condition) AND (condition OR (condition)))
# ...
endif()

其他參考
if — CMake Documentation
https://cmake.org/cmake/help/latest/command/if.html
CMake 入門/流程控制 - 維基教科書,自由的教學讀本
https://zh.wikibooks.org/wiki/CMake_%E5%85%A5%E9%96%80/%E6%B5%81%E7%A8%8B%E6%8E%A7%E5%88%B6

C++ std::stack 用法與範例

本篇 ShengYu 將介紹 C++ std::stack 用法與範例,stack 是個很基本也很重要的資料結構,stack 是後進先出原則(LIFO,Last In First Out),在很多考題上都容易出現,stack 常用基本的操作方法有 push()pop()top(),是必學的基本功能。

因為 stack 的後進先出原則,你只能看到最上面 top 的元素是什麼,之前推 push 進去的元素無法去遍歷查看的。

以下 C++ stack 用法與範例將分為這幾部分,

  • 將元素放入 stack 頂端
  • 從 stack 頂端移出元素
  • 取得 stack 裡的元素數量
  • 判斷 stack 是否為空
  • stack 查看最頂端的元素

要使用 stack 容器的話,需要引入的標頭檔<stack>

將元素放入 stack 頂端

stack 頂端要推入新元素的話,可以使用 push()

std-stack.cpp
1
2
3
4
5
std::stack<int> mystack;
mystack.push(1);
mystack.push(2);
mystack.push(3);
std::cout << mystack.size() << "\n"; // 3

也可以從在 stack 建構時帶入元素,例如從 vector 複製元素,

1
2
3
std::vector<int> myvector = {4, 5};
std::stack<int, std::vector<int>> mystack2(myvector);
std::cout << mystack2.size() << "\n"; // 2

也可以從在 stack 建構時從 deque 複製元素,

1
2
3
std::deque<int> mydeque = {6, 7, 8};
std::stack<int, std::deque<int>> mystack3(mydeque);
std::cout << mystack3.size() << "\n"; // 3

從 stack 頂端移出元素

stack 頂端要移出元素的話,要使用 pop()

std-stack2.cpp
1
2
3
4
5
6
7
std::stack<int> mystack;
mystack.push(1);
mystack.push(2);
std::cout << mystack.size() << "\n"; // 2
mystack.pop();
mystack.pop();
mystack.pop(); // Segmentation fault

值得注意的是,上例中 stack 為空時再 pop 會讓程式崩潰,
為了避免程式崩潰,所以通常在 pop 時會對 stack 進行檢查是否為空,非空才 pop(),例如下面這樣,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
std::stack<int> mystack;
mystack.push(1);
mystack.push(2);
std::cout << mystack.size() << "\n"; // 2
if (!mystack.empty()) {
mystack.pop();
}
if (!mystack.empty()) {
mystack.pop();
}
std::cout << mystack.size() << "\n"; // 0
if (!mystack.empty()) {
mystack.pop();
}

取得 stack 裡的元素數量

stack 要取得 stack 裡元素數量要使用 size()

std-stack3.cpp
1
2
3
4
5
6
std::stack<char> mystack;
std::cout << mystack.size() << "\n";
mystack.push('a');
std::cout << mystack.size() << "\n";
mystack.push('b');
std::cout << mystack.size() << "\n";

輸出為

1
2
3
0
1
2

從 vector 複製元素初始化 stack,並且印出數量

1
2
3
4
// stack initialized from vector
std::vector<int> myvector = {1, 2};
std::stack<int, std::vector<int>> mystack2(myvector);
std::cout << mystack2.size() << "\n"; // 2

判斷 stack 是否為空

stack 要判斷是否為空的話,可以使用 empty()

std-stack4.cpp
1
2
3
4
5
6
7
8
9
10
11
12
std::stack<int> mystack;
if (mystack.empty())
std::cout << "empty\n";
else
std::cout << "not empty\n";

mystack.push(1);

if (mystack.empty())
std::cout << "empty\n";
else
std::cout << "not empty\n";

輸出為

1
2
empty
not empty

stack 查看最頂端的元素

stack 要查看最頂端的元素,可以使用 top(),要注意的是如果 stack 為空時呼叫 top() 會 Segmentation fault,正確作法為先判斷 stack 是否為空,stack 不為空才呼叫 top()

std-stack5.cpp
1
2
3
4
5
6
7
8
9
std::stack<int> mystack;
// std::cout << mystack.top() << "\n"; // Segmentation fault
if (!mystack.empty())
std::cout << mystack.top() << "\n";
mystack.push(1);
mystack.push(2);
mystack.push(3);
if (!mystack.empty())
std::cout << mystack.top() << "\n"; // 3

以上就是 C++ std::stack 用法與範例的介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

其他參考
stack - C++ Reference
https://www.cplusplus.com/reference/stack/stack/

leetcode 一些使用到 stack 的題目
Valid Parentheses
https://leetcode.com/problems/valid-parentheses/
Min Stack
https://leetcode.com/problems/min-stack/

其它相關文章推薦
如果你想學習 C++ 相關技術,可以參考看看下面的文章,
C/C++ 新手入門教學懶人包
std::queue 用法與範例
std::deque 介紹與用法
std::vector 用法與範例
std::set 用法與範例
std::map 用法與範例
std::unordered_map 用法與範例
std::thread 用法與範例
std::mutex 用法與範例
std::find 用法與範例
std::sort 用法與範例
std::random_shuffle 產生不重複的隨機亂數
std::shared_ptr 用法與範例
std::async 用法與範例

libvncserver 原始碼入門介紹

使用到 libvncserver 的專案有很多,像是比較有名的 x11vnc,其中一個便是 android-vnc-server,我便稍微研究了一下在 Android 怎麼使用,

在 fbvncserver.c 裡 Framebuffer device 的路徑定義如下,Android 不使用 /dev/fb0 路徑,

1
#define FB_DEVICE "/dev/graphics/fb0"

所以只要從這個裝置裡取出影像資料便是螢幕的影像了,所以螢幕截圖的功能也可以這樣實現。

init_fb() 裡用 open 開啟 fb 裝置,之後再用 ioctl() 取得該裝置的資訊(寬跟高),
再用 mmap() 取得 fb 裝置記憶體的映射

update_screen() 裡取得 framebuffer 的 pixel 的資料,比對跟前一幀的 pixel,不一樣的話就使用 rfbMarkRectAsModified() 更新這次的畫面有改變的矩形範圍,

這樣一個小小的程式便完成了 VNC Server 的工作,用了 libvncserver 提供好的 API 是方便許多。

其他參考
fbvncserver.c
https://android.googlesource.com/platform/external/libvncserver/+/master/examples/android/jni/fbvncserver.c
PC 远程控制 android手机的方法之一VNC
https://blog.csdn.net/shuzui1985/article/details/7841079
另外還一有篇簡單的 libvncserver 入門介紹
https://my.oschina.net/u/1250206/blog/1577985
oNaiPs/droidVncServer
https://github.com/oNaiPs/droidVncServer
在這個 Android 專案裡多了一層 GUI 來控制 VNC Server 的設定

Bowling Game Kata

最近 ShengYu 在閱讀 Uncle Bob 的無暇程式碼 番外篇 The Clean Coder 第6章時,發現了所謂的程式設計道場 (Coding Dojo),便覺得有趣,

術語解釋
Kata 套路/對打
Wasa 瓦薩
Dojo 道場
Randori 自由練習

我自己也練習了一個 Bowling Game Kata,詳情可以看 Github 的 commit 紀錄,就知道我做了什麼事。

以下是 Uncle Bob 喜歡的 kata
保齡球 http://butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata
質因數 http://www.butunclebob.com/ArticleS.UncleBob.ThePrimeFactorsKata
自動換行 http://thecleancoder.blogspot.com/2010/10/craftsman-62-dark-path.html

測試驅動 TDD (Test-Driven Development) 給我一個很大的啟發是,過往我們寫的程式過很久後再回去看時,發現當初寫得不夠好,要擴充難以擴充,想重構又怕改壞了原有功能,但如果當初是測試驅動 TDD 開發的,那麼我們便能有信心的動手下去改,因為改完只需要再跑一次測試就知道有沒有改壞,這是多麼好的一件事啊,然而現實面不一定能夠這樣,可能變成是不敢去改,因為有功無賞打壞要賠的事很少有人會去做,但未來可以嘗試看看是不是對專案開發有幫助。

其他參考
Coding Dojo 程式設計道場
http://www.codingdojo.org/KataCatalogue/
Adventures in C#: The Bowling Game
https://ronjeffries.com/xprog/articles/acsbowling/
The Bowling Game Kata - 泰迪軟體Teddysoft
https://youtu.be/Om0co6xNNBI
(講解得不錯)
魚乾的筆記本: Bowling Game Kata
http://fishjerky.blogspot.com/2014/08/bowling-game-kata.html
Coding Dojo 規則介紹 + FizzBuzz Kata
https://www.slideshare.net/AgileCommunity/coding-dojo-38138724
Coding Dojo 初體驗(Android Code Club)+ PokerHands
https://carterchen247.medium.com/coding-dojo-%E5%88%9D%E9%AB%94%E9%A9%97-android-code-club-d3b4513cec70