2009年12月17日 星期四

格式化輸出

今天在寫Shell script時,需要用到格式化輸出,例如要串接001~100,可以用for迴圈加上printf達成:

for number in $(seq 1 100)
do
format=`printf %.03d $number`
# Do something else
done

2009年12月12日 星期六

Pipe

當兩個不同的Process要溝通時,我們可以用pipe來達成。簡單來說,pipe就像是一條水管,連接兩個Process,其中一端寫入資料到水管,另一端便可從水管中讀出此資料。

建立pipe:
#include <unistd.h>
int pipe(int pipefd[2]);

呼叫pipe()來建立pipe,其參數int pipefd[2]是用來回傳兩個file descriptors,pipefd[0]代表的是pipe的讀取端,pipefd[1]則是pipe的寫入端。

簡單範例:
#include <stdio.h>
#include <string.h>

int main() {
int pipefd[2];
pipe(pipefd);

char writeBuf[] = "Hello pipe!";
write(pipefd[1], writeBuf, strlen(writeBuf));

char readBuf[20];
int n = read(pipefd[0], readBuf, 20);
readBuf[n] = 0;
printf("%s\n", readBuf);

return 0;
}

接下來就將單一Process擴展到不同的Process,寫出ls | wc -l,也就是計算當前目錄下有幾個檔案。
先利用fork產生Child Process,再叫用execlp()執行外部指令。

#include <stdio.h>
#include <unistd.h>

int main() {
int pipefd[2];
pipe(pipefd);

pid_t pid = fork();
if(pid != 0) {
close(pipefd[1]);
dup2(pipefd[0], 0);
close(pipefd[0]);
execlp("wc", "wc", "-l", NULL);
}
else {
close(pipefd[0]);
dup2(pipefd[1], 1);
close(pipefd[1]);

execlp("ls", "ls", NULL);
}
return 0;
}

由於fork會使pipefd[0], pipefd[1]產生兩份,記得把不必要的Descriptor關閉,可避免不當的操作。
比較需要注意的便是dup2()的用法,dup2(pipefd[0], 0)可以把它想成複製pipefd[0]且當作是標準輸入(stdin),如此wc -l從stdin讀資料就會從pipe中讀取。
可參考此網頁的說明,便能明白dup2()的用意。

2009年12月9日 星期三

freopen()

當我們想要redirect我們的標準輸出(stdout)或標準輸入(stdin)到某一個檔案,可以使用freopen()來達成。
FILE *freopen(const char *path, const char *mode, FILE *stream);

以下是簡單小範例

#include <iostream>
int main() {
freopen("test.txt", "w", stdout);
std::cout << "Hello freopen()" << std::endl;
return 0;
}


執行時,便不會看到任何輸出,而是會出現在test.txt檔案裡。

2009年11月29日 星期日

簡單的COM範例

簡單的COM範例

環境:Visual C++ 2008

1. 新增一個ATL專案,取名叫SimpleATL,伺服程式類型選擇DLL。
2. 在類別檢視下,可以看見SimpleATL類別,按右鍵加入類別,選擇ATL簡單物件,簡短名稱就設為MyATL。
3. 接著就是在IMyATL interface加上method。在IMyATL按右鍵加入method,方法名稱為Add,參數屬性為:
[in] LONG lNum1, [in] LONG lNum2, [out] LONG * plResult
4. 實作Add Method
STDMETHODIMP CMyATL::Add(LONG lNum1, LONG lNum2, LONG * plResult)
{
*plResult = lNum1 + lNum2;
return S_OK;
}

5. 建置專案即完成。


接著我們就用VC++來寫程式來使用這個COM
建立一個新的Win32 Console Application,選擇主控台應用程式和空專案選項。
先將SimpleATL_i.h及SimpleATL_i.c複製並加入到這個專案資料夾。
新增TestATL.cpp
#include "SimpleATL_i.h"
#include <iostream>

using namespace std;

