Fork me on GitHub

6/29/2011

[C++] 使用預設參數值 實現 可變量參數

#include <iostream>
using namespace std;

void method(int a, int b) {
 int aa = a;
 int bb = b;
 cout << "aa:" << aa << " bb:" << bb << endl;
}

void defaultParaMethod(int a = 0, int b = 1) {
 int aa = a;
 int bb = b;
 cout << "aa:" << aa << " bb:" << bb << endl;
}

int main() {

 int A = 1;
 int B = 2;
 defaultParaMethod(A);
 defaultParaMethod(A, B);
 //method(a); // error

 return 0;
}

6/28/2011

[Android] 執行週期性任務 - execute period task

最近專案需要定期從系統擷取一些資料,除了開一個 thread 之外,找的一個更為輕量的解決方案,整理如下:

final Handler handler= new Handler();
        
final int delay = 5000; // 5 second
final int period = 1000; // 1 second

final Runnable r = new Runnable() {
    public void run() {
        Toast.makeText(getApplicationContext(),"RUN!",Toast.LENGTH_SHORT).show();
        handler.postDelayed(this, period);
        }
    };

handler.postDelayed(r, delay);

poseDelayed(): adds the runnable to the queue and it runs in the UI thread

除了這個方法之外還有一些其他的方法:
1. Handlers, and PostDelayed can be nice lightweight ways of having your foreground activity called on a regular basis. Even the messages are reused. These are used in the Snake example program (Snake/SnakeView.java/sleep()) to make the snake move. It runs as 'post a message delayed by 500ms', in 500ms catch it in HandleMessage (the default for Handlers), move, then send it again. Even the message is reused with obtainMessage(). I've used these for making a button update while it is pushed down.

2. Threads are a bit heavier. You might use these for background or where you are already used to running a thread. Make a 'new Thread(aRunnable).start()'. I haven't used them much on the Android.

3. Launch an Intent with StartActivityForResult() and catch the result with OnActivityResult to make a standard RPC. See step 2 of the notepad example for more information.

4. Look into more Intents to launch for different scenarios. I find putting your 'create and launch intent' into separate functions helps maintenance and debugging.

via Android - Question on postDelayed and Threads

參考資料:
  1. 「有人建議不要使用 TimerTasks」: Schedule task in android - Stack Overflow
  2. How to run a Runnable thread in Android? - Stack Overflow

... ...

6/26/2011

[C++] local variable 為什麼可以離開 scope 而被存取

在 stackoverflow 看到一則有趣的討論串,問題是這樣的:

int * foo()
{
    int a = 5;
    return &a;
}

int main()
{
    int* p = foo();
    cout << *p;
    *p = 8;
    cout << *p;
}

And the code is just running with no runtime exceptions! The output was 5 8! How can it be? Isn't the memory of a local variable inaccessible outside its function?

意思就是為什麼 a 這個函數的局部變數還存活到離開了函數的 scope 呢?下面一個答案的比喻真是妙極了:
You rent a hotel room. You put a book in the top drawer of the bedside table and go to sleep. You check out the next morning, but "forget" to give back your key. You steal the key!

A week later, you return to the hotel, do not check in, sneak into your old room with your stolen key, and look in the drawer. Your book is still there. Astonishing!

How can that be? Isn't the contents of a hotel room drawer inaccessible if you haven't rented the room?

這個作者回答的相當生動,當然後面也補充了一些技術細節,有興趣的可以到這裡參考!

參考文章


... ...

6/22/2011

[Eclipse] 調整 Eclipse 在 Mac 中選單字體大小

在 Mac 環境中運行 Eclipse 字體變得很小,Editor 的字體大小可以透過 Preference 選項修改,那選單裡面的字型要怎麼放大呢?

可以參考 Make Eclipse use larger fonts 這篇文章。主要就是到 Eclipse 的安裝路徑下找到 eclipse.ini 這個檔案,然後把裡面的 -Dorg.eclipse.swt.internal.carbon.smallFonts 改成 -Dorg.eclipse.swt.internal.carbon.largeFonts 即可。

要怎麼找到 eclipse.ini 這個檔案呢?在 Eclipse.app 上面按右鍵 Show Package Contents -> Contents -> MacOS -> eclipse.ini 即可...

