vim + ctags 看程式碼好用的工具

http://ctags.sourceforge.net/

ctags是用vim寫程式的程式設計師一定要知道的套件
ctags會幫使用者建立一個tag (or index) 檔,方便游標可以在各個符號中快速移動
比如說你在trace一段source code時候發現一個function call
就可以利用快速鍵切換游標到function定義的地方
使用方法非常簡單

首先先在source code的最外層目錄輸入指令:

$ ctags -R *

這時候系統就會建立對應的tag檔
接著進去vim就會自動載入對應tag檔
你也可以在vim中輸入以下指令來載入對應的tag:

:set tags=/home/sway/src/tags

/home/sway/src/tags就是我tag存放的路徑
如果常用的話也可以把這行vim設定存放到~/.vimrc裡頭

之後當你游標移到function call上時,輸入:

【Ctrl】+【]】

就可以跳到function的定義
接著再輸入:

【Ctrl】+【t】

就可回到function call的地方

如果你沒有SourceInsight這類tool的話,vim + ctags也是可以幫你做一些簡單的trace
其他包括macro, class, namespace都可以用這種方法來trace

MacBook Pro 鍵盤維修方案經驗(STUDIO A 新竹中正維修中心)

這次維修的產品為2017 MacBook Pro 13’’

由於蘋果對於近幾代設計的蝴蝶式鍵盤提供免費維修的服務

因為本身非常幸運某一個按鍵按了常常沒反應 所以決定去維修

線上預約維修2019/12/07 晚上6:40拿去維修

服務人員 詢問是否有會員,因為之前有在studio a 買過耳機填過資料,所以報個手機所有資料都出來了 跟服務人員敘述mac的問題後 他說我的mac屬於蝴蝶式鍵盤召回方案 他將會依照此方案幫我送修 然後說7-14個工作天後才能拿到mac 沒有當場檢測就送我離開了

回家時接到他們的電話 說檢測後有以下問題

1. 鍵盤左半部有被含糖飲料滲入的跡象(是我之前不小心打翻玉米濃湯)

2. 電池膨脹問題(我因為長時間都接著電源線 沒有特別注意電池的問題 但是有發現放在桌子上會稍微搖晃 看起來真的是有膨脹導致下機殼不穩)

3. 由於含糖飲料滲入導致麥克風的線已生鏽 沒有辦法正常工作(這部分完全沒注意到 因為很久沒用mac的麥克風功能)

服務人員說 我的主機板有滲水且更換電池有可能導致主機板沒辦法正常工作

一開始我被唬得一愣一愣 想說乾脆都一起換一換好了 報價一萬三 後來仔細思考和朋友討論後 決定還是不更換主機板 再打電話過去跟他們確認情況 也跟服務人員表明說 就換鍵盤就好 不用額外更換主機板

隔天晚上想說來看看這家維修中心的評價如何

不查還好 一查整個心死一半 評價超低 我差點哭出來 早知道就直接送去101直營修 貪圖一時方便選鄰近的維修 網路上查詢如果決定不修還是要支付檢測費1200和訂維修材料的費用 一想到還要再付錢就只好祈禱維修順利

2019/12/12 下午4點 收到簡訊說已經維修完畢 可以去取貨 心裡一直祈禱千萬不要再額外收錢和維修順利成功 到現場非常多人在排隊 不論是等維修或取件 總之拿到之後看起來問題都有解決

這次蝴蝶式鍵盤召回方案直接把C件更換(Top case with battery) 所以我的電池也順便更換 更換後心得

1. 鍵盤真的都不卡了

2. 電池是顆全新的整個像是重生的感覺

3. 感覺喇叭的聲音有比較順

4. 維修期間比我預期的快

5. 報價時候真的要想清楚 不需要多花錢

How to find some pattern in the String?

