2015年1月31日 星期六

[C++] string 轉 char array



==========================================


  1.  #include <iostream>

  2. using namespace std;


  3. int main(){

  4.      string s;

  5.      cin >> s; // input

  6.      char c [s.length()];
  7.     
  8.      for(int i=0; i<s.length(); i++){
  9.           c[i] = s[i];
  10.       }
  11.    
  12.    return 0;
  13. }

===========================================


[C++] size_t 介紹


size_t 类型在C++上是定义在cstddef头文件中,而在C上是定義在头文件stddef.h 中。
它是一个与机器相关的unsigned类型,其大小足以保证存储内存中对象的大小。

中文名:size_t
外文名:unsigned int

在C++中,设计 size_t 就是为了适应多个平台的 。size_t的引入增强了程序在不同平台上的可移植性。size_t是针对系统定制的一种数据类型,一般是整型,因为C/C++标准只定义一最低的位数,而不是必需的固定位数。而且在内存里,对数的高位对齐存储还是低位对齐存储各系统都不一样。为了提高代码的可移植性,就有必要定义这样的数据类型。一般这种类型都会定义到它具体占几位内存等。当然,有些是编译器或系统已经给定义好的。经测试发现,在32位系统中size_t是4字节的,而在64位系统中,size_t是8字节的,这样利用该类型可以增强程序的可移植性。




文章出處:size_t 百度 http://baike.baidu.com/view/3236587.htm

2015年1月29日 星期四

C++ 字串函數 (String method)






C++ 內置了一個String類別,內裡有很多函數給予我們處理字串的運算。


最常用有以下:


方 法 說 明
assign(string, start, num) 從string的第start個字元取出num個字元來指定給另一字串物件。
append(string, start, num) 從string的第start個字元取出num個字元來附加至另一字串物件之後。
find(string, 0) 從引發find的字串物件第0個字元尋找是否有符合string的子字串。
insert(start, string) 將string插入引發insert的字串物件第start個字元之後。
length() 傳回字串的長度。




===================================

// assign 的使用

#include <iostream>
#include <stdlib.h>
#include <time.h>

using namespace std;


int main(){

    string str1;
    str1 = str1.assign("c++isfunny", 5, 6);
    cout << "str1: " << str1 << endl;
  
    return 0;
  
}

====================================

- output : funny
- 注意的是,就算第3個參數-->6 可能已經超出字串範圍,但都不會造成error的。


*有學習JAVA的朋友可能會覺得assign method和java裡的substring method 相當相似,但其實並不
一樣的,substring函數是 String substring(int beginIndex, int endIndex),第二個參數是endindex,即字串只會copy到endindex前一個字符就會停,與assign函數是不同的。




C++ 亂數函數 rand() 和 srand()




所謂的亂數,即是指電腦自動產生的一個數字,好似一個六合彩號碼般,
無永遠沒法知道下一個出現的號碼。而C/C++的亂碼其實是由一個亂數產
生器產生的,函數名稱是rand,放在stdlib.h / cstdlib 表頭檔裡面,在使用
時直接呼叫 rand() 便可。


註:若果你不明白表頭檔 <stdlib.h> 是什麼 ,可以到這篇文章看看-->> stdlib.h介紹





Rand() 和 Srand()