... ...

[C++] 淺談左值與右值 - lvalue and rvalue

左值和右值感覺是基礎的東西,書本上經常會提到,但是始終不懂他們的用意是什麼,又有什麼區別,於是決心到網路上找看看有沒有精確又容易理解的說明!發現「Rvalue References: C++0x Features in VC10, Part 2」講解的還不錯,節錄如下:

lvalues and rvalues in C++98/03

C++03 3.10/1 says: "Every expression is either an lvalue or an rvalue."  It's important to remember that lvalueness versus rvalueness is a property of expressions, not of objects

原來 lvalue 和 rvalue 是用來描述 「expressions」 的屬性而非 objects!

Lvalues name objects that persist beyond a single expression.  For example, obj , *ptr , ptr[index] , and ++x are all lvalues.

Rvalues are temporaries that evaporate at the end of the full-expression in which they live ("at the semicolon").  For example, 1729 , x + y , std::string("meow") , and x++ are all rvalues.

左值讓一段 expression 成為一個有名稱的物件;而右值只是一段 expression 的結果且隨時會蒸發不見。為什麼 ++x 是左值而 x++ 卻是右值呢?

Both ++x and x++ increment x, but ++x returns the persistent object itself, while x++ returns a temporary copy. That's why ++x is an lvalue, while x++ is an rvalue

If you want to build up intuition for this, another way to determine whether an expression is an lvalue is to ask "can I take its address?". If you can, it's an lvalue. If you can't, it's an rvalue. For example, &obj , &*ptr , &ptr[index] , and &++x are all valid (even though some of those expressions are silly), while &1729 , &(x + y) , &std::string("meow") , and &x++ are all invalid.

並且可以利用一個簡單的方法來 check 一段 expression 是 lvalue 或 rvalue,就是看看可不可以使用 & 運算元對該 expression 取得他的位置

"A function call is an lvalue if and only if the result type is a reference." (C++03 5.2.2/10) Therefore, given vector v(10, 1729); , v[0] is an lvalue because operator[]() returns int& (and &v[0] is valid and useful), while given string s("foo"); and string t("bar"); , s + t is an rvalue because operator+() returns string (and &(s + t) is invalid)

Both lvalues and rvalues can be either modifiable (non-const) or non-modifiable (const). Here are examples:

左值和右值皆可以為 non-const 和 const (用 non-const 似乎較 modifiable 來的直覺),以下為範例:

string one("cute");
const string two("fluffy");
string three() { return "kittens"; }
const string four() { return "are an essential part of a healthy diet"; }

one; // modifiable lvalue
two; // const lvalue
three(); // modifiable rvalue
four(); // const rvalue

Type& binds to modifiable lvalues (and can be used to observe and mutate them). It can't bind to const lvalues, as that would violate const correctness. It can't bind to modifiable rvalues, as that would be extremely dangerous. Accidentally modifying temporaries, only to have the temporaries evaporate along with your modifications, would lead to subtle and obnoxious bugs, so C++ rightly prohibits this. And it can't bind to const rvalues, as that would be doubly bad. (Careful readers should note that I'm not talking about template argument deduction here.)

non-const reference 可以綁定 non-const lvalues,不可以綁定 const lvalues。這很容易理解,因為 reference 就只是一個 alias。

non-const reference 也不能綁定 non-const rvalue。因為 rvalue 只是一個暫態,沒有一個東西可以 hold 住他,所以你可能以為 non-const reference 可以對他做操控,但實際上卻不行。


const Type& binds to everything: modifiable lvalues, const lvalues, modifiable rvalues, and const rvalues (and can be used to observe them).

const reference 則可以綁定所有 (non-const lvalues, const lvalues, non-const rvalues 和 const rvalues)


接著還可以進一步牽扯到 C++0x 的新語言特性,有點複雜,因此有興趣的話可以再回原文參閱...


參考資料:
Rvalue References: C++0x Features in VC10, Part 2
http://blogs.msdn.com/b/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx

C++ Primer 中文版 p.60

... ...

6/20/2011

[C++] 搞懂複雜變數的簡單規則 - Right-Left Rule