void main(void)
{
HRESULT hr;
IMyATL *pIMyATL;

hr = CoInitialize(NULL);

if(SUCCEEDED(hr))
{
hr = CoCreateInstance(CLSID_MyATL, NULL, CLSCTX_INPROC_SERVER, IID_IMyATL, (void**) &pIMyATL);

if(SUCCEEDED(hr))
{
long lResult;

hr = pIMyATL->Add(5, 10, &lResult);
cout << "5 + 10 = " << lResult << endl;
hr = pIMyATL->Release();
}
else
cout << "CoCreateInstance Failed." << endl;
}
CoUninitialize();
}

2009年11月28日 星期六

SO_REUSEADDR

當一個Socket server如果重新啟動時,在bind的過程就會出現:Address already in use的錯誤訊息,必須等待TCP TIME_WAIT state的時間(2 * MSL)才能使用這個Address。為了避免這個問題發生,我們可以透過修改socket參數來讓socket可以馬上bind之前的Address。

sock = socket(AF_INET, SOCK_STREAM, 0);

int on = 1;
int status = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
if (status == -1)
perror("setsockopt() error");

簡單的DLL範例

簡單的DLL範例

環境:Visual C++ 2008

建立一個新的,選擇Win32 Console Application
最後選擇DLL和Empty Porject選項

建立AddInt.h及AddInt.cpp

AddInt.h
#ifndef _ADD_INT_H_
#define _ADD_INT_H_

#define DLLExport __declspec( dllexport )

extern "C"
{
DLLExport int Add(int a, int b);
}

#endif


function必須export才能被使用,有兩種方法可以使用:
使用 __declspec這個關鍵字
建立一個Module-Definition File (.DEF)

至於為什麼要加入extern "C"
因為C++ compiler在編譯時會將function name作一些修飾也就是改名字的動作(mangle)
加入extern "C"則可保留原名

AddInt.cpp
#include "AddInt.h"

int Add(int a, int b) {
return a + b;
}


Build Project即完成,我們會在資料夾找到AddInt.dll及AddInt.lib


接著我們就寫一個程式來使用這個DLL

可以用兩種方式來使用DLL

Implicit Linking - 程式需link到AddInt.lib,並將AddInt.dll放在與程式同目錄下
#include <iostream>
#include "AddInt.h"

int main()
{
std::cout << Add(5, 10) << std::endl;

return 0;
}


Explicit Linking - 不需要AddInt.h及AddInt.Lib,僅需要AddInt.dll,但使用較為複雜。
#include <iostream>
#include <windows.h>

typedef int (*pfAddIntFunction)(int,int);

int main()
{
pfAddIntFunction pfAddInt ;

HINSTANCE hLibrary = LoadLibrary(L"AddInt.dll");

if(hLibrary)
{
pfAddInt = (pfAddIntFunction)GetProcAddress(hLibrary, "Add");

if(pfAddInt)
{
std::cout << pfAddInt(5, 10) << std::endl;
}

FreeLibrary(hLibrary);
}
else
{
std::cout << "Failed To Load Library" << std::endl;
}

return 0;
}

2009年11月21日 星期六

NAT型態

NAT的類型大致可分為四種:
  • Full cone NAT
  • (Address) Restricted cone NAT
  • Port-Restricted cone NAT
  • Symmetric NAT

假設在NAT下的主機A為(iIP, iPort),實際對外為(eIP, ePort)

Full cone NAT: 任何主機皆可透過(eIP, ePort)送封包給A。

(Address) Restricted cone NAT:只有之前收過A送來封包的外部主機(hIP, any),才可透過(eIP, ePort)送封包給A,不限定原來溝通的Port。

Port-Restricted cone NAT :同上,但外部主機只能用之前用的Port才能送封包給A。

Symmetric NAT:同上,但A對每一個不同的(hIP, hPort),也就是IP或Port的任何一值改變,其(eIP, ePort)就會不同。

2009年11月17日 星期二

Dump Schema

若要匯出MySQL下某個資料庫的Schema,可以用mysqldump來達成:

# mysqldump -d -u 使用者名稱 -p 欲備份的資料庫 >> FILENAME.sql