先來個rand()使用的示範:
==================================

  1. #include <iostream>
  2. #include <stdlib.h>    // 引入表頭檔

  3. using namespace std;  

  4. int main(){

  5.     for(int i=0; i<5; i++){
  6.         cout<< rand() << endl;    // 印出5個亂數
  7.     }
  8.  
  9.     return 0;
  10.    


===================================



你可能會好奇,那究竟這些亂數的範圍到底是多少呢?

目前可以確定的是,最大值(RAND_MAX) 至少會是 0x7fff (轉換10進制後是32767),
最大會是多少不一定。以 Visual C++ 2010 環境而言,這個值是 32767。實際上
VC6.0 , VC2002 / 2003 , VC2008, VC2010 , gcc, Dev-C++ , Code::Blocks (with mingw) ,
這個值也都剛好是 32767,只是他們實作的亂數細節不同而已。但新版的版本的
RAND_MAX 會更大,例如在mac上用xcode開發的C/C++,最大值便是2147483647(231-1)
主要是看軟體( compiler )的實作方式,若想查下最大值是多少,不坊用以下程式測試一下:



========================
  1. #include <iostream>
  2. #include <stdlib.h>
  3. using namespace std;
  4. int main(){
  5.  
  6.     cout<< RAND_MAX;
  7.  
  8.     return 0;
  9.    
  10. }
========================


另外,當你不停用rand() run最初的程式時,會發現產生出來的亂數都是一樣的,因為rand()產生
的是偽隨機數字,每次執行時都是相同的,給果想要不同,就要使用srand()函數初始化它。

在預設的情況下,rand()的隨機種子(seed :指起始點,即最小值) 是1,而相同的隨機種子
產生的結果都是一樣的。那初始值該給多少?初始值給固定的值都沒用,要會隨著環境變動
的值才有意義,像是 記憶體使用量、process id 、CPU 使用率 等,這些都是會隨環境變動,
但有些變動性可能不大,而最常用來給初始值的,是時間,所以程式可以修改如下:


===========================================

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4. int main()
  5. {
  6.     int i;
  7.     unsigned seed;
  8.     seed = (unsigned)time(NULL); // 取得時間序列
  9.     srand(seed); // 以時間序列當亂數種子
  10.     for(i=0; i<5; i++)
  11.          cout << rand() << endl; 
  12.     return 0;
  13. }

===========================================


註:

- 7-9 行可以縮短為 srand( (unsigned) time(NULL) );

- time(NULL),傳入值為NULL可以獲取當前時間的總秒數(從 00:00 hours, Jan 1, 1970 UTC 起),
  實際語法如下, time_t time (time_t* timer) 。

- 如果不明白什麼是 unsigned ,請先看這篇文章--> Unsigned keyword







Rand() 指定範圍



-需要使用%運算子,如果不明什麼是%,就GOOGLE一下吧。

程式如下:

================================

  1. #include <iostream>
  2. #include <stdlib.h>
  3. #include <time.h>

  4. using namespace std;


  5. int main(){

  6.     srand( (int)time(NULL));
  7.  
  8.     for(int i=0; i<5; i++)
  9.     cout<< rand()%6+2 <<endl;
  10.  
  11.     return 0;
  12.    
  13. }

================================


以上程序運行後,將會輸出5個號碼,範圍由 2~7 。

-rand()%6 :即指定範圍需要由起始數開始取6個數值,包括起始數
-rand()%6+2 :+2 的意思是指定起始數是2,然後由2開始取六個數作為range(包括2),
                           若沒有+2,起始數預設是0。










C++ stdlib.h 介紹

 
stdlib 意思即 standard library 標準庫頭文件
 
stdlib 包含了C、C++语言的最常用的系统函数
 
常用的函数如malloc()、calloc()、realloc()、free()、system()、atoi()、atol()、rand()、srand()、exit()等等。
 
具體內容可以自己打開編譯器的include目錄裡的 stdlib.h 頭文件看看。

C++ Unsigned keyword



Unsigned keyword 是一個 data type specifier, 即無符號的意思,

其只可以用於表示一個正數和0,只可應用係 char, short, int , long
的data type, 例如:

int typically 的值是 -32768 to 32767  ,那 unsigned int 的值會是 0 to 65535,
沒有負數。

當你知道變量的值永遠不會是負數,你就可以採用unsigned了。


更多說明:

一個32bit的int,會有1bit用於記住該數的正負號,但當使用了unsigned int,
則所宣告的變數只能存放正數,由於沒有正負之分,不再需要借用1bit去記
住正負號,可儲存的正數範圍就可以增加了一倍,因為數值的位元多了一位。

例如:

int 值的範圍 : -231 ~ 231-1
unsigned int 值的範圍 : 232-1  //  -1 的意思是因為要包含全0的組合。

- unsigned int 可簡寫為 unsigned
- unsigned short int 可簡寫為 unsigned short





2015年1月28日 星期三

C++ iostream.h 和 iostream 的分別


 很多c++書上都喜愛用
 #include <iostream.h>

 但對於現在新的IDE可能已經不能編譯了

 以前的寫法
  #include<iostream.h>
  int main()


 新定的標準寫法
  #include<iostream>
  using namesapec std;
  int main()


  <iostream> 定義輸出輸入的函式
  但 cout 本名為 std::cout
       cin 本名為 std::cin

 所以要使用 名稱空間(namespace) std

 早年這個名稱空間有定義在 <iostream.h>

 現在的新編譯器可能沒有這個功能了 所以會編輯失敗!




C++ Pointer 與 Array




指標(Pointer)其實是"箭頭",內容其實是位址(Address)


Pointer 和 Array 可以說是 “兄弟關係” ,  關係相當緊密。




Pointer 與 一維陣列 


例如:

 int a [] = { 1, 2, 3, 4, 5 };

 a[3] 可以represent為 *(a+3)
 a[0] 可以represent為 *(a+0) or *a <-- *a的起始值是a[0]


或者可以用一個pointer指住一個array,
e.g. int *p = a;   // 此方法只適用於一維陣列,多維陣列的宣告方法會於文章末端提及。



此時, 若a陣列記憶體位址分佈如下:

a[0] =  12000
           12001
           12002
           12003

a[1] =  12004
           12005
           12006
           12007

a[2] =  12008
           12009
           12010
           12011
......
......


p = 12000, *p = a[0] = 1;
p+1 = 12004, *(p+1) = a[1] = 2;
p+2 = 12008, *(p+2) = a[2] = 3;

註: *p+1 和 *(p+1) 的意思是不同,
      *p+1 會等於 2 , 意思是指先把*p的值
      拿出來,然後再+1。





Pointer 與 多維陣列


例如:

int a[2][4] = { {1,3,5,7} , {2,4,6,8} };

陣列表示法 連續記憶體表示法 陣列索引值轉換表示法
a[0][0] 1 **a *(*(a+0)+0)
a[0][1] 3 *(*a+1) *(*(a+0)+1)
a[1][0] 2 *(*a+4) *(*(a+1)+0)
a[1][3] 8 *(*a+7) *(*(a+1)+3)

註:Pointer會把一個多維陣列中每欄的element都編上
       一個次序,例如第一欄 {1,3,5,7} ,所得的次序就是
       0-3 , 接著第二欄 {2,4,6,8} ,所得次序就是4-7。
       例如 *( *a+7 ) 中,由於 *a 值是 0 , 所以*a+7 得出
       是7,然後 *7 即是指排在第7元素的值,即是第二欄
       的第4個element的值, 即是8。



- 在二維陣列的記憶體裡的位置是連續的儲存空間

- *( *(a+i) + j )  == a [ i ] [ j ] ;

- a[0][1][3] == *( *( *a+1)+3 ) ;
- a[1][2][3] == *( *( *(a+1) + 2 ) +3 );






Exercise: 


#include <iostream.h>
void main() {

       int a [3] [4] = { {1,3,5,7} , {2,4,6,8} , {10,20,30,40} };
 
       int *p = &a[0][0];
       int *pp = a[0][0];
       int *p0 = a[0];  // p0的起始點會是a[0][0]
       int *p1 = a[1];  // p1的起始點會是a[1][0]
       int *p2 = a[2];
 
       cout << *(p+4+1) << endl;
       cout << *pp << endl;
       cout << *(p0+2)  << endl;
       cout << *p1  <<endl;
       cout << *(p2-2) <<endl;
       cout << *p2[3] <<endl;
    
}



output:
4
1
5
2
6
40




* 常見問題!


知道一維宣告方法是

int *arr = new int[1];

但是換成了

int *arr = new int[1][1];

就出錯了,為什麼呢?



解答:

==============================

當宣告一維陣列時,可以

const int x=10;
int obj[x];

用指標宣告方法:

const int x=10;
int *obj = new int[x];

================================

但當宣告二維時,必須使用**,
以便逐一由內而外配置。

const int x=10, y=20;
int **obj;
obj = new int*[x];  // 第一次分配第一維

for(int i=0; i<x; ++i) {
       obj[i] = new int [y]; // 第二次分配第二維
}



=================================

三維陣列做法一樣

const int x=10, y=20, z=5;

int ***obj;

obj = new int**[x]; // 配置一次少一個星

for(int i=0; i<x; ++i) {

       obj[i] = new int*[y];  // 再配置一次,再少一個星

       for(int j=0; j<y; ++j) {
                 obj[i][j] = new int[z];  // 再配置一次,再少一個星
       }
}



C++ Pointer 指標介紹 (2)


Pointer 有一個很大的用處,就是動態記憶體配置(Dynamic Memory Allocation)。

c++ provide了兩個有關Dynamic Memory Allocation的operator :
1. new : 申請配置記憶體,自己控制記憶體大小。
2. delete : release所配置了的記憶體空間。


new 語法:

(data type) *(pointer variable) = new (data type) [size];

e.g.

int *ip = new int [4];  // pointer ip 將會使用 16bytes , 因為int type 是佔 4bytes, 4*size = 16 bytes
float *fp = new float [4];

or

int *ip = new int;
float *fp = new float;

註:不一定需要size的指定,如果沒有指定,compiler會以size=1為依據。




delete 語法:

delete (pointer variable)

e.g.

int b = 10;
int *a = &b;

delete a;  // 將會release a 指向b的記憶體空間

宣告後的記憶體,如果程式不會再用到,就可以使用delete來release記憶體空間,
防止程序執行期間有記憶體空間不足的情況發生。






2015年1月27日 星期二

Java - 陣列大小排序方法

  1. public class output{
  2. public static void main(String[]args){
  3. int a [] = { 10, 30, 20, 40, 50, 15};
  4. bubbleSorting(a);
  5. printAll(a);
  6. a [] = { 10, 30, 20, 40, 50, 15};
  7. selectionSorting(a);
  8. printAll(a);
  9. }

  10. static void bubbleSorting(int[]a){
  11. for(int i=0; i< leng-1 ; i++){
  12. for(int j=0; j< leng-1-i ; j++){
  13.     if(a[j] > a[j+1]){   // 小至大 ,調轉就是大至小
  14.          int temp = a[j];
  15.          a[j] = a[j+1];
  16.          a[j+1] = temp;
  17.      }
  18. }
  19. }

  20. static void selectionSorting(int[]a){
  21. for(int i=0; i<a.length; i++){
  22.              int index=i;
  23.              for(int j=i+1; j<a.length; j++){
  24.                 if(a[index]>a[j])
  25.                      index = j;                    
  26.              }
  27.              int tmp = a[i];
  28.              a[i] = a[index];
  29.              a[index] = tmp;
  30.           }
  31. }
  32. }

  33. static void printAll(int[]a){
  34.   for(int i=0; i<a.length; i++)
  35.    System.out.println(a[i]);
  36. }

Android GridView - 使用 BaseAdapter 建立 和 更新


在建立方面:


以下方法取自Kelvin Chan,使用BaseAdapter建立一個gridview,
並對gridview中每一格作出仔細的處理,藉此達成顯示不同的效果,
此方法雖然比較複雜,但可以套用在不同的控件上,例如ListView和
Spinner等等,可以說是萬能!














<-- 目標












 







Step 1 :  建立XML文件




























按上圖可見,在Project的res->layout 下有兩個xml文件,
1. activity_main.xml : 這個xml檔是用來規劃MainActivity.java
    在建立android project時已經預設建立好,無需再自行建立。
2. listitem.xml : 這個xml檔需要自行建立,
    方法是先R-click layout -> New -> Android XML file
    在 file : 打上listitem,其他設定default就好了。
    這個xml作用是用於規畫GridView中每個格仔的佈局。






Step 2 :  修改兩個 XML文件

1.在 activity_main.xml 中,


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:paddingBottom="@dimen/activity_vertical_margin"
      android:paddingLeft="@dimen/activity_horizontal_margin"
      android:paddingRight="@dimen/activity_horizontal_margin"
      android:paddingTop="@dimen/activity_vertical_margin"
      tools:context=".MainActivity" >


    <!-- 加設一個GridView -->
   
    <GridView
        android:id="@+id/gridview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#DCDCDC"
        android:gravity="center"
        android:horizontalSpacing="1dp"

        android:verticalSpacing="1dp"
        android:numColumns="7"
        android:stretchMode="columnWidth"

     >
    </GridView>

   

   

</RelativeLayout>


- 灰色部份已經在建立Project時預設了,可以忽略,主要是增設黃色部份。
- horizontalSpacing : 定義列之間的間距
- verticalSpacing :定義欄之間的間距
- stretchMode:格子拉伸模式
  ( none:不要伸縮 /
   spacingWidth:拉伸每列的間距 /
   columnWidth:拉伸每格 /
   spacingWidthUniform:均勻拉伸間距)



2. 在listitem.xml中,


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
   

    <TextView
        android:layout_width="match_parent"
        android:layout_height="70dp"
        android:background="#ffffff"
        android:textSize="20sp"
        android:id="@+id/tv"></TextView>

   
</LinearLayout>


註:TextView 將會題示數目字






Step 3 : 建立兩個自設類別及修改主程序


  1. package wtf.kyl.blog;
  2. import java.util.ArrayList;
  3. import android.app.Activity;
  4. import android.content.Context;
  5. import android.graphics.Color;
  6. import android.os.Bundle;
  7. import android.view.LayoutInflater;
  8. import android.view.View;
  9. import android.view.ViewGroup;
  10. import android.widget.BaseAdapter;
  11. import android.widget.GridView;
  12. import android.widget.TextView;

  13. public class MainActivity extends Activity {
  14.           // 宣告所需元件
  15.           GridView gv; 
  16.           Adapter adapter;  // 將會繼承baseadapter
  17.           Item item;   // 一個自設的class object, 指的是每個格仔, 待會需要create 42個 Item 物件
  18.           ArrayList <Item> ary_items;  // 就像一個容器裝載全部的 Item 物件
  19.           int total = 42; //  共需建立的格仔總數,預設就42吧

  20.          @Override
  21.          protected void onCreate(Bundle savedInstanceState) {
  22.                super.onCreate(savedInstanceState);
  23.                setContentView(R.layout.activity_main);
  24.        
  25.                GridView gv = (GridView) findViewById(R.id.gridview);
  26.            
  27.               ary_items = new ArrayList<Item>();  // 建立一個容器
  28.               addItems(total); // 自設類別方法處理建立Item物件, 日後在更新GridView時將會大派用場。
  29.               adapter = new Adapter(this, ary_items);  // 建立適調器,並傳入兩個Arguments,
  30.                                                                                // this指當前activity,ary_items就是容器,執行
  31.                                                                                // addItems()後,容器已經裝住了42個Item物件
  32.               gv.setAdapter(adapter);  // 告訴Gridview知道它的適調器是adapter
  33.        
  34.     }
  35.     public void addItems(int total){    // 自設方法
  36.            for(int i=1; i<=total; i++){  // loop total=42 times
  37.                 
  38.                  item = new Item(); // 每次建立一個item物件
  39.                  item.day = i;     // 告訴 item 物件中 day 這個變量的值是 i
  40.                 
  41.                  if(i%2==0) item.isEvenNumber = true;  // odd and even checking
  42.                  else item.isEvenNumber = false; 
  43.                 
  44.                  ary_items.add(item);   // 把item物件扔進容器ary_items
  45.                 
  46.            }
  47.     }
  48.    
  49.    
  50. }
  51.   class Item {   // 自設item類別
  52.       int day;
  53.       boolean isEvenNumber;
  54. }
  55. class Adapter extends BaseAdapter{
  56.    
  57.     Context context;  // context 會指向mainactivity
  58.     ArrayList<Item> ary_items;   // 容器,已經裝滿42個item物件
  59.     
  60.     // 自設Default Constructor,用以接收activity和容器
  61.     public Adapter(Context context, ArrayList<Item> ary_items){
  62.            this.context = context;   
  63.            this.ary_items = ary_items;
  64.     }
  65.    
  66.    // Overriding BaseAdapter中的內建方法
  67.     @Override
  68.     public int getCount() {   // item總數量
  69.         // TODO Auto-generated method stub
  70.         return ary_items.size();
  71.     }
  72.     @Override
  73.     public Object getItem(int arg0) {  // 無須理會,在處理點擊事件時才會調用
  74.         // TODO Auto-generated method stub
  75.         return 0;
  76.     }
  77.     @Override
  78.     public long getItemId(int arg0) {  // 無須理會,在處理點擊事件時才會調用
  79.          // TODO Auto-generated method stub
  80.         return 0;
  81.     }
  82.     @Override
  83.     public View getView(int arg0, View arg1, ViewGroup arg2) {  // arg0 = 每格的ID
  84.        
  85.        
  86.         if(arg1==null){
  87.             LayoutInflater a = LayoutInflater.from(context);   // LayoutInflater可以幫助我們把
  88.             arg1 = a.inflate(R.layout.listitem, null);          //  listitem中的佈局FIT返每一格的SIZE
  89.         }
  90.        
  91.         TextView tv = (TextView) arg1.findViewById(R.id.tv);
  92.         tv.setText(""+ary_items.get(arg0).day);
  93.         if(ary_items.get(arg0).isEvenNumber==true) tv.setTextColor(Color.RED);
  94.         if(ary_items.get(arg0).day == 26) tv.setBackgroundColor(Color.GREEN);
  95.         if(ary_items.get(arg0).day == 17) tv.setBackgroundColor(Color.YELLOW);
  96.         return arg1;  // arg1 指該格仔,android中視每一格為一個view
  97.     }
  98.       
  99. }





********************************

在更新方面:


增加兩個Button作測試,並利用adapter告知GridView需要更新






   






  <﹣﹣最終目標
















Step 1 : 在activity_main.xml檔加設Button控件


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >
   
   
    <!-- 加設一個GridView -->
         
    <GridView
        android:id="@+id/gridview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#DCDCDC"
        android:gravity="center"
        android:horizontalSpacing="1dp"
        android:numColumns="7"
        android:stretchMode="columnWidth"
        android:verticalSpacing="1dp"
     >
    </GridView>

   
   
    <!-- 新增兩個Button, 用LinerLayout作打橫排序 -->
   
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true">
   
   
      <Button
        android:id="@+id/button1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1">
       
     </Button>
     <Button
         android:id="@+id/button2"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:layout_weight="1"></Button>
    
     </LinearLayout>
</RelativeLayout>




Step 2 : 修改MainActivity.java


  1. @Override
  2.     protected void onCreate(Bundle savedInstanceState) {
  3.         super.onCreate(savedInstanceState);
  4.         setContentView(R.layout.activity_main);
  5.        
  6.         GridView gv = (GridView) findViewById(R.id.gridview);
  7.            
  8.         ary_items = new ArrayList<Item>();
  9.         addItems(total);
  10.         adapter = new Adapter(this, ary_items);
  11.         gv.setAdapter(adapter);
  12.        
  13.        
  14.         // 增設兩個Button
  15.         Button btn_add = (Button) findViewById(R.id.button1);
  16.         btn_add.setText("add one");
  17.         Button btn_del = (Button) findViewById(R.id.button2);
  18.         btn_del.setText("delete one");
  19.        
  20.         // 建立點擊事件,需要import android.view.View.OnClickListener;
  21.   
  22.         btn_del.setOnClickListener(new OnClickListener(){
  23.             @Override
  24.             public void onClick(View arg0) {
  25.                    total--;   
  26.                    ary_items.clear();   // 把容器中的Item全部清除
  27.                    addItems(total);     // 重新加入Item
  28.                    adapter.notifyDataSetChanged(); // 利用Adapter告知GridView需要更新Item
  29.             }
  30.            
  31.         });
  32.        
  33.         btn_add.setOnClickListener(new OnClickListener(){
  34.             @Override
  35.             public void onClick(View arg0) {
  36.                 // TODO Auto-generated method stub
  37.                 total++;
  38.                 ary_items.clear();
  39.                 addItems(total);
  40.                 adapter.notifyDataSetChanged();
  41.                
  42.             }
  43.               
  44.         });
  45.        
  46.        
  47.     }


完成:D

Java - Overloading (多載) 和 Overriding (覆寫) 介紹

Overloading 和 Overriding 都是OOP中相當重要的概念,
很多時我們在coding的時候都會使用到這兩個概念,例如
call 一個 string indexOf() method 或是 charAt() method
都是使用緊Overloading的概念。


Overloading 多載 

- 指在一個類別(class)中,定義多個 相同名稱 ,
  但 參數(Parameter) 不同 的函式(Method)。


在JAVA內置的String 類別中,擁有多個相同名稱的class method,例如

public int indexOf(int ch)
public int indexOf(int ch, int fromIndex)
int indexOf(String str)
int indexOf(String str, int fromIndex)

- 以上四個函式都有相同名稱叫作 indexOf , 可是他們當中的Parameter就不同了,
這就是所謂的Overloading多載了。


- Parament 是指在method 名稱後面用( ) 包住的變量,
  例如 public int indexOf(int ch, int fromIndex)函式中,
  ch 和 fromIndex 便是Parameter了。


用途:當我們想調用indexOf這個函式,可以pass不同的argument(引數) 去調用不
同的indexOf函式, 因為JAVA懂得自己根據argument呼叫對應的函式,舉個例子,

String str = "abc";
int result1 = str.indexOf('a'); // 將會調用 public int indexOf(int ch) 函式
int result2 = str.indexOf("c", 1); // 將會調用int indexOf(String str, int fromIndex) 函式

註:
argument是指當我們 invoking a method 的時候, 我們給予method的 
一個 value of desired data type 或 一個 object reference 。

在上面的例子,‘a', "c" 和 1 就分別是char, string and int date type的引數 (argument) 。  





Overriding (覆寫)

- 指一個子類別將會extends(繼承) 父類別,並改寫父類別已定義好的method。
- 在Overriding的過程中,argument, parameter, method name, return type都必須相同,
  但return的值就可以不同了。

舉個例子:
class shape{
         public double getArea(int length, int height){
                   return length*height;
         }
}

class triangle extends shape{
         public double getArea(int length, int height){
                    return (length*height)/2;
         }
}

- 在此,類別triangle繼承了父類別shape,並共同擁有getArea() method,
  只是return value不同,但return type 都是double。

用途:Overriding可以在不改動父類別一早寫好的method下,通過extends方式,
從而獲取父類別的method,作出所需的改動,從而獲得不同的result。
在Android的開發中,Overriding的使用可以說是無處不見。

 

 

2015年1月26日 星期一

C++ Pointer 指標介紹 (1)

Pointer 是一個可以儲存位址的變數,

宣告方法:在資料型態後面加上星號*,例如:

int *p;
int* p;
int*p;

以上宣告方法都是合法的。

現在,指標變數p可以存放int data type 資料的位址了。





C++提供了兩個一元運算子( unary operators) 可計算出變數的 位址 和 其所指的資料。

1.  *  : Pointer dereference : 傳回位址資料數值。
2.  & : Address-of : 傳回起始位址。




=======================================================

Example 1:

int v  = 5 ;
int *p = &v;
int v2 = *p;

假設v的位址是12000,
Result 便會是 : v = 5 , *p = 12000 , v2 = 5,

(註:int 佔用的空間隨電腦機型而定,以32位元電腦來說,佔用了4byte,
        而 v 便佔用了記憶體位址的12000~12003 , 另外,任何data type的
        指標變數所佔用的記憶體空間皆為4byte。)

=======================================================

Example 2:

Given
&v   = 0x0065FDF4 ;
&p   = 0x0065FDF0;
&v2 = 0x0065FDEC;

int v=5;
int *p = &v;
int v2 = *p;


Result:
&v    = 0x0065FDF4
v       = 5;
&p    = 0x0065FDF0
p       = 0x0065FDF4
*p      = 5;
&v2   = 0x0065FDEC
v2     = 5

=======================================================

Example 3:

Given
&v   = 0x0065FDF4 ;
&p   = 0x0065FDF0;
&v2 = 0x0065FDEC;

int v=5;
int *p = &v;
int v2 = *p;


Result:

&p        =  0x0065FDF0 
p          =  0x0065FDF4
p+1      =  0x0065FDF8  (int 佔4 byte so 0x0065FDF4 + 4)
*p         =  5
*(p+1)   =  未知數,但其的目標地址將會是 0x0065FDF8,若此地址包含
                 了一個數值如10,那 *(p+1)得出的值就不是未知數了,會是10。

=======================================================





C++ 電腦記憶體位址及其16進制


*位址就是電腦所儲存資料的記憶地址
*16進制,一般用數字0到9和字母A到F表示(其中:A~F10~15
 
位址通常以十六進制顯示 e.g. 0x0065FDF4
0x <- 代表該數將以十六進制顯示
0065FDF4 中每個數字都佔據 4bit ,
因為轉換為二進制時每個數值都需要使用4bit,

例如:6的16進制轉換為2進制便是 0110,
而16進制最大值F的2進制是 1111 。

16進制轉換10進制的過程:
2A1F(16進制) = 163 x 2  +  162 x 10 + 161 x 1 + 160 x 15 = 10,783 (十進制)



































- 從 0x0065FDF4 這個地址上可以推算電腦是運行32bit , 因為4bit x 8 = 32bit.
- 一部32bit電腦最多只可以擁有232 個物理層地址(Total 4GB),
  因為ram是線性,所以每個physical address入面可以存放無限bit的虛擬位址。

- 而每個windows程序也會有自己的虛擬地址

- 值得一提的是,電腦儲存位址的方式是倒轉放,例如:
  當一個物理地址0x0001存放著 1個位元組(byte)的空間 0x34 ,
  那該位址便會是0x3401,而Pointer亦會指向0x3401該位址。





Android - 建立/刪除 多個鬧鐘 (Alarmmanager) 的教學

建立多個鬧鐘



Step 1: 建立鬧鐘接收器


﹣1.1 : 在建立好android project後,自行建立一個.class檔, 名為AlarmReceiver ,
project -> src -> package -> R-click -> New -> Class ,
如下圖:




















-1.2 : 繼成BroadcastReceiver, 並覆寫onReceive方法























- 每當鬧鐘觸發時,便會調用這個接收器,並執行onReceiver中的程序。



-1.3 : 最後在Project的AndroidManifest.xml中註冊這個AlarmReceiver

*緊記要把<receiver></receiver>標纖寫在<application/>中



























Step 2 : 設定和建立多個鬧鐘






- 執行以上程序後,30個鬧鐘便會建立,並同時在2014年1月1日的10時10分10秒 觸發並執行AlarmReceiver中onReceiver的程序。


備註:

-AlarmManager.RTC_WAKEUP :  指鬧鐘在睡眠狀態下會喚醒系統並執行提示功能
-AlarmManager.RTC : 指鬧鐘在睡眠狀態下不可以使用。
-AlarmManager.POWER_OFF_WAKEUP : 指在手機關機的狀態下也能正常進行提示功能。


- 若想每日都重覆觸發鬧鐘,可以使用alarmmanager中的setrepeating
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 86400000, pi);
- System.currenTimeMillis() 會拿取當前系統的時間,單位是毫秒(1秒=1000毫秒)
- 86,400,000 毫秒 = 24小時


- 在此,pi是指一個pendingintent, 即是等待,未決定的意圖,當中有4個參數
參數1:this : 指當前的context, 即activity
參數2:i 是指requestCode , 可以當作每個 pi 攜帶的身份id
參數3:intent : 指將會觸發的activity, 在此, AlarmReceiver.class 便會是我們的最終目標
參數4:4個選擇
- FLAG_CANCEL_CURRENT:如果該PendingIntent已經存在,則會先取消當前的pi,再建立新的pi。
- FLAG_NO_CREATE:如果該PendingIntent不存在,直接返回null而不是創建一个PendingIntent.
- FLAG_ONE_SHOT:該PendingIntent只能用一次,在send()方法執行後,自動取消。
- FLAG_UPDATE_CURRENT:如果該PendingIntent已經存在,則用新傳入的Intent更新當前的數據。




取消多個鬧鐘


取消多個鬧鐘比較容易處理,例如我們先前已經利用FOR LOOP建立了30個鬧鐘,
我們可以再利用FOR LOOP取消這30個鬧鐘:




- 完成:D