雖然平常寫程式的時候不太會用到那麼複雜的變數,但是這東西考試倒是蠻喜歡考的,靠著 Right-Left Rule 在複雜的變數也可以被輕鬆破解!

底下為轉文,原文在 C Right-Left Rule (Rick Ord's CSE 30 - UC San Diego)

The "right-left" rule is a completely regular rule for deciphering C
declarations.  It can also be useful in creating them.

First, symbols.  Read

     *  as "pointer to"   - always on the left side
     []  as "array of"   - always on the right side
     ()  as "function returning"  - always on the right side

as you encounter them in the declaration.

STEP 1
------
Find the identifier.  This is your starting point.  Then say to yourself,
"identifier is."  You've started your declaration.

STEP 2
------
Look at the symbols on the right of the identifier.  If, say, you find "()"
there, then you know that this is the declaration for a function.  So you
would then have "identifier is function returning".  Or if you found a 
"[]" there, you would say "identifier is array of".  Continue right until
you run out of symbols *OR* hit a *right* parenthesis ")".  (If you hit a 
left parenthesis, that's the beginning of a () symbol, even if there
is stuff in between the parentheses.  More on that below.)

STEP 3
------
Look at the symbols to the left of the identifier.  If it is not one of our
symbols above (say, something like "int"), just say it.  Otherwise, translate
it into English using that table above.  Keep going left until you run out of
symbols *OR* hit a *left* parenthesis "(".  

Now repeat steps 2 and 3 until you've formed your declaration.  Here are some
examples:

     int *p[];

1) Find identifier.          int *p[];
                                  ^
   "p is"

2) Move right until out of symbols or left parenthesis hit.
                             int *p[];
                                   ^^
   "p is array of"

3) Can't move right anymore (out of symbols), so move left and find:
                             int *p[];
                                 ^
   "p is array of pointer to"

4) Keep going left and find:
                             int *p[];
                             ^^^
   "p is array of pointer to int". 
   (or "p is an array where each element is of type pointer to int")

Another example:

   int *(*func())();

1) Find the identifier.      int *(*func())();
                                    ^^^^
   "func is"

2) Move right.               int *(*func())();
                                        ^^
   "func is function returning"

3) Can't move right anymore because of the right parenthesis, so move left.
                             int *(*func())();
                                   ^
   "func is function returning pointer to"

4) Can't move left anymore because of the left parenthesis, so keep going
   right.                    int *(*func())();
                                           ^^
   "func is function returning pointer to function returning"

5) Can't move right anymore because we're out of symbols, so go left.
                             int *(*func())();
                                 ^
   "func is function returning pointer to function returning pointer to"

6) And finally, keep going left, because there's nothing left on the right.
                             int *(*func())();
                             ^^^
   "func is function returning pointer to function returning pointer to int".


As you can see, this rule can be quite useful.  You can also use it to
sanity check yourself while you are creating declarations, and to give
you a hint about where to put the next symbol and whether parentheses
are required.

Some declarations look much more complicated than they are due to array
sizes and argument lists in prototype form.  If you see "[3]", that's
read as "array (size 3) of...".  If you see "(char *,int)" that's read
as "function expecting (char *,int) and returning...".  Here's a fun
one:

                 int (*(*fun_one)(char *,double))[9][20];

I won't go through each of the steps to decipher this one.

Ok.  It's:

     "fun_one is pointer to function expecting (char *,double) and 
      returning pointer to array (size 9) of array (size 20) of int."

As you can see, it's not as complicated if you get rid of the array sizes
and argument lists:

     int (*(*fun_one)())[][];

You can decipher it that way, and then put in the array sizes and argument
lists later.

Some final words:

It is quite possible to make illegal declarations using this rule,
so some knowledge of what's legal in C is necessary.  For instance,
if the above had been:

     int *((*fun_one)())[][];

it would have been "fun_one is pointer to function returning array of array of
                                          ^^^^^^^^^^^^^^^^^^^^^^^^
pointer to int".  Since a function cannot return an array, but only a 
pointer to an array, that declaration is illegal.


Illegal combinations include:

  []() - cannot have an array of functions
  ()() - cannot have a function that returns a function
  ()[] - cannot have a function that returns an array