例:
# mysqldump -d -u howard -p account > account.sql


匯入到新的MySQL資料庫

# mysql -u 使用者名稱 -p 資料庫 < account.sql

2009年10月27日 星期二

CMake簡單範例

CMake是一個軟體建構工具,可以幫我們產生MakeFile。以下就用簡單的範例來呈現:
我們有三個檔案main.cpp hello.cpp hello.h和三個CMakeLists.txt
分別位於

|-- CMakeLists.txt
|-- lib
| |-- CMakeLists.txt
| |-- hello.cpp
| |-- hello.h
|-- src
|-- CMakeLists.txt
|-- main.cpp

hello.h
void hello();
hello.cpp
#include "hello.h"
#include <iostream>
void hello() {
std::cout << "Hello CMake!" << std::endl;
}

main.cpp
#include "hello.h"
int main() {
hello();
return 0;
}

最上層的CMakeLists.txt
PROJECT (HELLO)
# 加入兩個子資料夾(src後面bin的意思是將src的輸出放到bin資料夾)
ADD_SUBDIRECTORY (src bin)
ADD_SUBDIRECTORY (lib)

lib/CMakeLists.txt
# 將hello.cpp編譯成static library
ADD_LIBRARY (HelloLibrary hello.cpp)

src/CMakeLists.txt
INCLUDE_DIRECTORIES (${HELLO_SOURCE_DIR}/lib)
SET (HELLO_SRCS main.cpp)
ADD_EXECUTABLE (HelloCMake HELLO_SRCS)
TARGET_LINK_LIBRARIES (HelloCMake HelloLibrary)

在執行cmake前,我們可以在最上層先建立一個目錄(例如:build),然後到build目錄下執行cmake,如此cmake後產生的資料皆會在build資料夾裡。
# mkdir build
# cd build
# cmake ../
# make

若順利的話,便可在bin找到HelloCMake執行檔,在lib可找到libHelloLibrary.a

2009年10月24日 星期六

FastCGI

FastCGI是一個網頁伺服器端應用程式介面,CGI有一個很大的缺點就是CGI程式每次執行就會產生一個新的process,當同時很多人上線時,會對伺服器造成很大負擔;而FastCGI程式是常駐型的CGI程式,不會因為Http_Request結束而終止。

在Debian 5安裝Apache2 + FastCGI
# apt-get install apache2 libapache2-mod-fastcgi
# /etc/init.d/apache2 restart

接著用c寫一個helloFCGI的程式來驗証:
#include "fcgi_stdio.h"
#include <stdlib.h>

int main()
{
int count = 0;
while(FCGI_Accept() >= 0) {
printf("Content-type: text/html\r\n"
"\r\n"
"<title>Hello FastCGI</title>"
"<h1>Hello FastCGI</h1>"
"Request number %d running on host <i>%s</i>\n",
++count, getenv("SERVER_NAME"));
}
return 0;
}

編譯時要加上-lfcgi參數
# gcc -lfcgi -o helloFCGI.fcgi helloFCGI.c

將helloFCGI.fcgi放到所設定的FastCGI執行的資料夾內(Debian安裝好的預設資料夾在/usr/lib/cgi-bin),在網頁執行http://localhost/cgi-bin/helloFCGI.fcgi即可看到結果。

2009年10月7日 星期三

Windows Multithreaded Programming

要建立多執行緒程式,我們會用到<process.h>標頭檔定義的函式:

uintptr_t _beginthread(

void( __cdecl *start_address )( void * ),
unsigned stack_size,
void *arglist

);

_beginthread()需要三個參數,第一個是要執行緒所執行的函式名稱(注意這個函式的prototype);第二個參數為給這個執行緒的stack size,若設定0值則作業系統會自動設定此值;第三個參數可以用來傳遞資料給欲執行的函式。

#include <windows.h>
#include <process.h>
#include <iostream>

using namespace std;

void func1(void *);
void func2(void *);

int main()
{
_beginthread(func1, 0, NULL);
_beginthread(func2, 0, NULL);

Sleep(10000);
cout << "Main exit" << endl;
getchar();
return 0;
}