find
string s("This_is_an_example_string");
if (s.find("This" != string::npos) { cout<<"Find!!"<<endl;}
else { cout<<"Not found!!"<<endl; }
#npos is a special cases for string (type:size_t), its indicates the pattern is not found in this string.

cout<<"Find the matched pattern from index 5"<<s.find("is", 5)<<endl;
rfind
cout<<"Reverse find the matched pattern position"<<s.rfind("is")<<endl;
find_first_of
cout<<"The first position of found pattern"<<s.find_first_of("is")<<endl;
#The functionality is exactly their name 
find_first_of
 string flag="a";
 int position=0;
 int i=1;
  while((position=s.find_first_of(flag,position))!=string::npos)
 {
   //position=s.find_first_of(flag,position);
   cout<<"position  "<<i<<" : "<<position<<endl;
   position++;
   i++;
 }
#find all the position of the matched pattern
 flag.find_first_not_of
 cout<<"The first position of not matched pattern"<<s.find_first_not_of("is")<<endl; 
 #The functionality is exactly their name  

C++ 變數的存放位置

畢竟我本身並不是CS出身,所以程式相關課程所學不多,大部分是自己網路上找。這次想跟大家談的內容是有關C++變數的存放位置。或許你會覺得只要宣告正確編譯過了就沒事,何需在意他的變數存放位置? 可是自從某天在網路上看到相關文章,讀懂之後會有一茅塞頓開的感覺。

 _________
| stack |
| heap |
|_________|
| .data |
|_________|
| .text |
|_________|

(之後補圖)

在程式執行過程中,處理器會幫我們分配一塊記憶體如上圖。這記憶體分為四大塊,會一直變動的stack 與 heap ,與固定不變的.data 與 .text

stack

區域變數(non-static)都會放在這裡,他會隨著function被call的順序一層一層"堆疊",所以每進入或離開一個scope,stack的堆疊方式就會依序改變。
有幾個東西要稍微提醒一下!

  1. stack他的資料處理型態是先進後出First-in, Last-out(FILO)。
  2. 由於區域變數指在此function被宣告,所以有作用域(scope)的限制,離開就消失,沒有特別宣告其他型態不可以被其他人所使用。
  3. 如果你有使用過GDB相關的debug軟體,當你發現bug時,程式它是一層一層被call進去,所以你在除錯時,你會一層一層往外看。你可以從他所提供的資訊感受到你function call進去的意思,有一種在剝洋蔥的感覺。
void f(){
int i; //non-stack var. (in stack)
static int i; //stack var. (in .data)
}

heap

這區塊裡的記憶體會隨著程式的執行而有所增減,主要存被"new"出來的動態變數。因為是user所要求的記憶體,程式會回傳一個指摽,所以回收的動作要自行處理,所以我們才說"自己new的記憶體自己delete!!!"
通常記憶體被delete之後會再讓該指標指向NULL(第0塊位置),這是為了讓系統之後可以回收此記憶體,就算記憶體被delete之後,指標依舊可以指向他。

new 有兩步驟
1. Memory allocation: 向 heap 要一塊記憶體
2. Initialization : 初始化,呼叫constructor

delete 也有兩步驟
1. clean up : 呼叫 deconstructor 清空記憶體
2. free : 歸回記憶體

如果呼叫 deconstructor 卻沒有歸還記憶體,之後delete 還要把指標指向NULL ,有關於C++的new/delete之後會再攥寫一篇敘述,在此就先打住。

.data

這塊區域主要存放Global跟static variable,此區塊的物件可以被任何地方存取,這塊記憶體會固定且一開始就規劃好。

.text

主要是存放程式碼的地方

來看看以下這個例子

void f(){
int* pa=new int;
}

所以記憶體他怎配置呢?

首先,pa是由我們宣告出來的"區域變數",所以pa會存放在stack (因為它是個區域變數),而我們new的是int,所以它存放在heap裡,透過指標把pa指過去heap裡的int。

const to pointer/pointer to const?

這絕非繞口令,在某些面試或考試題目中有時候回提到這類的題目,我研究了很久,終於搞懂了,在此把它分享給大家

先遞上例子

const char* p

char* const p

這兩個看起來很像兄弟但他們的意思完全不同,所以各位請由右邊往左邊唸,答案就出來了

const char* p = p is a pointer to const character

char* const p = p is a const pointer to character

指標所指的資料
const char* p 指標可以指別人所指的資料不能變
(const character)
char* const p 指標不可以指別人
(const pointer)
所指的資料可以變

該買哪一種?AirPods 1代與2代的分析與個人建議

乍暖還寒,蘋果公司也推出了新一代的AirPods。每次只要有新產品推出,大家一定會開始問到底該不該買最新版本的產品? 早買早享受,晚買享優惠!一直以來都是市場與消費者之間的準則。那這次新推出的AirPods到底有多少亮點,到底該不該買下去呢?讓我們繼續看下去~

這次除了無線耳機上的升級之外,蘋果也推出了無線充電盒。那我們先來分析無線耳機本身的差別

AirPods 1代AirPods 2代
處理器 W1 晶片 H1 晶片
嘿,siri 不支援 支援
充電盒可提供聆聽時間 24小時 24小時
充電15分鐘3 小時聆聽時間
1 小時的通話時間
3 小時聆聽時間
2 小時的通話時間
無線耳機充飽電一次 5 小時聆聽時間 5 小時聆聽時間
優點相對便宜 已啟用的裝置間切換速度快達 2 倍
通話的連接速度快達 1.5 倍
減少聲音延遲多達 30%

除了無線耳機的升級,也推出無線充電盒,那無線充電盒的優點就是可以無限充電,但不得不說,即使iphone8以上的手機都支援無線充電,但我還是完全沒用過,個人覺得酷訊大於實用度。

最後就是價錢上的差異,以下的價錢都是由官網所提供,二手或是其他平台能取得更便宜的價格則不列入比較,由於這次的AirPods 2 代 可以選擇是否搭配無線充電盒,所以組合上有更多選擇。

AirPods 1 代 AirPods 2 代
搭配充電盒 NT$5,290 以下
NT$5,290
搭配無線充電盒 無 AirPods
加夠NT$2,690
NT$6,490

由表格可得知,最便宜的當然就是買一代的AirPods,像是好市多或是其他通路都可以買到更便宜。

懶人包

最便宜買法: 買 AirPods 1 代
最推薦買法: 買 AirPods 2 代 搭配充電盒 (這時候可以去比較刷卡回饋金來得到最多折扣) 最奢華買法: 買AirPods 2 代 搭配充電盒