In all the above cases, you would need a set of parens to bind a *
symbol on the left between these () and [] right-side symbols in order
for the declaration to be legal.

Here are some legal and illegal examples:

int i;                  an int
int *p;                 an int pointer (ptr to an int)
int a[];                an array of ints
int f();                a function returning an int
int **pp;               a pointer to an int pointer (ptr to a ptr to an int)
int (*pa)[];            a pointer to an array of ints
int (*pf)();            a pointer to a function returning an int
int *ap[];              an array of int pointers (array of ptrs to ints)
int aa[][];             an array of arrays of ints
int af[]();             an array of functions returning an int (ILLEGAL)
int *fp();              a function returning an int pointer
int fa()[];             a function returning an array of ints (ILLEGAL)
int ff()();             a function returning a function returning an int
                                (ILLEGAL)
int ***ppp;             a pointer to a pointer to an int pointer
int (**ppa)[];          a pointer to a pointer to an array of ints
int (**ppf)();          a pointer to a pointer to a function returning an int
int *(*pap)[];          a pointer to an array of int pointers
int (*paa)[][];         a pointer to an array of arrays of ints
int (*paf)[]();         a pointer to a an array of functions returning an int
                                (ILLEGAL)
int *(*pfp)();          a pointer to a function returning an int pointer
int (*pfa)()[];         a pointer to a function returning an array of ints
                                (ILLEGAL)
int (*pff)()();         a pointer to a function returning a function
                                returning an int (ILLEGAL)
int **app[];            an array of pointers to int pointers
int (*apa[])[];         an array of pointers to arrays of ints
int (*apf[])();         an array of pointers to functions returning an int
int *aap[][];           an array of arrays of int pointers
int aaa[][][];          an array of arrays of arrays of ints
int aaf[][]();          an array of arrays of functions returning an int
                                (ILLEGAL)
int *afp[]();           an array of functions returning int pointers (ILLEGAL)
int afa[]()[];          an array of functions returning an array of ints
                                (ILLEGAL)
int aff[]()();          an array of functions returning functions
                                returning an int (ILLEGAL)
int **fpp();            a function returning a pointer to an int pointer
int (*fpa())[];         a function returning a pointer to an array of ints
int (*fpf())();         a function returning a pointer to a function
                                returning an int
int *fap()[];           a function returning an array of int pointers (ILLEGAL)
int faa()[][];          a function returning an array of arrays of ints
                                (ILLEGAL)
int faf()[]();          a function returning an array of functions
                                returning an int (ILLEGAL)
int *ffp()();           a function returning a function
                                returning an int pointer (ILLEGAL)


... ...

6/17/2011

[Java] 淺談 call by value 和 call by reference

在 C++ 中, call-by-value 意味著把變數的值複製一份傳進函數;  而 call-by-reference 則意味著把變數的 alias (用 &var 或者指標) 傳進函數當中。

因此,在 C++ 中我是這麼理解的,在函數內部改變 call-by-value 傳入的參數並不會影響外部變數,因為傳進來的是它的複製品;  而改變 call-by-reference 傳入的參數則會影響到外部變數,因為 alias 是指向同一個 value 的。

基於這樣的理解,在學習 Java 的時候遇到「只有 call-by-value」這樣的觀念,便在讓我產生了疑惑:「要怎麼讓傳入函數的變數隨著函數內部對它操作而跟著變動」,也就是說 Java 要怎麼做到 call-by-reference 的語意呢?

後來發現,原本我以為 Java 的 call-by-value 和 C++ 的 call-by-value 有相同的立足點 (將物件複製一份丟進函數) 實際上是錯誤的。

原來,在 Java 當中,除了原生型別的變數,一般型別的變數其實不是直接 hold 物件本身,而是 hold 物件的 reference!

這點跟 C++ 就有一點出入了,在 C++ 中要用一個變數 hold 一個物件的 reference,只得明確用指標,像是 Dog* aDog = new Dog;  這樣一來,操作上也得用 -> 運算子,像是 aDog->setName('Lucky');  如果是用 Dog aDog;aDog 這個變數就是指物件本身(傳進函數會被複製一份)。

