本周為了幫二哥準備 APCS 與資訊能力考試, Python, 機器學習, Fintech, MicroPython 這些研究項目全都停下來專心在 C 語言與演算法上面. 最近也在研究自己的八字命盤, 日元為己土, 屬偏財格, 興趣多元無法專致一處, 確實與心性若合符節. 命者天性雖不可改, 但只要能認識弱點採取行動, 即有機會譜寫不一樣的篇章, 運者運作也.
這週二聽聞水某的三叔過世, 於今日出殯, 水某生肖犯沖無法前往, 我又要載二哥上學, 由於時辰甚早我趕不上, 爸說他可以前去弔唁, 但岳母說無公祭僅家祭而已, 儀典簡單, 因此來電說不需前往.
最近 CNN 晨間新聞幾乎每天都在報火山爆發, 岩漿四溢造成居民逃離家園避難; 這幾天瓜地馬拉也是如此, 似乎地下的怒火已按捺不住, 狂暴噴發, 不知會不會引起地震? 地下在噴火, 地上也不遑多讓, 最近天氣真是熱斃了, 我每個周日下午都到西角的冰店去買兩盒冰帶回高雄, 但因為會考結束後她都跟老師請事假在家避暑, 僅周三與周五到校, 不到兩天冰都被菁菁吃光光.
近一年來所訂雜誌較少有時間看, 上期還沒拆封, 匆匆一周已過新的一期又來. 上週 iPad 2 升版後下載了最近幾期財訊與今周刊, 學會了截圖存檔方法, 以後看到好文章就可以抓下來保存了. 重點是必須在周日之前看完主要文章, 不要拖到下周四, 才不會積一堆舊雜誌.
2018年6月5日 星期二
資策會的 TensorFlow 與 Keras 深度學習班
AI 時代來臨使得熟悉機器學習的工程師炙手可熱, 業界需求甚殷, 為因應這個 AI/ML everwhere 的趨勢. 高雄資策會推出 TensorFlow 與 Keras 學習實作課程, 實在是南部學習者的福音 :
# http://www.iiiedu.org.tw/south/TENSORFLOW_AI.htm
此課程預定 7/7~7/8 兩天 14 小時, 學費 NT$12000, 於 6/20 前完成報名及繳費可享早鳥優惠價 NT$8000.
# http://www.iiiedu.org.tw/south/TENSORFLOW_AI.htm
此課程預定 7/7~7/8 兩天 14 小時, 學費 NT$12000, 於 6/20 前完成報名及繳費可享早鳥優惠價 NT$8000.
2018年6月4日 星期一
簡要的 MicroPython 簡報
今天在網路上找到一個很扼要的 MicroPython 簡報 :
# https://todayispotato.github.io/micropython-talk/#/
原來 MicroPython 的經費一部分來自歐洲航太總署資助, 目前有一個專職開發者, 兩個核心的非專職協助者.
# https://todayispotato.github.io/micropython-talk/#/
原來 MicroPython 的經費一部分來自歐洲航太總署資助, 目前有一個專職開發者, 兩個核心的非專職協助者.
文星電子的 UART 介面 LoRa 模組
今天在露天找到這款 UART 介面的 LoRa 模組, 係台北文星電子公司今年推出的新產品, 內建陶瓷天線, 使用 AT 指令即可操控 LoRa 遠距通訊 (內建 MCU) :
# LoRa RF展頻模組-物聯網IOT低功耗長距離(內含MCU) 433MHz $250
單片 250 元, 這個價格目前蠻有競爭力的, 做實驗需買一對 250*2=500, 加運費 100 共 600 元, 含運平均一片 300 元, 大量採購 1000 片每片 165 元.
該公司目前有四款 LoRa 模組產品 :
# LoRa擴頻模組物聯網超低功耗長距離通信RF模組無網LORA 433MHz $175
不過這款好像是 SPI 介面.
UART 測試程式參考 :
# Jswoon/UNO + UM402 (SX1278 or SX1276, 433MHz, UART)
# LoRa RF展頻模組-物聯網IOT低功耗長距離(內含MCU) 433MHz $250
單片 250 元, 這個價格目前蠻有競爭力的, 做實驗需買一對 250*2=500, 加運費 100 共 600 元, 含運平均一片 300 元, 大量採購 1000 片每片 165 元.
該公司目前有四款 LoRa 模組產品 :
- TRW-LORA20 LoRa 通訊模組
- TRW-LORA20UART LoRa 通訊模組
- TRW-LORA20UARTC LoRa 通訊模組
- TRW-LORA30UART LoRa 通訊模組
# LoRa擴頻模組物聯網超低功耗長距離通信RF模組無網LORA 433MHz $175
不過這款好像是 SPI 介面.
UART 測試程式參考 :
# Jswoon/UNO + UM402 (SX1278 or SX1276, 433MHz, UART)
2018年6月3日 星期日
好書 : 動畫圖解資料結構第二版
最近因為要幫二哥複習 APCS 的 C 語言, 練習二元樹與圖的部分, 在市圖找到下面這本編得超棒的資料結構書籍, 全書詳細圖解個資料結構之原理以及 C, C++, Java, VB, VC 等語言之實作, 書附光碟還有動畫與 CD-ROM 電子書, 可說是 100 分的好書.
# 上奇-動畫圖解資料結構第二版-李春雄
雖然我主要的 Coding 重心已經轉移到 Python, 但是在追求效能時還是必須用 C 語言撰寫底層 API 給 Python 用, 總之, C 語言永遠不會被淘汰.
# 上奇-動畫圖解資料結構第二版-李春雄
Source : 博客來
雖然我主要的 Coding 重心已經轉移到 Python, 但是在追求效能時還是必須用 C 語言撰寫底層 API 給 Python 用, 總之, C 語言永遠不會被淘汰.
2018年6月1日 星期五
如何在 Dev C++ 中設定預設程式碼
最近使用 Dev C++ 編譯器測試 C 語言時, 覺得每次都要敲前面的 include 以及 main() 等等很麻煩, 可不可以開啟新檔案時就自動帶出 C 程式的基本架構呢? 可以的, 參考下面這個網頁 :
# 第0章 Dev C++的使用
設定位置在 "工具\編輯器選項\程式碼\預設程式碼" 頁籤, 輸入下列 C 程式基本架構作為預設程式碼 :
#include <stdio.h>
#include <stdlib.h>
int main(void) {
//coding here
system("pause");
return 0;
}
對於 Dev C++ 而言不需要 system("pause") 來停住視窗, 因此也不需匯入 stdlib, 因為 Dev C++ 已經在背後幫我們搞定了. 注意必須勾選上方 "開啟新的空白檔案時插入下列程式碼", 否則無作用 :
這樣開啟新的原始碼檔案時, 預設程式碼就會自動帶進來了 :
此外還要取消 Tab 設定, 這樣程式碼複製到記事本或部落格時, 格式才不會亂掉, 設定位置在 "工具\編輯器選項\一般" 頁籤左下角 :
另外, Dev-C++ 預設字型太小, 可在 "工具\編輯器選項\字型" 中變更 :
工欲善其事, 必先利其器, 這樣 Dev-C++ 就很好用了.
# 第0章 Dev C++的使用
設定位置在 "工具\編輯器選項\程式碼\預設程式碼" 頁籤, 輸入下列 C 程式基本架構作為預設程式碼 :
#include <stdio.h>
#include <stdlib.h>
int main(void) {
//coding here
system("pause");
return 0;
}
對於 Dev C++ 而言不需要 system("pause") 來停住視窗, 因此也不需匯入 stdlib, 因為 Dev C++ 已經在背後幫我們搞定了. 注意必須勾選上方 "開啟新的空白檔案時插入下列程式碼", 否則無作用 :
這樣開啟新的原始碼檔案時, 預設程式碼就會自動帶進來了 :
此外還要取消 Tab 設定, 這樣程式碼複製到記事本或部落格時, 格式才不會亂掉, 設定位置在 "工具\編輯器選項\一般" 頁籤左下角 :
另外, Dev-C++ 預設字型太小, 可在 "工具\編輯器選項\字型" 中變更 :
工欲善其事, 必先利其器, 這樣 Dev-C++ 就很好用了.
2018年5月30日 星期三
C 語言學習筆記 : 字串函數測試
C 語言的字串處理需匯入 string.h 函式庫, 其中常用的函式如下 :
注意, 傳回值為位址的函數如 strrev() 等必須宣告一個 char 指標來儲存新字串之位址, 不可用 char 陣列. 參考 :
# https://zh.wikipedia.org/wiki/String.h
測試 1 : strlen(str)
此函數會傳回傳入字串 s1 的字元個數 (整數), 下列程式分別使用 scanf() 與 gets() 讀取輸入字串, scanf() 遇到空格就會停止讀取, 但 gets() 則不會, 會一直讀到跳行為止 (含); 除此之外 scanf() 不會讀入跳行字元 \n, 但 gets() 則會. 程式如下 :
#include <stdio.h>
#include <string.h>
int main(void) {
char str[256];
printf("請輸入字串\n"); //輸入 "Hello World"
scanf("%s", str); //用 scanf() 讀取會被空格中斷
printf("讀入字串=%s\n", str); //輸出 "Hello"
printf("字串長度=%d 個字元\n", strlen(str)); //輸出 5
gets(str); //用 gets() 讀取不會被空格中斷
printf("讀入字串=%s\n", str); //輸出 " World"
printf("字串長度=%d 個字元\n", strlen(str)); //輸出 6 (含前面一空格)
return 0;
}
執行結果如下 :
請輸入字串
Hello World
讀入字串=Hello
字串長度=5 個字元
讀入字串= World (注意, W 前面有一個空格)
字串長度=6 個字元
--------------------------------
Process exited after 9.066 seconds with return value 0
請按任意鍵繼續 . . .
測試 2 : strrev(str)
此函數會將傳入字串反轉, 並將反轉後之新字串開頭位址傳回, 故須定義一個 char 指標來儲存此位址. 程式如下 :
#include <stdio.h>
#include <string.h>
int main(void) {
char str[256], *nstr; //分別儲存原始字串與反轉後之字串
printf("請輸入字串\n");
gets(str);
printf("讀入字串=%s\n", str);
nstr=strrev(str); //須用 char 指標來儲存位址
printf("反轉字串=%s\n", nstr);
return 0;
}
執行結果 :
請輸入字串
Hello World
讀入字串=Hello World
反轉字串=dlroW olleH
--------------------------------
Process exited after 11.87 seconds with return value 0
請按任意鍵繼續 . . .
測試 3 : strupr(str)
此函數會將傳入字串之全部字元轉成大寫, 傳回此新字串之開頭位址, 因此必須定義一個 char 指標來儲存. 範例如下 :
#include <stdio.h>
#include <string.h>
int main(void) {
char str[256], *nstr; //分別儲存原始字串與大寫後之字串
printf("請輸入字串\n");
gets(str);
printf("讀入字串=%s\n", str);
nstr=strupr(str); //須用 char 指標來儲存位址
printf("大寫字串=%s\n", nstr);
return 0;
}
執行結果 :
請輸入字串
hello world
讀入字串=hello world
大寫字串=HELLO WORLD
--------------------------------
Process exited after 9.636 seconds with return value 0
請按任意鍵繼續 . . .
測試 4 : strlwr(str)
此函數會將傳入字串之全部字元轉成小寫, 傳回此新字串之開頭位址, 因此必須定義一個 char 指標來儲存. 範例如下 :
#include <stdio.h>
#include <string.h>
int main(void) {
char str[256], *nstr; //分別儲存原始字串與大寫後之字串
printf("請輸入字串\n");
gets(str);
printf("讀入字串=%s\n", str);
nstr=strlwr(str); //須用 char 指標來儲存位址
printf("小寫字串=%s\n", nstr);
return 0;
}
執行結果 :
請輸入字串
HELLO WORLD
讀入字串=HELLO WORLD
小寫字串=hello world
--------------------------------
Process exited after 7.496 seconds with return value 0
請按任意鍵繼續 . . .
測試 5 : strchr(str, ch)
此函數會從字串 str 頭開始尋找字元 ch, 找到的話傳回第一次出現的位址, 否則傳回 NULL. 將傳回位址減掉字串 str 之位址即為第一次出現的 ch 在 str 之索引, 例如 :
#include <stdio.h>
#include <string.h>
int main(void) {
char str[]="Hello World";
char *ptr;
printf("字串內容 %s\n", str);
for (int i=0; i<strlen(str); i++) {
printf("字元 '%c' 位址=%p\n", str[i], &str[i]);
}
ptr=strchr(str, 'o');
printf("第一個 o 出現位置之位址=%p\n", ptr);
printf("第一個 o 出現位置之索引=%d\n", ptr-str);
return 0;
}
執行結果 :
測試 6 : strrchr(str, ch)
執行結果 :
字串內容 Hello World
字元 'H' 位址=000000000062FE20
字元 'e' 位址=000000000062FE21
字元 'l' 位址=000000000062FE22
字元 'l' 位址=000000000062FE23
字元 'o' 位址=000000000062FE24
字元 ' ' 位址=000000000062FE25
字元 'W' 位址=000000000062FE26
字元 'o' 位址=000000000062FE27
字元 'r' 位址=000000000062FE28
字元 'l' 位址=000000000062FE29
字元 'd' 位址=000000000062FE2A
第一個 o 出現位置之位址=000000000062FE27
第一個 o 出現位置之索引=7
--------------------------------
Process exited after 0.08958 seconds with return value 0
請按任意鍵繼續 . . .
測試 7 : strspn(s1, s2)
#include <stdio.h>
#include <string.h>
int main(void) {
char str1[]="Hello World";
char str2[]="Hello Tony";
size_t loc=strspn(str1, str2);
printf("第一個字元不同位置之索引=%d\n", loc);
return 0;
}
執行結果 :
第一個字元不同位置之索引=6
--------------------------------
Process exited after 0.09996 seconds with return value 0
請按任意鍵繼續 . . .
測試 8 : strcspn(s1, s2)
#include <stdio.h>
#include <string.h>
int main(void) {
char str1[]="7777B333";
char str2[]="6666B222";
size_t loc=strcspn(str1, str2);
printf("第一個字元相同位置之索引=%d\n", loc);
return 0;
}
執行結果 :
第一個字元相同位置之索引=4
--------------------------------
Process exited after 0.08926 seconds with return value 0
請按任意鍵繼續 . . .
測試 9 : strstr(heystack, needle)
此函數會在 heystack 字串中從頭尋找第一個符合之子字串 needle, 找到的話將此起始位址傳回, 否則傳回 NULL. 顯示傳回位址所指內容即是此起始位置之後之子字串. 將傳回位址減掉 heystack 字串開頭位址即是符合字串在 heystack 中之索引.
#include <stdio.h>
#include <string.h>
int main(void) {
char str[]="Hello World";
char *ptr;
printf("字串內容 %s\n", str);
for (int i=0; i<strlen(str); i++) { //顯示字串中各字元位址
printf("字元 '%c' 位址=%p\n", str[i], &str[i]);
}
ptr=strstr(str, "o");
printf("字串開頭位址=%p\n", str);
printf("第一個 o 出現位置之子字串=%s\n", ptr);
printf("第一個 o 出現位置之子字串位址=%p\n", ptr);
printf("第一個 o 出現位置之索引=%d\n", ptr-str);
return 0;
}
執行結果 :
字串內容 Hello World
字元 'H' 位址=000000000062FE20
字元 'e' 位址=000000000062FE21
字元 'l' 位址=000000000062FE22
字元 'l' 位址=000000000062FE23
字元 'o' 位址=000000000062FE24
字元 ' ' 位址=000000000062FE25
字元 'W' 位址=000000000062FE26
字元 'o' 位址=000000000062FE27
字元 'r' 位址=000000000062FE28
字元 'l' 位址=000000000062FE29
字元 'd' 位址=000000000062FE2A
字串開頭位址=000000000062FE20
第一個 o 出現位置之子字串=o World
第一個 o 出現位置之子字串位址=000000000062FE24
第一個 o 出現位置之索引=4
--------------------------------
Process exited after 0.1082 seconds with return value 0
請按任意鍵繼續 . . .
測試 10 : strcpy(dest, source)
此函數會將第二參數來源字串 source 的內容複製到第一參數目的字串 dest, 並傳回目的字串的位址.
#include <stdio.h>
#include <string.h>
int main(void) {
char source[]="Hello World";
char dest[20]={};
printf("來源字串 '%s'\n", source);
printf("目的地字串 '%s'\n", dest);
printf("來源字串位址 %p\n", source); //顯示來源字串位址
printf("目的地字串位址 %p\n", dest); //顯示目的地字串位址
strcpy(dest, source); //傳回 dest 字串之位址
printf("目的字串 '%s'\n", dest);
printf("目的地字串位址 %p\n", strcpy(dest, source)); //顯示目的地字串位址
return 0;
}
執行結果 :
來源字串 'Hello World'
目的地字串 ''
來源字串位址 000000000022FE40
目的地字串位址 000000000022FE20
目的字串 'Hello World'
目的地字串位址 000000000022FE20
--------------------------------
Process exited with return value 0
Press any key to continue . . .
測試 11 : strncpy(dest, source, n)
此函數會將第二參數來源字串 source 的內容複製 n 個字元到第一參數目的字串 dest, 並傳回目的字串 dest 的位址.
#include <stdio.h>
#include <string.h>
int main(void) {
char source[]="Hello World";
char dest[20]={};
printf("來源字串 '%s'\n", source);
printf("目的地字串 '%s'\n", dest);
printf("來源字串位址 %p\n", source); //顯示來源字串位址
printf("目的地字串位址 %p\n", dest); //顯示目的地字串位址
strncpy(dest, source, 7); //傳回 dest 字串之位址 (複製 7 個字元)
printf("目的字串 '%s'\n", dest);
printf("目的地字串位址 %p\n", strcpy(dest, source, n)); //顯示目的地字串位址
return 0;
}
執行結果 :
測試 12 : strcat(dest, source)
此函數會將字串 source 的內容串接到字串 dest 後面並傳回 dest 的位址 (指標), 例如 :
#include <stdio.h>
#include <string.h>
int main(void) {
char str1[20]="Hello";
char str2[20]=" World";
printf("'Hello' 位址=%p\n", str1); //顯示第一個字串位址
printf("' World' 位址=%p\n", str2); //顯示第二個字串位址
printf("strcat('Hello', ' World')=%s\n", strcat(str1, str2)); //串接後以第一個字串為結果
printf("strcat('Hello', ' World') 位址=%p\n", strcat(str1, str2)); //顯示第一個字串位址
return 0;
}
此程式中先顯示兩個串接字串在記憶體中之位址, strcat(dest, source) 函數以第一個字串作為結果字串, 因此傳回值為第一個字串之位址.
執行結果 :
'Hello' 位址=000000000062FE30
' World' 位址=000000000062FE10
strcat('Hello', ' World')=Hello World
strcat('Hello', ' World') 位址=000000000062FE30 //串接後傳回第一個字串位址
--------------------------------
Process exited after 0.08643 seconds with return value 0
請按任意鍵繼續 . . .
測試 13 : strcmp(s1, s2)
#include <stdio.h>
#include <string.h>
int main(void) {
char str1[20]="Hello";
char str2[20]="hello";
printf("strcmp('Hello', 'Hello')=%d\n", strcmp(str1, str1));
printf("strcmp('Hello', 'hello')=%d\n", strcmp(str1, str2));
printf("strcmp('hello', 'Hello')=%d\n", strcmp(str2, str1));
return 0;
}
執行結果 :
strcmp('Hello', 'Hello')=0
strcmp('Hello', 'hello')=-1
strcmp('hello', 'Hello')=1
--------------------------------
Process exited after 0.09408 seconds with return value 0
請按任意鍵繼續 . . .
可見由於 H 的 ASCII 編碼數值 (72) 小於 h 的編碼 (104), 因此 strcmp('Hello', 'hello') 傳回 -1.
測試 14 : strtok(str, delim)
此函數會以字串 delim 為分界符號拆解字串 str, 傳回值為分界符前面之子字串, 若要全部拆解須用遞迴方式, 但遞迴時第一參數必須傳入 NULL, 例如 :
#include <stdio.h>
#include <string.h>
int main(void) {
char str[]="11:22:33:44:55:66"; //待拆解字串
char delim[]=":"; //分界符
char *tok; //儲存分界符前之子字串
printf("待拆解字串 %s\n", str);
printf("分界字串 %s\n", delim);
tok=strtok(str, delim); //第一次拆解
while (tok != NULL) { //遞迴拆解
printf("%s\n", tok); //輸出分界符前之子字串
tok=strtok(NULL, delim); //第二次拆解傳入 NULL
}
return 0;
}
執行結果 :
待拆解字串 11:22:33:44:55:66
分界字串 :
11
22
33
44
55
66
--------------------------------
Process exited with return value 0
Press any key to continue . . .
遞迴迴圈內的 strtok() 第一參數若傳入待拆解字串 str 會不斷地拆解第一個子字串而形成無窮迴圈, 務必要傳入 NULL, 參考 :
# 切割字串函數:strtok, Network mac address 分割
測試 15 : memset(str, ch, n)
此函數會以 n 個 ch 字元填入 str 字串中, 傳回值為 str 字串之位址 (指標). 在宣告字元陣列時可用字串 literal 例如 "0000000000" 或 {'0', '0', .... '0'} 初始化, 但是如果陣列很大的話就必須用 memset() 了. 例如 :
#include <stdio.h>
#include <string.h>
int main(void) {
char str[11];
memset(str, '0', 10); //填入 10 個 '0'
str[10]='\0'; //字串結尾字元
printf("%s\n", str);
for (int i=0; i<strlen(str); i++) {
printf("字元 '%c' 位址=%p\n", str[i], &str[i]);
}
return 0;
}
執行結果 :
0000000000
字元 '0' 位址=000000000022FE30
字元 '0' 位址=000000000022FE31
字元 '0' 位址=000000000022FE32
字元 '0' 位址=000000000022FE33
字元 '0' 位址=000000000022FE34
字元 '0' 位址=000000000022FE35
字元 '0' 位址=000000000022FE36
字元 '0' 位址=000000000022FE37
字元 '0' 位址=000000000022FE38
字元 '0' 位址=000000000022FE39
--------------------------------
Process exited with return value 0
Press any key to continue . . .
參考 :
# http://www.cplusplus.com/reference/cstring/memset/
# 字串比較、搜尋
# C語言字符串函數大全
# [C&++] 字串整數轉換
# C++字符串格式化 sprintf、printf
# [C/C++] cstring (string.h) 搜尋函式:strstr, strchr
# [C/C++] 切割字串函數:strtok, Network mac address 分割
# C語言編譯器哪個好?6款好用的C語言編譯器推薦
| 函數 | 說明 |
| strlen(str) | 傳回字串 str 的長度 (字元個數) |
| strrev(str) | 將字串 str 反轉後傳回新字串之位址 |
| strupr(str) | 將字串 str 轉成大寫後傳回新字串之位址 |
| strlwr(str) | 將字串 str 轉成小後傳回新字串之位址 |
| strchr(str, ch) | 從字串 str 頭開始尋找字元 ch, 傳回第一次出現的位址 |
| strrchr(str, ch) | 從字串 str 尾開始尋找字元 ch, 傳回第一次出現的位址 |
| strspn(s1, s2) | 比對兩個字串, 傳回第一次字元不同位置之索引 |
| strcspn(s1, s2) | 比對兩個字串, 傳回第一次字元相同位置之索引 |
| strstr(heystack, needle) | 從字串 needle 頭開始尋找字串 heystack, 傳回第一次出現的位址 |
| strcpy(dest, source) | 將字串 source 的內容複製到字串 dest, 傳回目的字串 dest 位址 |
| strncpy(dest, source, n) | 將字串 source 的內容複製 n 個字元到字串 dest, 傳回字串 dest 位址 |
| strcat(dest, source) | 將字串 source 的內容串接到字串 dest 後面並傳回 dest 的位址 |
| strcmp(s1, s2) | 比較字串 s1 與 s2 的內容, 相等傳回 0, s1 > s2 傳回正數, 否則負數 |
| strtok(str, delim) | 將字串 str 以 delim 字串為分界符遞迴切割為子字串傳回 |
| memset(str, ch, n) | 以 n 個 ch 字元填入字串 str 中, 傳回 str 位址 |
注意, 傳回值為位址的函數如 strrev() 等必須宣告一個 char 指標來儲存新字串之位址, 不可用 char 陣列. 參考 :
# https://zh.wikipedia.org/wiki/String.h
測試 1 : strlen(str)
此函數會傳回傳入字串 s1 的字元個數 (整數), 下列程式分別使用 scanf() 與 gets() 讀取輸入字串, scanf() 遇到空格就會停止讀取, 但 gets() 則不會, 會一直讀到跳行為止 (含); 除此之外 scanf() 不會讀入跳行字元 \n, 但 gets() 則會. 程式如下 :
#include <stdio.h>
#include <string.h>
int main(void) {
char str[256];
printf("請輸入字串\n"); //輸入 "Hello World"
scanf("%s", str); //用 scanf() 讀取會被空格中斷
printf("讀入字串=%s\n", str); //輸出 "Hello"
printf("字串長度=%d 個字元\n", strlen(str)); //輸出 5
gets(str); //用 gets() 讀取不會被空格中斷
printf("讀入字串=%s\n", str); //輸出 " World"
printf("字串長度=%d 個字元\n", strlen(str)); //輸出 6 (含前面一空格)
return 0;
}
執行結果如下 :
請輸入字串
Hello World
讀入字串=Hello
字串長度=5 個字元
讀入字串= World (注意, W 前面有一個空格)
字串長度=6 個字元
--------------------------------
Process exited after 9.066 seconds with return value 0
請按任意鍵繼續 . . .
測試 2 : strrev(str)
此函數會將傳入字串反轉, 並將反轉後之新字串開頭位址傳回, 故須定義一個 char 指標來儲存此位址. 程式如下 :
#include <stdio.h>
#include <string.h>
int main(void) {
char str[256], *nstr; //分別儲存原始字串與反轉後之字串
printf("請輸入字串\n");
gets(str);
printf("讀入字串=%s\n", str);
nstr=strrev(str); //須用 char 指標來儲存位址
printf("反轉字串=%s\n", nstr);
return 0;
}
執行結果 :
請輸入字串
Hello World
讀入字串=Hello World
反轉字串=dlroW olleH
--------------------------------
Process exited after 11.87 seconds with return value 0
請按任意鍵繼續 . . .
測試 3 : strupr(str)
此函數會將傳入字串之全部字元轉成大寫, 傳回此新字串之開頭位址, 因此必須定義一個 char 指標來儲存. 範例如下 :
#include <stdio.h>
#include <string.h>
int main(void) {
char str[256], *nstr; //分別儲存原始字串與大寫後之字串
printf("請輸入字串\n");
gets(str);
printf("讀入字串=%s\n", str);
nstr=strupr(str); //須用 char 指標來儲存位址
printf("大寫字串=%s\n", nstr);
return 0;
}
執行結果 :
請輸入字串
hello world
讀入字串=hello world
大寫字串=HELLO WORLD
--------------------------------
Process exited after 9.636 seconds with return value 0
請按任意鍵繼續 . . .
測試 4 : strlwr(str)
此函數會將傳入字串之全部字元轉成小寫, 傳回此新字串之開頭位址, 因此必須定義一個 char 指標來儲存. 範例如下 :
#include <stdio.h>
#include <string.h>
int main(void) {
char str[256], *nstr; //分別儲存原始字串與大寫後之字串
printf("請輸入字串\n");
gets(str);
printf("讀入字串=%s\n", str);
nstr=strlwr(str); //須用 char 指標來儲存位址
printf("小寫字串=%s\n", nstr);
return 0;
}
執行結果 :
請輸入字串
HELLO WORLD
讀入字串=HELLO WORLD
小寫字串=hello world
--------------------------------
Process exited after 7.496 seconds with return value 0
請按任意鍵繼續 . . .
測試 5 : strchr(str, ch)
此函數會從字串 str 頭開始尋找字元 ch, 找到的話傳回第一次出現的位址, 否則傳回 NULL. 將傳回位址減掉字串 str 之位址即為第一次出現的 ch 在 str 之索引, 例如 :
#include <stdio.h>
#include <string.h>
int main(void) {
char str[]="Hello World";
char *ptr;
printf("字串內容 %s\n", str);
for (int i=0; i<strlen(str); i++) {
printf("字元 '%c' 位址=%p\n", str[i], &str[i]);
}
ptr=strchr(str, 'o');
printf("第一個 o 出現位置之位址=%p\n", ptr);
printf("第一個 o 出現位置之索引=%d\n", ptr-str);
return 0;
}
執行結果 :
字串內容 Hello World
字元 'H' 位址=000000000062FE20
字元 'e' 位址=000000000062FE21
字元 'l' 位址=000000000062FE22
字元 'l' 位址=000000000062FE23
字元 'o' 位址=000000000062FE24
字元 ' ' 位址=000000000062FE25
字元 'W' 位址=000000000062FE26
字元 'o' 位址=000000000062FE27
字元 'r' 位址=000000000062FE28
字元 'l' 位址=000000000062FE29
字元 'd' 位址=000000000062FE2A
第一個 o 出現位置之位址=000000000062FE24
第一個 o 出現位置之索引=4
--------------------------------
Process exited after 0.07511 seconds with return value 0
請按任意鍵繼續 . . .
測試 6 : strrchr(str, ch)
此函數會從字串 str 尾開始尋找字元 ch, 找到的話傳回第一次出現的位址, 否則傳回 NULL. 將傳回位址減掉字串 str 之位址即為第一次出現的 ch 在 str 之索引, 例如 :
#include <stdio.h>
#include <string.h>
int main(void) {
char str[]="Hello World";
char *ptr;
printf("字串內容 %s\n", str);
for (int i=0; i<strlen(str); i++) {
printf("字元 '%c' 位址=%p\n", str[i], &str[i]);
}
ptr=strrchr(str, 'o');
printf("第一個 o 出現位置之位址=%p\n", ptr);
printf("第一個 o 出現位置之索引=%d\n", ptr-str);
return 0;
}
#include <string.h>
int main(void) {
char str[]="Hello World";
char *ptr;
printf("字串內容 %s\n", str);
for (int i=0; i<strlen(str); i++) {
printf("字元 '%c' 位址=%p\n", str[i], &str[i]);
}
ptr=strrchr(str, 'o');
printf("第一個 o 出現位置之位址=%p\n", ptr);
printf("第一個 o 出現位置之索引=%d\n", ptr-str);
return 0;
}
字串內容 Hello World
字元 'H' 位址=000000000062FE20
字元 'e' 位址=000000000062FE21
字元 'l' 位址=000000000062FE22
字元 'l' 位址=000000000062FE23
字元 'o' 位址=000000000062FE24
字元 ' ' 位址=000000000062FE25
字元 'W' 位址=000000000062FE26
字元 'o' 位址=000000000062FE27
字元 'r' 位址=000000000062FE28
字元 'l' 位址=000000000062FE29
字元 'd' 位址=000000000062FE2A
第一個 o 出現位置之位址=000000000062FE27
第一個 o 出現位置之索引=7
--------------------------------
Process exited after 0.08958 seconds with return value 0
請按任意鍵繼續 . . .
測試 7 : strspn(s1, s2)
#include <stdio.h>
#include <string.h>
int main(void) {
char str1[]="Hello World";
char str2[]="Hello Tony";
size_t loc=strspn(str1, str2);
printf("第一個字元不同位置之索引=%d\n", loc);
return 0;
}
執行結果 :
第一個字元不同位置之索引=6
--------------------------------
Process exited after 0.09996 seconds with return value 0
請按任意鍵繼續 . . .
測試 8 : strcspn(s1, s2)
#include <stdio.h>
#include <string.h>
int main(void) {
char str1[]="7777B333";
char str2[]="6666B222";
size_t loc=strcspn(str1, str2);
printf("第一個字元相同位置之索引=%d\n", loc);
return 0;
}
執行結果 :
第一個字元相同位置之索引=4
--------------------------------
Process exited after 0.08926 seconds with return value 0
請按任意鍵繼續 . . .
測試 9 : strstr(heystack, needle)
此函數會在 heystack 字串中從頭尋找第一個符合之子字串 needle, 找到的話將此起始位址傳回, 否則傳回 NULL. 顯示傳回位址所指內容即是此起始位置之後之子字串. 將傳回位址減掉 heystack 字串開頭位址即是符合字串在 heystack 中之索引.
#include <stdio.h>
#include <string.h>
char str[]="Hello World";
char *ptr;
printf("字串內容 %s\n", str);
for (int i=0; i<strlen(str); i++) { //顯示字串中各字元位址
printf("字元 '%c' 位址=%p\n", str[i], &str[i]);
}
ptr=strstr(str, "o");
printf("字串開頭位址=%p\n", str);
printf("第一個 o 出現位置之子字串=%s\n", ptr);
printf("第一個 o 出現位置之子字串位址=%p\n", ptr);
printf("第一個 o 出現位置之索引=%d\n", ptr-str);
return 0;
}
執行結果 :
字串內容 Hello World
字元 'H' 位址=000000000062FE20
字元 'e' 位址=000000000062FE21
字元 'l' 位址=000000000062FE22
字元 'l' 位址=000000000062FE23
字元 'o' 位址=000000000062FE24
字元 ' ' 位址=000000000062FE25
字元 'W' 位址=000000000062FE26
字元 'o' 位址=000000000062FE27
字元 'r' 位址=000000000062FE28
字元 'l' 位址=000000000062FE29
字元 'd' 位址=000000000062FE2A
字串開頭位址=000000000062FE20
第一個 o 出現位置之子字串=o World
第一個 o 出現位置之子字串位址=000000000062FE24
第一個 o 出現位置之索引=4
--------------------------------
Process exited after 0.1082 seconds with return value 0
請按任意鍵繼續 . . .
測試 10 : strcpy(dest, source)
此函數會將第二參數來源字串 source 的內容複製到第一參數目的字串 dest, 並傳回目的字串的位址.
#include <stdio.h>
#include <string.h>
int main(void) {
char source[]="Hello World";
char dest[20]={};
printf("來源字串 '%s'\n", source);
printf("目的地字串 '%s'\n", dest);
printf("來源字串位址 %p\n", source); //顯示來源字串位址
printf("目的地字串位址 %p\n", dest); //顯示目的地字串位址
strcpy(dest, source); //傳回 dest 字串之位址
printf("目的字串 '%s'\n", dest);
printf("目的地字串位址 %p\n", strcpy(dest, source)); //顯示目的地字串位址
return 0;
}
執行結果 :
來源字串 'Hello World'
目的地字串 ''
來源字串位址 000000000022FE40
目的地字串位址 000000000022FE20
目的字串 'Hello World'
目的地字串位址 000000000022FE20
--------------------------------
Process exited with return value 0
Press any key to continue . . .
測試 11 : strncpy(dest, source, n)
此函數會將第二參數來源字串 source 的內容複製 n 個字元到第一參數目的字串 dest, 並傳回目的字串 dest 的位址.
#include <stdio.h>
#include <string.h>
int main(void) {
char source[]="Hello World";
char dest[20]={};
printf("來源字串 '%s'\n", source);
printf("目的地字串 '%s'\n", dest);
printf("來源字串位址 %p\n", source); //顯示來源字串位址
printf("目的地字串位址 %p\n", dest); //顯示目的地字串位址
strncpy(dest, source, 7); //傳回 dest 字串之位址 (複製 7 個字元)
printf("目的字串 '%s'\n", dest);
printf("目的地字串位址 %p\n", strcpy(dest, source, n)); //顯示目的地字串位址
return 0;
}
執行結果 :
來源字串 'Hello World'
目的地字串 ''
來源字串位址 000000000062FE40
目的地字串位址 000000000062FE20
目的字串 'Hello W'
目的地字串位址 000000000062FE20
--------------------------------
Process exited after 0.09536 seconds with return value 0
請按任意鍵繼續 . . .
目的地字串 ''
來源字串位址 000000000062FE40
目的地字串位址 000000000062FE20
目的字串 'Hello W'
目的地字串位址 000000000062FE20
--------------------------------
Process exited after 0.09536 seconds with return value 0
請按任意鍵繼續 . . .
測試 12 : strcat(dest, source)
此函數會將字串 source 的內容串接到字串 dest 後面並傳回 dest 的位址 (指標), 例如 :
#include <stdio.h>
#include <string.h>
int main(void) {
char str1[20]="Hello";
char str2[20]=" World";
printf("'Hello' 位址=%p\n", str1); //顯示第一個字串位址
printf("' World' 位址=%p\n", str2); //顯示第二個字串位址
printf("strcat('Hello', ' World')=%s\n", strcat(str1, str2)); //串接後以第一個字串為結果
printf("strcat('Hello', ' World') 位址=%p\n", strcat(str1, str2)); //顯示第一個字串位址
return 0;
}
此程式中先顯示兩個串接字串在記憶體中之位址, strcat(dest, source) 函數以第一個字串作為結果字串, 因此傳回值為第一個字串之位址.
執行結果 :
' World' 位址=000000000062FE10
strcat('Hello', ' World')=Hello World
strcat('Hello', ' World') 位址=000000000062FE30 //串接後傳回第一個字串位址
--------------------------------
Process exited after 0.08643 seconds with return value 0
請按任意鍵繼續 . . .
測試 13 : strcmp(s1, s2)
#include <stdio.h>
#include <string.h>
int main(void) {
char str1[20]="Hello";
char str2[20]="hello";
printf("strcmp('Hello', 'Hello')=%d\n", strcmp(str1, str1));
printf("strcmp('Hello', 'hello')=%d\n", strcmp(str1, str2));
printf("strcmp('hello', 'Hello')=%d\n", strcmp(str2, str1));
return 0;
}
執行結果 :
strcmp('Hello', 'Hello')=0
strcmp('Hello', 'hello')=-1
strcmp('hello', 'Hello')=1
--------------------------------
Process exited after 0.09408 seconds with return value 0
請按任意鍵繼續 . . .
可見由於 H 的 ASCII 編碼數值 (72) 小於 h 的編碼 (104), 因此 strcmp('Hello', 'hello') 傳回 -1.
測試 14 : strtok(str, delim)
此函數會以字串 delim 為分界符號拆解字串 str, 傳回值為分界符前面之子字串, 若要全部拆解須用遞迴方式, 但遞迴時第一參數必須傳入 NULL, 例如 :
#include <stdio.h>
#include <string.h>
int main(void) {
char str[]="11:22:33:44:55:66"; //待拆解字串
char delim[]=":"; //分界符
char *tok; //儲存分界符前之子字串
printf("待拆解字串 %s\n", str);
printf("分界字串 %s\n", delim);
tok=strtok(str, delim); //第一次拆解
while (tok != NULL) { //遞迴拆解
printf("%s\n", tok); //輸出分界符前之子字串
tok=strtok(NULL, delim); //第二次拆解傳入 NULL
}
return 0;
}
執行結果 :
待拆解字串 11:22:33:44:55:66
分界字串 :
11
22
33
44
55
66
--------------------------------
Process exited with return value 0
Press any key to continue . . .
遞迴迴圈內的 strtok() 第一參數若傳入待拆解字串 str 會不斷地拆解第一個子字串而形成無窮迴圈, 務必要傳入 NULL, 參考 :
# 切割字串函數:strtok, Network mac address 分割
測試 15 : memset(str, ch, n)
此函數會以 n 個 ch 字元填入 str 字串中, 傳回值為 str 字串之位址 (指標). 在宣告字元陣列時可用字串 literal 例如 "0000000000" 或 {'0', '0', .... '0'} 初始化, 但是如果陣列很大的話就必須用 memset() 了. 例如 :
#include <stdio.h>
#include <string.h>
int main(void) {
char str[11];
memset(str, '0', 10); //填入 10 個 '0'
str[10]='\0'; //字串結尾字元
printf("%s\n", str);
for (int i=0; i<strlen(str); i++) {
printf("字元 '%c' 位址=%p\n", str[i], &str[i]);
}
return 0;
}
執行結果 :
0000000000
字元 '0' 位址=000000000022FE30
字元 '0' 位址=000000000022FE31
字元 '0' 位址=000000000022FE32
字元 '0' 位址=000000000022FE33
字元 '0' 位址=000000000022FE34
字元 '0' 位址=000000000022FE35
字元 '0' 位址=000000000022FE36
字元 '0' 位址=000000000022FE37
字元 '0' 位址=000000000022FE38
字元 '0' 位址=000000000022FE39
--------------------------------
Process exited with return value 0
Press any key to continue . . .
參考 :
# http://www.cplusplus.com/reference/cstring/memset/
# 字串比較、搜尋
# C語言字符串函數大全
# [C&++] 字串整數轉換
# C++字符串格式化 sprintf、printf
# [C/C++] cstring (string.h) 搜尋函式:strstr, strchr
# [C/C++] 切割字串函數:strtok, Network mac address 分割
# C語言編譯器哪個好?6款好用的C語言編譯器推薦
單利複利計算機
今天找到一個很棒的線上單利複利計算機, 網址簡單又好記 :
# http://rate.0123456789.tw
以投資 10000 元於殖利率 6%, 12%, 以及 18% 的價值股 20 年, 股息再投入為例分別計算複利本利和結果如下 :
20 年後 6% 的殖利率使原資產膨脹為 3.2 倍; 12% 膨脹為 9.6 倍; 18% 膨脹為 27 倍! 複利的威力真是超乎想像! 一個企業要長期維持殖利率 10% 以上不容易, 因此必須定期檢視持股與追蹤優質標的, 在殖利率因外部因素 (例如股災) 拉升時購入才能創造 18% 的超高利潤.
# http://rate.0123456789.tw
以投資 10000 元於殖利率 6%, 12%, 以及 18% 的價值股 20 年, 股息再投入為例分別計算複利本利和結果如下 :
20 年後 6% 的殖利率使原資產膨脹為 3.2 倍; 12% 膨脹為 9.6 倍; 18% 膨脹為 27 倍! 複利的威力真是超乎想像! 一個企業要長期維持殖利率 10% 以上不容易, 因此必須定期檢視持股與追蹤優質標的, 在殖利率因外部因素 (例如股災) 拉升時購入才能創造 18% 的超高利潤.
2018年5月29日 星期二
時空的解碼器
兩周前在鄉下的市圖分館找電腦書時, 轉身看到隔壁命理學書架上有一本 "圖解八字", 好奇翻閱之下覺得玄學真是神奇的學問, 透過簡單的八個字就能窺視人的未來? 由於我要看的書太多了, 估計就算借了也沒時間看, 就放回去了.
以前因為受訓時聽老師談論占星術, 曾買書鑽研了一陣子就因為其他研究而丟一邊. 近日或許機緣成熟, 想起書架上多年前買的兩本八字論命書籍, 但是翻讀之後覺得作者寫得太深奧無法契入, 因此上周去鄉下的市圖分館還書時特意再去命理書架尋找, 挑選了下面幾本我覺得應該可以看懂的入門書 :
書中金玉良言節錄兩句如下 :
以前因為受訓時聽老師談論占星術, 曾買書鑽研了一陣子就因為其他研究而丟一邊. 近日或許機緣成熟, 想起書架上多年前買的兩本八字論命書籍, 但是翻讀之後覺得作者寫得太深奧無法契入, 因此上周去鄉下的市圖分館還書時特意再去命理書架尋找, 挑選了下面幾本我覺得應該可以看懂的入門書 :
- 八字真言 (知書房, 李如明)
- 圖解八字 : 一本可以邊看邊用的開運書
- 學學八字, 這本最好用 : 引爆命理學新革命
- 人人八字 : 為自己找出成功的密碼
- 八字學入門初階講義 : 從星座輕鬆學會看八字
書中金玉良言節錄兩句如下 :
- 幸福的主宰不在於命, 而在於一顆會調適的心.
- 命裡沒有的, 現實一定得不到; 但命裡有的, 多半人會把它糟蹋掉.
C 語言好站 : 美麗 C 世界
訂閱:
文章
(
Atom
)