void func1(void *p)
{
for(int i = 1; i < 6; ++i)
cout << "func1 value " << i << endl;
}

void func2(void *p)
{
for(int i = 1; i < 6; ++i)
cout << "func2 value " << i << endl;
}

以下用簡單的範例說明:
執行結果如下:


這個結果可以發現兩個執行緒可以在任何時間點去插隊執行,若要避免這種情況發生,我們可以利用critical section來解決它。

2009年9月26日 星期六

update-alternatives

Debian提供了update-alternatives的工具,可以用來管理套件的版本。例如:系統有三套Java的套件GIJ、GCJ和Sun Java,如何能自由且快速的切換不同版本。

首先,先看一下java指令的路徑
#which java
/usr/bin/java

# ls -l /usr/bin/java
/usr/bin/java -> /etc/alternatives/java
# ls -l /etc/alternatives/java
/etc/alternatives/java -> /usr/lib/jvm/java-gcj/jre/bin/java

我們可以看到java的指令用一個symbolic link連到/etc/alternatives/java,而/etc/alternatives/java又是一個symbolic link連到/usr/lib/jvm/java-gcj/jre/bin/java。
所以update-alternatives就是將/etc/alternatives/java改掉。

# update-alternatives --display java
java - status is auto.
link currently points to /usr/lib/jvm/java-gcj/jre/bin/java
/usr/bin/gij-4.2 - priority 42
slave java.1.gz: /usr/share/man/man1/gij-4.2.1.gz
/usr/lib/jvm/java-gcj/jre/bin/java - priority 1042
/usr/lib/jvm/java-6-sun/jre/bin/java - priority 63
slave java.1.gz: /usr/lib/jvm/java-6-sun-1.6.0.00/jre/man/man1/java.1.gz
Current `best' version is /usr/lib/jvm/java-gcj/jre/bin/java.

可以看到目前系統有gcj和Sun Java,由於status是auto,而gcj的優先權最高,所以可以最下面顯示目前最佳的版本是gcj。若要改變成java-6-sun:

# update-alternatives --config java

即可選擇java-6-sun。

2009年9月22日 星期二

ldd

ldd可以用來顯示每個程式所使用到的shared library。ldd其實是一個shell script而不是執行檔。

在linux,我們可以將程式編譯成靜態連結或是動態連結,在這以hello.c來解釋。

#include <stdio.h>
int main(void) {
printf("Hello world!\n");
return 0;
}

用gcc編譯
# gcc hello.c -o hello
則會產生hello的執行檔,而其預設是使用動態連結的方式:

用file指令來檢視其屬性
# file hello
hello: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.8, not stripped

用ldd來檢視共用了哪些shared library
# ldd hello
linux-gate.so.1 => (0xb7f6a000)
libc.so.6 => /lib/i686/cmov/libc.so.6 (0xb7dfd000)
/lib/ld-linux.so.2 (0xb7f6b000)

此外,此檔案的大小為
# ls -l hello
-rwxr-xr-x 1 howard howard 6256 2008-09-30 00:00 hello

上述為程式使用動態連結,我們也可以將程式編譯成靜態連結:
# gcc -static hello.c -o hello

用file來檢視,可以看到顯示為靜態連結
# file hello
hello: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.6.8, not stripped

用ldd來檢視,自然沒使用到任何shared library
# ldd hello
not a dynamic executable

再來檢視檔案的大小
# ls -l hello
-rwxr-xr-x 1 howard howard 564881 2008-09-30 00:07 hello

我們可以看到檔案大小為564881 Bytes,相對於之前用動態連結只用了6256 Bytes,足足大上快一百倍。可見使用動態連結能大大節省空間。

2009年9月18日 星期五

解決JAVA中文顯示方塊

在Linux下執行Java程式時,常發現中文字體無法顯示,全部變成方塊,解決方法如下:

# cd /usr/lib/jvm/java-6-sun/jre/lib/fonts/
# mkdir fallback
# cd fallback
# ln -s /usr/share/fonts/truetype/arphic/uming.ttc .

新增一個fallback資料夾,再將中文字體連結到資料夾內即可。

2009年9月16日 星期三

飛虎803T 登出

十一個月又八天的軍旅生涯,在早上拿著退伍令走出營門的那一刻終於結束,恢復成老百姓的感覺真好!

既然都退伍了,就不再提軍中生活了。當兵只是人生的一個小階段,緊接面對的才是重要的挑戰,相信自己一定可以的,加油!

2009年9月2日 星期三

再見了!C-130

還記得第一次搭飛機的經驗就是坐上C-130運輸機,對於它的印象就是很吵,但由於免錢的因素所以每次休假返台幾乎都是搭軍機回家。昨天是軍旅生涯最後一次的休假了,應該也是最後一次能搭乘C-130。不知道為什麼最後一次的C-130特別舒適,起飛時就睡著了,醒來時已經在台北的天空翱翔。



再見了!C-130

2009年8月13日 星期四

插座產生火花

剛在筆電快沒電時,將筆電的插頭插進插座時冒出火花,於是就查了一下是什麼原因會造成火花的出現。

引用自 http://enews.nfa.gov.tw/issue/940421/images/radio.htm


插頭在插入插座時,為何會有小小火花產生呢?

插頭在插入插座時,經常會發現有小小火花,主要是因為電器用品在尚未通電之前已將開關打開或上次不使用後,只是將插頭把掉,但沒有把開關關掉,以致再使用時,直接插入插座時,便立即處於通電狀態,以致瞬間電流較高,又加上插頭長期未清理,插頭的兩隻腳(正負兩極)間會逐漸堆積一些灰塵、毛髮,而這些灰塵、毛髮,如果碰到水氣,產生銅鏽,就有可能成為導體,造成插座兩極間出現一個迴路,而產生火花。所以只要平時經常保持插頭銅片乾淨,且養成插頭插上插座後,再打開電器開關,既可以延長電器的壽命又可以避免因火花而引起的不必要災害。

2009年7月25日 星期六

空軍軍歌

上次收假回部隊後,突然來了一個大驚喜,那就是單位新來了兩位新兵,這代表我終於擺脫菜島的身份。人多好辦事,相信應該可以快快樂樂的退伍才是。

但也因這兩位新兵的加入,副主任要這兩位新兵學唱空軍軍歌,然後總班長叫我去教他們,所以我也不會唱的事也跟著露餡。不過,身為空軍卻不會唱空軍軍歌實在是說不過去,所以就趁這個時候學一下好了。



空軍軍歌
簡樸詞 劉雪庵曲

凌雲御風去,報國把志伸,遨遊崑崙上空,俯瞰太平洋濱,
看五嶽三江雄關要塞,美麗的錦繡河山,輝映著無敵機群。
緬懷先烈莫辜負創業艱辛,發揚光大尤賴我空軍軍人,
同志們努力努力,
矢勇矢勤,國祚皇皇萬世榮。

盡瘁為空軍,報國把志伸, 那怕風霜雨露,只信雙手萬能,
看鐵翼蔽空馬達齊鳴,美麗的錦繡河山,輝映著無敵機群。
我們要使技術發明日日新,我們要用血汗永固中華魂。
同志們努力努力,
同德同心,國祚皇皇萬世榮。

2009年7月6日 星期一

排列演算法

數學一向不是很好的我,一看到要列出某字串所有的排列(Permutation),就讓我非常的頭大。記得當初要準備考研究所時就曾經看著資料結構書上的解法想了老半天,似懂非懂,但最近又看到類似的題目,證明了以前是裝懂。

To iterate is human, to recurse divine.


遞迴的程式一定要在頭腦清楚時再來看,否則只是在浪費時間而已。這次,我真的看懂了。

以{a, b, c, d}為例子,要列出所有的排列,我們可以將這個問題拆解成:
  • 開頭為a加上{b, c, d}的所有排列
  • 開頭為b加上{a, c, d}的所有排列
  • 開頭為c加上{a, b, d}的所有排列
  • 開頭為d加上{a, b, c}的所有排列
所以,很明顯的是可以用遞迴方式來解。在此用C++來實作

void perm(char *obj, int pos, int n) {
if(pos == n - 1) {
for(int i = 0; i < n; ++i) cout << obj[i] << " ";
cout << endl;
}
else {
for(int i = pos; i < n; ++i) {
// swap()是要自己寫的函式,交換陣列內的值
swap(obj[pos], obj[i]);
perm(obj, pos + 1, n);
swap(obj[pos], obj[i]);
}}}

else內的for迴圈是整個程式的關鍵,可以用上面舉的例子來說明,假設obj陣列已經存了{a, b, c, d}四個值,我們呼叫perm(obj, 0, 4)來印出所有排列。for迴圈的解釋就如同將第一個位置分別用a, b, c, d為開頭,所以用了swap()把每一個值都對調到第一個位置,接著再呼叫perm(obj, 1, 4)來排列剩下的三個字元,依此類推。

2009年6月10日 星期三

軍旅生涯倒數

看到週遭的朋友一個一個退伍了,何時才會輪到我呢?至從上次點放在網咖裡寫了一個退伍倒數計時器放在部落格上,就這樣開始展開我的軍旅生涯倒數,很巧的是從123天開始。到現在已經剩下98天,敲敲的破百了,而破百的意義不外乎是從三位數變成兩位數,也就是可以準備開始打包行李了。

隨著退伍日一天天的逼近,心情卻是有些忐忑不安,因為退伍後即將面臨的是就業問題,不知道自己究竟能做什麼,會做什麼?很後悔自己在大學時期沒有更積極的學習,只是顧著怎樣應付期中期末考,卻沒想到要去多培養一些專業的能力來充實自己。

雖說面對未來有些徬徨不安,但有一件事非常的肯定,那就是我是不可能選擇當軍人的,外面的空氣自由多了!

2009年6月8日 星期一

UVa 113 - Power of Cryptography

終於遇見一個秒殺的題目了,UVa 113 - Power of Cryptography這題只是單純的數字開根號問題,只要用<math.h>裡的pow(double x, double y)即可完成。

程式碼

因為有使用到<math.h>的函式,在用gcc編譯時要多一個-lm的參數。

2009年6月5日 星期五

Debian GNU/Linux 5.0

將近要一年沒有碰Linux了,之前用的Debian GNU/Linux 5.0 (Lenny)都從測試版變成穩定版了。一時興起,決定再來重灌一下Debian。但這次不再選擇使用測試版本,雖說測試版本有許多較新的軟體可以使用,但更新頻率實在是太高了,有時正常的系統更新後就感覺變的怪怪的,然後就要花很多時間去搜集資料把問題解決。

在安裝完後,通常我都會先做以下幾步驟:
  • 調整系統字型
  • 更新顯示卡驅動程式
  • 安裝gcin,並且新增嘸蝦米輸入法
  • GNOME-Look.org找尋想要的桌布與佈景主題
  • 調整登入畫面
  • 安裝PCMan (主要用來PTT)
  • 安裝Audacious (聽音樂必備)
  • 安裝aMSN
另外,由於感覺桌面顯示的圖示有點大,也順手將它變小。可在組態編輯器或在終端機輸入gconf-editor進入,選擇apps -> nautilus -> icon_view裡的default_zoom_levelstandard改為small即可。

以下即為安裝後的畫面

2009年5月16日 星期六

倒數計時器

當兵最在意的事是什麼呢?對我而言就是還剩幾天才能拿到退伍令。所以我就決定用JavaScript來寫一個倒數計時器放在部落格上。

<script language="JavaScript">
var today = new Date();
var endDay = new Date(2009, 9 - 1, 16);

var diffDay = (endDay.getTime() - today.getTime()) / (24 * 60 * 60 * 1000);

diffDay = Math.ceil(diffDay);
var message = diffDay <= 0 ? "已退伍" : "離退伍還剩" + diffDay + "天";
document.write("<b>" + message + "</b>");
</script>

程式很簡單,就單純把兩個時間相減即可。另外在最後再做個判斷是否時間已經到了,以免輸出負數的日期。

要注意一點的是new Date(年, 月 - 1, 日),月份是從0到11,所以要減1才是正確的日期。

2009年5月7日 星期四

UVa 112 - Tree Summing

面對UVa 112 - Tree Summing這一題,一開始我的想法是要先將整顆樹建立起來,再從root拜訪到leaf。但再仔細研究一下,其實不需要建立樹,用遞迴的方式,很快就能解出。遞迴想法很容易,簡單述說如下:

1. 從root開始,將value傳給左右子節點。
2. 子節點將value與父節點傳來的value相加,再將value傳給自己的左右子節點。
3. 當節點為葉節點時,判斷總合是否相符。

程式碼

對我來講,一開始遇見的瓶頸在於怎樣處理題目給的輸入,但只要想通了就很容易,每一個節點都從左括號開始,右括號結束,抓著這一點,程式就可以開始寫了。這個題目還有一點要注意的是有可能會出現負值,所以記得要處理。

2009年5月6日 星期三

增廣見聞

厭倦自己的書櫃裡總是滿滿的電腦書籍,其它領域的知識也應該有所涉獵。所以今天和從前不一樣,從書局帶回了兩本非資訊的書,分別是圖解金融以及文法女王:無痛升級學習法。文法女王的目的主要就是試圖喚醒自己遺忘已久的英文文法,而圖解金融是想多瞭解金融市場的基本知識,不然每次都看不懂財經新聞在報導什麼。

另外,意外發現一個不錯的網站(aNobii),功能如同是個人線上書櫃,可以收藏、整理、分享、交友與買賣,是免費的且也有中文介面,有興趣的可以去試試看!

2009年5月4日 星期一

UVa 111 - History Grading

UVa 111 - History Grading題目不難,可以用LCS(Longest Common Subsequence)來解。唯一要注意的是題目所給的輸入資料。

程式碼


例如:
10
3 1 2 4 9 5 10 6 8 7
2 10 1 3 8 4 9 5 7 6

第一數字表示有十個事件。
接下來的每一行裡的數字則是指每一個事件在第幾個順序發生的:
event 1 -> order 3
event 2 -> order 1
event 3 -> order 2
以此類推,所以要先經過轉換後,事件的正確發生順序為2 3 1 4 6 8 10 9 5 7
下一行經過轉換後,順序為3 1 4 6 8 10 9 5 7 2
由LCS計算可得到最大的共同子序列長度為9

2009年4月20日 星期一

要升一兵了

入伍到現在已經六個多月了,五月一號就要正式升一兵,代表薪水也會升個五百元左右,不無小補。但雖說升上一兵,但我依舊是單位中最菜的一位,不只是完全沒新兵進來,現在更只剩我一個義務役的,所以到現在不管是有任何公差勤務,第一個最佳人選一定是我。有一句話說:「難過是一天,快樂也是一天!」用愉快的心情去面對這些公差勤務,其實一切都可以很簡單的。

在軍中這半年裡,對我最大的收穫就是變胖了,記得在當兵前總常常被人嫌太瘦,當兵前的體重大約都在六十公斤左右,而現在吃了半年油膩的軍中伙食,體重已經飆升到七十公斤,說不一定改天就有人叫我胖子了。 所以當然也不能讓體重無限增長,因此最近也開始會到軍中的健身房做做重量訓練和一些運動,有肌肉總比贅肉好。

雖說當了半年的兵,但還是寫不出什麼感想,就像每個禮拜要寫的莒光作文簿一樣,短短的幾句話就讓我寫了好久,還是比較喜歡外面多采多姿的生活。還剩下五個月,繼續加油囉!

「什麼都是假的,平安退伍才是真的!」

2009年4月8日 星期三

序曲

總覺得之前的網誌寫的有點亂又懶得整理,於是就有了現在這個網誌的出現。和之前一樣,依舊是記錄自己的心情日記、學習心得等。

期待這個網誌能一直存在著。