Java 沒有指標的觀念 (全物件導向),除了原生型別,它的物件都需要用 new 建立 (跟 C++ 的 new 又不太一樣,C++ new 是用來動態配置記憶體用的)  如 Dog aDog = new Dog;  這裡的 aDog 並不是 Dog 型別的物件本身,而是物件的一個 reference

因此「要怎麼讓傳入函數的變數隨著函數內部對它操作而跟著變動」這個疑惑就解開了,Java 所謂的「只有 call-by-value」的 value 指的就是「物件的 reference」,既然物件的 reference 被複製一份進去函數,那當然可以透過函數內部操作該 reference 來改變外部的物件 (而且不需要用 -> 運算元)。

這裡又冒出一個問題,既然原生型別的物件在 Java 當中是直接 hold 物件的值,所以傳入函數參數的預設行為就是 call-by-value,那麼如果想要實現 call-by-reference 的語意該怎麼做呢?其實也很簡單,就是將該原生型別的變數包裝成一個陣列,再傳入函數即可。

public static void increment(int[] array, int amount)
{
   array[0] = array[0] + amount;
}

public static void main(String args[])
{
   int[] myInt = { 1 };

   increment (myInt, 5);

   System.out.println ("Array contents : " + myInt[0]);
}

參考資料:
Java is Pass-by-Value, Dammit! - Scott Stanchfield
http://javadude.com/articles/passbyvalue.htm

Q&A : How do I pass a primitive data type by reference?
http://www.javacoffeebreak.com/faq/faq0066.html

... ...

6/14/2011

[Android] Thread, Looper, Handler and MessageQueue

目標:

Handler, Message, MessageQueue, Looper 它們四個 class 只有一個共同的目標
就是讓程式碼,可以丟到其它 thread 去執行。這麼作有什麼好處呢 ??

Android 的 GUI 元件不是 thread safe的 (屬單線程模型,Android UI 操作並不是線程安全的,並且這些操作必須在 UI線程 中執行,無法 multi-thread 執行)。

Activity 的畫面顯示是由 UI Thread 所負責的,若是你寫了 mutlti-thread 程式,又想更新畫面,就必須要將 Thread 內部的一段程式碼,交由 UI Thread 來執行才行。

類別說明:

Handler:
提供 callback function,預期讓其它 Thread 執行!
但 Handler 又要如何 transfer 至其它 Thread 呢? 於是有了 Message!

Message:
將 Handler 包裝起來, 傳送給其它 Thread!
但是同時有多條 thread 不斷的在系統中傳遞 Message 那麼如何緩衝呢?

MessageQueue:
是為了讓 Message 能夠作緩衝,好讓 Message 先暫存起來。
因此,當 Message 已經被放在其它 Thread 上的 MessageQueue 之後, 它裡面包著 Handler, 而 Handler 上的 callback function 總得有人來執行吧?

Looper:
就是為了將 Message 由 Thread 所對應的 MessageQueue 取出來,並且拿出 Handler
來執行它上面的 callback function.

當 Looper.java 中的 loop() 被呼叫起來之後,它就是在反覆作這件事
不斷將 Handler 由 Message 取出來,並且執行 Handler 上的 callback function。


Attribute to - [Android 개발] Looper와 Handler

這裡可以參考兩個網路文章的範例:

1. Detecting Network Speed and Type on Android (Edge,3G) | Greg's Dev Blog

  • 這個範例當中展示了,override Handler 物件 (此 handler 綁定 UI thread) 當中的 handleMessage 方法,對 MessageQueue 當中不同的 message 作處理 (利用 switch case 判斷message 更新 UI)。
  • 宣告了一個 Runnable 物件,並在 button 按下去的時候開啟一個新的 thread (以該 Runnable 物件初始化該 thread) 執行下載的任務,注意,在下載任務執行的代碼中,利用 mHandler.sendMessage() 將 message 傳入 UI thread 的 MessageQueue 當中進行 UI 更新。

2. Android Guts: Intro to Loopers and Handlers | Mind The Robot

  • 不同上面的範例,此範例將 Download 寫成一個獨立的 class (DownloadThread.java) 繼承 Thread,並且覆寫 run 函式,在其中實現 Looper 機制,負責處理 MessageQueue 中的任務 (範例中只是用一個計時器模擬下載任務)。
  • 而 DownloadQueueActivity 這個主要的 UI thread 包含一個 DownloadThread 成員,並且實現了 DownloadThreadListener 介面。在建構式中,將自己指定為 DownloadThread 成員的 Listener。由此,DownloadThread 可以調用 handleDownloadThreadUpdate 這個介面函式,讓 UI thread 做更新。反向來看,點擊 DownloadQueueActivity 當中的按鈕,則可以向 DownloadThread 的 MessageQueue 添加任務 (利用 enqueueDownload 函式)。

若想要更進一步瞭解細節可以依序參考下面的資料!


參考資料:

清楚瞭解 android.os 源碼中的 Looper,Handler,Message,MessageQueue | Milochen's Blog for hacking
http://milochen.wordpress.com/2011/03/25/understanding-android-os-src-looperhandler-message-messagequeue/

Android Guts: Intro to Loopers and Handlers | Mind The Robot
http://mindtherobot.com/blog/159/android-guts-intro-to-loopers-and-handlers/

Handler, Looper, Thread | Eddy@Joomla!藏經閣
http://blog.joomla.org.tw/android/173-Handler-Looper-Thread.html

Android 講義摘錄 | Google Android 論壇
http://www.android1.net/Topic.aspx?BoardID=11&TopicID=294

Android的線程使用來更新UI - Thread、Handler、Looper、TimerTask 等 | 山嶺巨人
http://www.cnblogs.com/playing/archive/2011/03/24/1993583.html

Android – Thread Messaging | DK's Blog
http://codinghard.wordpress.com/2009/05/16/android-thread-messaging/



... ...

6/10/2011

[Android] SharedPreferences - a example of application components share "SharedPreferences" Data



此範例展示如何利用 SharedPreferences 作為 application components 交換資料的方式。並且在程式起始的時候讀取 SharedPreferences 的內容,並有一清除 SharedPreferences 的按鈕。

Download source

參考資料:

Data Storage | Android Developers
http://developer.android.com/guide/topics/data/data-storage.html

Android數據存取之Preferences
http://www.roiding.com/index.php/archives/72

... ...

[Android] AsyncTask - a file downloading example with progress bar



Android single-threaded model:
1. Do not block the UI thread, and
2. Make sure that you access the Android UI toolkit only on the UI thread.

AsyncTask just makes it easier to do both of these things.

This example implement a AsyncTask downloader with a progress bar, Enjoy it :)
Download source

參考資料:

Painless Threading | Android Developers
http://developer.android.com/resources/articles/painless-threading.html

How to Use AsyncTask for Android
http://www.brighthub.com/mobile/google-android/articles/82805.aspx

AsyncTask | Android Developers
http://developer.android.com/reference/android/os/AsyncTask.html

... ...

6/02/2011

[C++] Reference 和 Pointer 的差異

在 C++ 當中 Reference 和 Pointer 都是一種間接取值的方法,既然兩者的功能那麼相近,到底為什麼要有 Reference 的存在呢?針對找到的資訊作一些整理如下:

  • Reference 和 Pointer 在功能和使用上的差異
  1. A pointer can be re-assigned any number of times while a reference can not be reassigned after initialization
  2. A pointer can point to NULL while reference can never point to NULL
  3. You can't take the address of a reference like you can with pointers
  4. There's no "reference arithmetics" (but you can take the address of an object pointed by a reference and do pointer arithmetics on it as in &obj + 5)

C++ 標準並沒有規定 compiler 要怎麼實作 Reference,但是似乎背後還是用指標的方式實現,所以在效能上並無差異。

  • Reference 的存在意義
  1. I believe the key insight into why C++ has reference types as well as pointer types is that reference types enable overloaded operators to look like built-in operators, as well as act like them.
  2. Pointers can do almost everything that references can do, but they can lead to expressions that don't look right. On the other hand, references have some restrictions that make them less convenient than pointers for implementing algorithms and data structures. References reduce, but do not eliminate, the need for pointers.
  3. As a general rule, use references in function parameters and return types to define attractive interfaces. Use pointers to implement algorithms and data structures.

參考資料: