目前分類:未分類文章 (13)

瀏覽方式: 標題列表 簡短摘要

Total = $11,100

  • Intel Pentium G4500 , $2700
  • 技嘉 B150M-D3H , $2790
  • 美光 8G DDR4-2133 , $799
  • Toshiba 1TB (DT01ACA100), $1680
  • 華碩 24XSATA燒錄器 , $459
  • 銀欣 PS11-Q , $1499
  • 海韻 S12II-430W , $1490

kcw 發表在 痞客邦 留言(0) 人氣()

想要找 Java 教材:
http://programming.im.ncnu.edu.tw/J_index.html


1. function 一定要明確 "指出" 回傳值 void int... JAVA 很在意這個

--

public class myExcep
{
  public static void main(String args[])
  {
    java.util.Scanner sc = new java.util.Scanner(System.in);
    int num = sc.nextInt(); /* 當輸入不是 int 時,會出現 exception  */
    System.out.println(x);  /* java.util.InputMismatchException */
  }
}

--

switch (grade)
{
  case 'A':
    System.out.println("ok");
    break;
  case 'B':
    break;

}

--

陣列在存取時超出範圍,會發生例外狀況

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10

如果存取一個並未配置空間的陣列參考,會出現
Exception in thread "main" java.lang.NullPointerException
--

Call by Value: 基本型別 (int, float, String...)
Call by Reference: 陣列、物件

foo (int tmp[][]) { do something ... }

bar {
  int num[][] ={ {1,2}, {3,4} }
  foo (num);  /* 這邊是call by reference,所以把參照 num 值拷了一份給 tmp*/
}


--

類別方法(Class Methods)
就是用 static 描述的方法,不用生出物件也可以直接呼叫

class myExample
{  public static void showName()
   {  System.out.print("name: Peter");
   }
}


類別變數(Class Variables)
成員變數屬於類別本身,當類別第一次建立時,就配置變數的記憶體
class myExample
{
  public static double PI=3.1415;
  public static int    count=0;

  myExample() { count++; }
}

main ()
{
  myEx obj[] = new myEx[2];
  obj[0] = new myEx();
  obj[1] = new myEx();
  System.out.println( obj[0].count );    /* 會得到 2 */
}

--

函式在多載,主要是用 input 的參數型別、個數來當識別,例如像:

  public static void   show(int x)    兩者視為相同,無法分辨
  public static double show(int x)    因為皆是傳入一個 int 參數。

--

數學函式的用法,直接用 Math.FUNCTION() 來呼叫就可以,不用 import 其他類別庫,
例如:
Math.max(12, 37)         // 取大值
Math.round(12.32)        // 四捨五入

重要的是 Math 類別提供了兩個 static 變數
Math.PI
Math.E

另外 Math 也提供了亂數可供使用
Math.random();          // 產生 0.0 ~  0.9999999   的亂數
Math.random() * 100     // 產生 0.0 ~ 99.9999999(無窮小數)

--

陣列的宣告法
int [] data = {1,2,3,4,5};
int [][] data = { {1,2,3} , {4,5} , {29,3,2,4,5} };
int [] data = new int [] {1,2,3,4,5};

底下這個方式很特別,稍微學一下。其中 Float 是一種物件
Object data[] = new Object[] {new Integer(28), new Float(12.1)};

/* 把 [][] 看成雙重指標 所以千萬不可以寫成  new int[10] */
/* 否則會出現 incompatible types found : int[]  required: int[][] */
int [][] num = new int[10][];
num[0] = new int[(int) (Math.random()* 10) ];


--

陣列你要想成,有多個指標幫你指向物件,

class node  { public int data; }

在用的時候,千萬記住要各別 new 出物件來
    node myNode[] = new node[5];
    myNode[0] = new node();       /* 各別再去配置空間 */
    myNode[0].data = 10;
    System.out.println(myNode[0].data);

同理也用在 Double 物件上面
    Double foo1[] = new Double[5];
    foo1[0] = new Double(5);
    System.out.println(foo1[0]);

但是如果是基本型別的資料,就可以直接用
    double foo2[] = new double[5];
    foo2[0] =5;
    System.out.println(foo2[0]);

--

String 是種物件,用法

String tmp = new String("the_key_word");
System.out.println( tmp.indexOf("key") );  /* 找出 key 這個字第一次出現*/

String num="123";
Integer.parseInt(str);

--

建構元的名稱,要與類別名稱相同

 class Circle
 {
   public Circle()            /* 修飾子可為 public 表示外界能呼叫  */
   { this(19); }              /* 用 this 這個關鍵字來呼叫建構元    */

   private Circle(int x)      /* 若為 private 則是只能透過內部呼叫 */
   { System.out.println(x); }
 }

--

兒子的 Constructor 如果有呼叫到父親的 Constructor,則要放在第一行
而且是用 super 這個關鍵字。

class Student extends Person
{
    Student()
    {   /* 呼叫父親的建構子,  should be at the 1st line */
        super();
        System.out.println("Student() ");
    }

  void foo() { System.out.println("Son foo"); }
  void bar() { super.foo(); }  /* 自己也有 foo() 所以
                                  如果要呼叫老爸的 foo() 就用 super 這字 */
}

--

super 的用法有兩種:
1. 用來呼叫父類別建構子: super();
   用來呼叫父類別特定的建構子: super(27, "abc");
2. 用來呼叫父類別的函式:如果父親、兒子都有 foo() ,
                         要特定指名呼叫 父的foo() 就用super.foo()


class CBase { protected int value=10; }  /* protected 允許讓兒子繼承 */

class CExt mextends CBase
{
  public int value=20;  /* 此時 CExt 會有兩個 value:自身、由父類來的 */

  public int get_Value() { return (value); }
  public void set_Value(int x)  { value = x; }

  public int get_Base_Value() { return (super.value); }
  public void set_Base_Value(int x) { super.value = x;}
}

public static void main(String args[])
{
    CExt obj1 = new CExt(); obj1.set_Base_Value(28);
    CExt obj2 = new CExt(); obj2.set_Base_Value(99);

    System.out.println( obj1.get_Base_Value() );  /* 得到 28 */
    System.out.println( obj2.get_Base_Value() );  /* 得到 99 */
}

--

this 的用法還有另一招
(注意:在 C++ 語言中,this 是一個指標,所使用時要用 -> 來操作)

class CBase
{
  public int value=10;

  public void show()
  { int value=99;
    System.out.println (this.value);   /* 物件成員 10 */
    System.out.println (value);        /* 區域變數 99 */
}

--

關於 final 的用法

1. 禁止 function 被子類別改寫(overriding)
  class Base { public final void show() {...} }

  /* 錯誤!! overridden method is final */
  class Ext extends Base { public void show() {...} }   /* 不允許自己重新定義 */

2. 用來達到 常數(constant) 的作用
   class Base { public static final double pi=3.14; }
   class Ext extends Base {
     double pi=8;            ○    /* 自己可以另外搞一套 */
     show() { super.pi=10;   ╳ }  /* 但是不可修改到父類那組 */
     show() { pi = 10; }
   }

3. 禁止 class 被繼承
   final class Base {}
   class CExt extends CBase        /* cannot inherit from final CBase */

--

問題:
1. 我在 myExcep.java 中用到 myClass.Java 的類別變數
為什麼 myClass.java 在每次重新執行時,不需要重新編譯?

2. Math.random() 到底產生的範圍是什麼? 去確認一下
   類別 java.util.Random 又是怎樣

3. String.indexOf() 的用法到底怎樣

--

開始談 class 的用法

class FOO()
{
  private int num=0;    /* private 變數隻允許自己的類別來存取 */
  public  set_Num(int x) { num = x; }
}

public class myEx
{
  public static void main(String args[])
  { FOO obj = new FOO();
    FOO.num=10;              ╳
    FOO.set_Num(10);         ○
  }
}

--
在一個建構子中,要呼叫另一個建構子時,用的是 this
而且 this 關鍵字 只能放在建構元內的第一行。

class Cfoo
{ String name;

  Cfoo()
  { this("default"); }  /* this.Cfoo("default") 這是錯的用法 */

  Cfoo(String x)
  { name = x ; }
}

--

預設的建構子

class Cfoo {} 的預設建構子會長成:  public Cfoo()

--

在類別函式中,不可以呼叫 實例函式/實體變數,因為這些東西屬於個別物件所有
non-static method my() cannot be referenced from a static context

class Cfoo
{
  static int num=0;
  int age;

  public void my() { }
  static void my_s()  /* (╳) 類別函式 不可以呼叫 實例函數、實例變數 */
  { my(); }

}

在類別函式中,也不能使用 this這個關鍵字,因為 this 是指呼叫該 method 的物件。

class Cfoo
{ int num=0;    /* 物件變數 */
  public static void get_Num()  /* 類別函式 (!!不可以用到物件變數!!) */
  {
    System.out.println ( num );      /* 這也是不允許的 ,沒物件跟本不會有 num*/
    System.out.println ( this.num )  /* this 代表呼叫這個函式的物件 */
  }                                  /* 不允許 */
}

--

class complex
{
  double a,b;
  public boolean compre(complex obj)
  { /* 要用每個欄位下去逐一比對 */
    if ( this.a==obj.a && this.b==obj.b) return true;
    else return false;  /* 如果寫成 this==obj 這表示,比較兩指標所指位置 */
  }
}

--

在 obj 物件內改寫 toString() 函式,注意看這邊的語法,奧義。

  public static void main(String args[])
  {
    Object obj = new Object()
    {
      public String toString()   /* 改寫 fucntion */
      { return ("noname"); }
    };
    System.out.println( obj.toString() );
  }

--

繼承登場

父類別                          子類別
======                          ======
沒有宣告 public/private  ---->  沒有宣告 public/private
public 成員              ---->  一樣是 public
private 成員             ---->  只能透過父類別的函式來存取
建構元                   ---->  不能繼承


class Circle
{ public Circle() {System.out.println("Circle constructor()");}
  public Circle(int x) {System.out.println("Circle constructor(int x)");}
}

class Coin extends Circle
{ /* 什麼都沒寫,預設會去呼叫父類別的 Circle() - 即 super() */
  public Coin() { System.out.println("Coin construcotr()"); } 與下面同樣意思
  public Coin() { super(); System.out.println("Coin construcotr()"); }

  /* 如果想要 呼叫特定的 父類別建子,那就用 super() - 會呼叫 Circle(int x) */
  public Coin(int x) { super(x); System.out.println("Coin construcotr()"); }
}

--

書本上有談到 overriding 與 overloading
overriding  - 在子類別中,定義名稱、引數個數、傳回值型態均與父類別相同的method
overloading - 在相同類別中,定義名稱相同,引數數目不同,或者型態不同的method

--

抽象類別登場 (子類別用 extends 來繼承,再補齊原本 abstract 部份)
所謂抽象類別就是內含有 abstract function 的類別。其使用語法如下:

abstract class Shape                /* 別忘了 class 要加上宣告 abstract */
{ public abstract void show(); }    /* 然後當然也少不了 函式的部份 */

class Rectangle extends Shape       /* 定義 Rectangle 之後準備實作 show() */
{ public void show() { System.out.println ("Rect()"); } }

class Circle extends Shape          /* 定義 Circle 之後實作 show() */
{ public void show(){ System.out.println ("Circle()"); } }


1. 抽象類別(abstract class)不可用來產生物件
2. 在抽象類別中所有 "抽象函數" 必定要在子類別中實作,這樣才可用子類別建物件
   (別忘了,只要有一個抽象函數存在,該 class 就變成 abstract class
    abstract class 是不能用來產生物件的。)
3. 抽象類別中,可以有部份函數已經實作。未實作部份就是由子類別來補齊。
4. 一個抽象函數,可以宣告為 public/protected

--

談談 interface

1. 介面中的成員變數,要設定初值
2. 在介面中的 function 默認都是 abstract 了
   在介面中的 成員變數 默認都是 final 了,不能更改其值 (一開始就要給初值)
3. 成員函數只能宣告為 public 或者不宣告。不能宣告為 protected/private。
4. 在實作 function 時,傳數參數的型別、數目,與回傳值 都要與介面定義內的相符合。
5. 所有在介面內定義的 function 都要在類別(class) 中實作出來,
   否則該類別就變成 abstract class

interface Shape
{
  int value=10;
  public abstract void foo();
  public abstract void bar();
}

abstract class Circle implements Shape  /* 抽象 - 因為 bar() 沒有實作出來 */
{
  public void foo()  { System.out.println("hello"); }
}

class Triangle implements Shape  /* 全部的函式都實作完,可以用來建立物件 */
{
  public void foo() {...}
  public void bar() {...}
}

--

在 java 中並不支援使用 extends 來多重繼承,而是用 "介面" implements 來實現

interface Shape { public abstract void show(); }  /* 傳入參數要給名字 */
interface Color { public abstract void setColor(String x); }

class Circle implements Shape, Color
{ public void show() {...}     /* 所有 函式 都要實作,否則會變成抽象類別*/
  public void setColor(String x) {...}
}

--

討論 interface 與 abstract 的差別

1. 介面內的 變數成員,要設定為常數
   介面內的 所有方法,都設定為抽象方法。
2. 抽象類別允許:變數不需要設定初值 + 一般函數/抽象函數 並存。

kcw 發表在 痞客邦 留言(0) 人氣()

--

使用 rand() 產生亂數,會介於 0 ~ RAND_MAX(32767)
調整亂數範圍: 下限 + rand % (上限-下限+1)
設定亂數種子: srand( time(NULL));

--

關於 ++ 與 -- 的問題

1. 若 a=2, b=5 , x = ++(a*b)  /* lvalue required as increment operand| */

這是一個錯誤用法,當使用 ++ 或 -- 時必需要有 左值(l value)
講白一點就是說,使用 ++ 或 -- 時要有變數能去儲存運算,而不是一個式子。

x = y 對於 x 而言它表示的是一個address,而 y 表示的是address裡的內容
l-value在compiletime就知道了,r-value在runtime時才會被知道,也就是說
所有symbol的address在compiletime時就會知道

有些東西只能當 r-value, 例如 literals
有些東西既可當 r-value 又可當 l-value, 例如變數
有些運算子需要 r-value, 例如 + 的兩側
有些運算子需要一個運算元同時可以扮演 r-value 與 l-value 的角色,例如 ++ --


--
關於迴圈

do-while 的語法,在 while 後面要有一個分號。

  do
  {
    i++;
  } while (i<=10);

--
關於陣列

int num[3][3] = {0};                  /* 宣告時才能這樣用,設定為整個都是 0 */
int num[2][2] = {1,2,3,4};            /* 會自己分組 */
int num[2][2] = { {1,2} , {3,4} };    /* 同意       */

這樣宣告是錯的,對 c 語言來說,他不曉得每一組有多少人   (真怪 T_T)
  int num[][] = { {1,2,3} , {4,5,6} ,{7,8,9} };
像下面這樣要講出每組有多少人才對
  int num[][3] = { {1,2,3} , {4,5,6} ,{7,8,9} };

傳遞陣列給函式

  foo (int a[] )        /* 一維陣列,可以這樣搞!! */
  foo (int a[][3])      /* 一定要把每組有多少元素標出來 */
  foo (int a[][] )      /* 這是錯的,因為不知道怎麼分組 */


在 C++ 中並不會檢查陣列的註標,也就是說在使用時,可能不小心超出範圍

--
陣列與指標的配合

1. 字串指標所形成的陣列
char* array[] = { "this", "is", "a", "book" };  /* 宣告一個字元指標的陣列 */
在這個例子中 array[1] 是指向 "this" 這個字串

2. 陣列名稱是指標沒錯,但是它是一個「常數指標」,所以是不能更改的。
int num={1,2,3,4,5}
int *ptr = num;
cout << *(num);       /* 會得到 num[1] 沒錯 */
cout << *(num+1);     /* 希望 num 向下移一個 大錯!! num 是指標常數,不能動的 */
cout << *(ptr+1);     /* 這才是對的,ptr 是一個指標變數,可以移動的 */

3.
int num[] = {1,2,3,4,5};
int *ptr = num;
cout << *++ptr;      /* 會把 ptr 向下移到 num[2] 並印出 num[2] 的值 */
cout << *ptr++;      /* 印出 num[2] 的值,並把 ptr 向下移一格指到 num[3] */
cout << *ptr;        /* 目前 ptr 指到 num[2] */

4. 注意一下這邊 ptr 與 ++ -- 用法順序
main()
{
  int num[SIZE];
  int *ptr = num;

  for (int idx=0; idx<SIZE; idx++)
    cin >> *(ptr++);

  for (int idx=0; idx<SIZE; idx++)
    cout << *(--ptr);
}

5.
void showArray (int data[])   /* 改成 int *data 也是可以 */
{
  for (int idx=0;idx<SIZE;idx++)
    cout << *(data + idx);
}

main() { int num[SIZE]={1,2,3,4,5}; showArray(num); }

6.
int *ptr = NULL;
cout << ptr;     /* we got 0x0 */
cout << ptr+1;   /* we got 0x4 */

7. 使用 new 與 delete 建立二維陣列

int **data;
data = new int*[m];
for(int i = 0; i < m ; i++)
    data[i] = new int[n];


for(i=0; i<m; i++)
    delete [] data[i];
delete [] data;

8. 不要被指標給嚇到了 char* a[] 沒你想的那麼難

void show(char* a[])    /* a[] 是一個陣列 裡面裝字元指標 */
{
  for (int idx=0; idx<SIZE; idx++)
    cout << a[idx] <<endl;
}

char* a[SIZE] = {"this", "is", "a", "book"};
show(a);


--
指標的奧義

1. 使用 ptr++ 表示指標移向下一格,不要想錯了

int num[10];
int *ptr = num;       /* 表示 ptr 指向 num[1] */
ptr++;                /* 表示 ptr 指向 num[2] */

2. 同型別的兩個指標不允許相加;但指標可以相減,
   相減表示兩個指標間相差的元數個數(會自動幫你換算)。

  int num [] = {1,2,3,4};
  int *p = &num[0];          /* 0x23ff28 */
  int *q = &num[1];          /* 0x23ff2c */

  cout << p << endl;
  cout << q << endl;
  cout << q-p;               /* 1 相差一個元素,不要懷疑 */

3. 函式指標 (function pointer)

void swap (int *p, int *q)
{ int tmp = *p; *p = *q; *q = tmp; }

int main()
{ int a=10, b=20;
  void (*fp)(int*, int*);
  fp = swap;
  (*fp)(&a, &b);       /* 寫成 fp(&a, &b) 也行 */
}

4. 函數指標的奧義

double add(double x, double y)
{ return (x+y); }

double multi(double x, double y)
{ return (x*y); }

double run(double x, double y, double (*fp)(double, double) )
{ cout << fp(x,y); }               ^^^^^^^^^^^^^^^ 會送一個 function 進來

int main()
{
  run (18.2, 25.1, add);    /* 進行相加運算 */
  run (281, 2, multi);      /* 進行乘法運算 */
  return 0;
}

5. 窮極無聊的指標

fun ( int array[] [3] )   /* 陣列是3個整數為一組,有多少組不曉得 */
fun ( int (*array)[3] )   /* 與上同義,每個指標指出去的,都是 int array[3] */
fun ( int * array[3]  )   /* 有 3個整數指標,形成一個陣列 */

array → □□□
         □□□

array[0]   □→
array[1]   □→
array[2]   □→

--
static 的用法

static 用在變數上,表示變數所佔用的記憶體,直到程式結束才會歸還。

static 全域變數只允許在一個檔案內使用。而且變數生命週期是從定義處開始,
所以在沒有定義靜態全域變數的區域中,是無法使用 static全域變數。
即使用了 extern 也沒辦法使用。

int main()
{ extern int x; }     /* x 是靜態全域變數,生命週期是從定義處才開始 */
static int x;         /* 因此在 main() 內的用法,是錯的 */


static 區域變數
動態變數在 function 執行時,會在堆疊建立一個區塊供變數使用,
並沒有固定記憶體空間,這種方式建立變數稱為「宣告」

在編譯時如果已配有固定記憶體空間的變數,稱為「定義」如 static / extern
靜態區域變數。變數的生命週期不會隨著函數結束而結束。而要等到整個程式結束。

foo()
{ static int num; }

--
extern 的用法
1. extern 表示只是 宣告, 不是定義(define)
2. 用來表示變數會在其它的位置被定義,可能在同個檔案,或者其他文件中。

void foo()
{
  extern int x;   /* (這邊是宣告)變數x 在別處定義,不能寫成 extern int x=10 */
  x=99;           /* 一定要兩個式子拆開來寫 */
  cout << x;
}

double x=10;      /* 這邊定義全域變數 x */

--

函式的參數傳遞,有給預設引數的,要靠右邊

void foo (int a, float b, float c=2.3, char d='z')

呼叫時: foo(12, 84.1);          /* 合法 此時 c預設2.3 d預設值'z' */
         foo(12, 84.1, 10.1);    /* 合法 狀況同上,但 c 值2.3     */
         foo(12);                /* 不合法,變數少一個            */
--
inline 函數

當一個 function 被呼叫時,程式的控制權會轉到函數上,並且使用堆疊(stack)
記錄返回位址。如此動作會耗費一些時間。

C++ 中的 inline function 被呼叫時,會直接「抄一份」貼到呼叫處。
使用 inline 函數可以減少程式主控權不停轉換。但是 inline 函數會佔用較大記憶體。
因為同一份程式碼,抄了很多次。

--

#define 巨集的使用

前置處理器會直接代換字串,不需要考慮型態問題,沒有函數的呼叫,
所以也省去了變數的定義、回傳值。所以如果十段相同的程式碼,
巨集 - 佔用的記憶體較大,但是程式控制權不用轉移,速度較快。
函數 - 程式較短,佔用的記憶體較小,但控制權要轉移,所以速度慢。

--
字串的處理
char str[10];

1. 讀取一行,可以包括空格
   cin.getline(str, 10);   /* 真正存的資料只會有9個,最後一個是 \0 佔用 */

2. 計算字串長度
   strlen(str)    /* 長度不包含最後 \0 符號,你輸入幾個就算幾個 */

2. 拷貝
   strcpy(a,b)    /* 字串 a 要準備 strlen(b)+1 的長度,因為最後還有一個 \0 */

--

關於 暫存器變數 register 用法
用來增加運算速度,將區域變數存在暫存器中,暫存器變數的活動範圍只在
所屬的左右大括號中。

foo()
{ register int num=10; }

--
關於 reference(參考) 的使用

1. 基本用法
int num;
int &ref = num;   /* 在這邊 ref 就是一個參考,指向 num */

2. 用來達到 swap 的功能
void swap(int &a, int &b)

3. 一個函式也能傳回 reference

int& foo (int &a, int &b) { return ( a>b? a:b); }  /* 這邊的 a,b 都是參考 */

main () { int num1, num2;
          num1=20; num2=30;
          foo(num1, num2)=99;  /* foo() 執行完後,會回傳較大者的位址 */
        }                      /* 之後把該變數值改成 99 */


--

volatile 加在變數的前面,表示該變數不會使用最佳化編譯。有時變數的值改變了
compiler 並不會馬上將他寫入記憶體中而先把結果放在CPU暫存器中 等到處理結束
之後 才寫入記憶體。若說這個變數是多執行緒的 flag 其他的執行緒要透過這個
變數來反應狀況。

而這個值卻又沒有寫入記憶體 這時便會發生意想不到的結果又或者是這變數為一個
硬體的暫存器會被硬體所改變然而compiler 並沒有正確的將值從硬體暫存器取出來
而是將自己暫存的值拿來使用。

這種情況 就是要用volatile 來宣告變數 告訴compiler不要自己暫存變數來提升速度
如此這個變數有任何的改變 便會馬上反應出來

*ptr = 0;
while(*ptr){     會被聰明的編譯器給最佳化→   *ptr = 0
    *ptr = 4 ;   但是每個值的改變,可能表     while(0) {}
    *ptr = 0 ;   示 hardware 的一個狀態,
}                不允許省略的!!

--

結構的用法
結構的大小是「欄位總長度」+「數個位元組」,讓存放在記憶體的下一個變數
起始處是偶數位址。(其實測的結果,長度都是 8 的倍數 8 16 24 32...)

1. 直接在定義後面,宣告出變數

struct myData
{
  char name[10];
  int age;
} Jack, Peter, Tom;      /* 宣告 Jack... 為 myData 格式 */

或者

struct myData Jack = { "jack", 18 };

cout << sizeof(Jack);   /* 得到結果是 16 */

2. 相同的結構允許直接拷貝
struct myData Jack = { "jack", 18 };
struct myData Tom;
Tom = Jack;

3. 位元欄位 (unsigned bit)  ... 有考過

struct File {
  unsigned int face :4    /* 使用 4位元 */
  unsigned int suit :2    /* 使用 2位元 */
  unsigned int color:1
};


--

Union 的用法   (省空間的作法 會取最大欄位那個)

union myUni
{
  char c;      /* 字元佔 1 byte       ■□□□         */
  int score;   /* 整數佔 4 byte       取最長的 4byte   */
};

myUni obj = {65} ;
cout << sizeof(obj);   /* 得到 4byte */
cout << obj.c;         /* 會得到英文字母 A (因為ascii A 65) */
cout << obj.score;     /* 會得到 65  */

--

enum 的用法

1. 基本值都是從 0 起跳,別忘了
enum myEn
{
  A,B,C,D=7,E,F       /* A=0, B=1, C=2, D=7!!, E=8 ... */
};                    /* 注意了,這邊的值要給整數 */

int main()
{
  myEn X=E;    /* we get 8 here , X 是列舉形態,要用列舉的格式 */
  cout << X;
  myEn Y;
  Y=1;         /* 在 c 語言可以這樣用,但在 c++ 要改 Y=static_cast<myEn>(1) */
  return 0;
}

2.

enum myEn
{ tennis, swimming, baseball };   /* tennis=0 swimming=1 baseball=2 */

enum myEn X=tennis;
switch (X)
{
  case tennis:              /* 這邊也可改成 case 0 */
    cout << "tennis";
    break;
  case swimming:
    cout << "swimming";
}

--
typedef 的用法

typedef struct
{
  int hour;
  int min;
} myTime;              /* myTime = struct {...} */

myTime clock[3];       /* 宣告時鐘陣列,每個元素都是 myTime 結構 */

--

談類別之前,先提一下 this 指標

  在 C++ 中這是指標,指向物件自身。           this->name
  在 JAVA 中是參考,語法有些微差異勿混用。    this.name

--

討論一下類別

class CWin
{
private:
  int height;
  int width;
public:
  CWin() {}
  CWin(int height, int width) { this->height = height; this->width=width; }
  int area();
};

/* scope resolution operator 範疇解析運算子 */
int CWin::area() { return (width*height); }

動態建立一個物件   CWin *ptr = new CWin();
使用指標呼叫       ptr->area();
刪除物件           delete ptr;

--

討論一下建構子 (constructor) / 解構子 (destructor)

class CWin
{
  private:
    char id;
    int width, height;
}

0. 非常重要的事 A為父類別,B為子類別
   建構子執行順序 A()  -> B()
   解構子執行順序 ~B() -> ~A()

1. 在建構子內直接初始化成員 (千萬記得,這招只能在建構子使用)
   CWin( char x='Q', int y=10, int z=15 ):id(x), width(y), height(z)
   直接指定 id=x, width=y, height=z

2. 建構子:不會有傳回值,但也不能宣告為 void!!
   因為系統建立物件時會主動呼叫 constructor,建構子跑完才會回到主程式。
   所以不用傳回值。

3. 解構子:與類別名稱同名,但多加一個 ~ 的函式稱為解構式。
   與建構式相同,解構式也不能有傳回值。

4. 跟 JAVA 相同 C++ 預設會為每個類別建立一個空的「預設建構子」
   預設建構子不會有任何引數,也不會做任何事。以類別 CWin 來說:

   CWin() {}  這就是預設建構子

   但如果我們有自訂建構子,那麼系統就不會自動建立預設建構子

5. 建構子的引數也可以提供預設值,當某個引數缺少時,會直接使用此值。

6. 注意建構子發生混淆的狀況
   建構子有兩個:
     CWin( char x='Q', int y=10, int z=15 ) {} /* 內建預設值,使用時可省略 */
     CWin( ) {}
   主程式中使用:  /* 對應錯誤!! 不知選哪個建構子 !! */
     CWin obj;     /* 要解讀成第一個,還是第二個?    */

7. 最先建立的物件,會是最後才進才解構

     myClock(char str[]) { strcpy(id,str);  cout << "create:" << id <<endl;}
     myClock::~myClock() { cout << "bye" << id <<endl; }
     main() { myClock obj("no.1"); myClock obj2("no.2"); }

   會得到
     create:no.1
     create:no.2
     byeno.2            /* 2號最後建立  但是最先解構 */
     byeno.1

--
拷貝建構子 (之前很少用過,其實也沒什麼)
用法大概是這樣

class myClock { char *name, int hour, int min }

myClock obj1("no.1", 12, 37);
myClock obj2(obj1);              /* 建立 obj2 物件,並把obj1 的資料拷過來 */

系統給的 預設 拷貝建構子會是這種型態: myClock(const myClock &)

[注意] 這邊會有一個 bug 當我們的成員變數有指標時,他會把指標的位址抄一份過來
       也就是說在上例中,obj1 與 obj2 的 *name 指向「同一份 no.1」
       這是不正確的。應該要存有兩個副本,否則一者 delete 掉之後,另一者就無法
       參考到。
                 obj1.name ---> [no.1] <--- obj2.name

這個問題可以自行定義拷貝建構子,來解決。改寫下面這個建構子。

myClock (const myClock &src)     /* 注意傳進來的一定是 const 參考。 */
{
  /* 把字串拷貝過來 這樣就不是共享同一份 自己指定要寫入什麼值 */
  name = new char[ strlen(src.name)+1 ]
  strcpy (name, src.name);
  hour = src.hour;
  min  = src.min;
}

--

多載運算子( operator overloading )

class myClock
{
  int hour, min;
  myClock(int x, int y) { hour=x, min=y; }

  void operator+ (const myClock &rhs)  /* 傳 reference 進來,而且是 const */
  { hour = (hour + rhs.hour) ; min  = (min  + rhs.min); }
}

使用時:
  myClock obj1(12,31);
  myClock obj2(1,1);
  obj1+obj2;         /* 也可以寫成 obj1.operator+(obj2) */

我也可以把加法改成這樣,算完之後會回傳一個結果:

  myClock operator+ (const myClock &rhs)
  { return ( myClock( (hour+rhs.hour) , (min+rhs.min) ) ); }

使用時:
  myClock obj1(12,31);
  myClock obj2(1,1);
  myClock obj3 = obj1+obj2 ;    /* 記得準備一個變數來接 相加後傳回的結果 */


另一個要注意的就是: 等於(=)運算子
這邊會出現的問題就跟「拷貝運算子」那邊是一樣的,當物件的資料如果有指標時
去做 等於= 運算時只會把 address 抄一份,而不是複製出另一份實體。
造成兩個變數共用一份實體。

class myClock
{
private:
  int hour, min;
  char *name;

public:
  void operator= (const myClock &rhs)
  {
    hour = rhs.hour, min=rhs.min;
    name = new char[ strlen(rhs.name)+1 ] ;
    strcpy (name, rhs.name);                 /* 直接拷一份過去 */
  }
}


--

類別中的 靜態(static)變數與函式
一個 static 變數必需在類別內部宣告,但初值指定要在 class 外部 !!

class myClock
{
private:
  int hour,min;
  const static double pi=3.14;   /* 靜態的 const 變數,可以在類別內初始化 */
  static int dummy_count;
public:
  static int count;                             /* 宣告靜態變數 */
  static void get_count() { cout << count; }    /* 宣告靜態方法 */
  myClock(){ hour = min = 0; count++; }         /* 每新生一個物件,計數加1 */
};

/* C++ 的 類別靜態成員 不可以在建構子內初始化 */
int myClock::count = 0;
/* 即使是 private 變數仍是這樣做 */
int myClock::dummy_count = 0;

int main()
{
  myClock obj[10];
  cout << myClock::count;   /* 這邊的計數值=10 因為上面有10個物件產生 */
  myClock::get_count();     /* 同樣道理,這是示範 static method 用法  */
  return 0;
}


靜態函數有一些限制,因為沒有物件產生:
  靜態函數 --不能存取--> 類別成員
  靜態函數 --不能呼叫--> 類別函數
  靜態函數 --不能使用--> this 這個關鍵字

但是反過來就不一樣了。

--

有關參考(reference)
CWin win1;
CWin &ref = win1;
cout << ref.width;           /* 使用時 */


--

談論一下 友誼函數 (friend function)

1. 友誼函數可以存取 類別 內的公有、私有類別
2. 友誼函數本身不屬於類別,所以無 public/private 問題
3. 友誼函數在類別內宣告 Prototype 就好,實際的 Body 寫在函數外面。

class CWin
{
private:
  int width, height;
public:
  CWin() { width=height=10; }
friend void getValue(CWin);        /* 定義友誼函數的 prototype */
};

void getValue(CWin X)            /* 友誼函數的 body 注意這邊參數的傳遞 */
{ cout << X.width; }

main()
{  CWin obj;  getValue(obj); }

--

C++ 的 try-catch 機制

C++ 有提供一套 try-catch 機制,在拋出例外時,什麼型別都可丟。
這點不像 Java 有內建了一套 Exception 類別。

在 try{} 中使用 throw 這個指令丟出例外,
在 catch(型別 變數名) {} 會去比對拋出的例外資料,是什麼型別。有符合才做處理。

  int a=10;
  try
  { if (a==10)
      throw ("EXCEPTION");    /* 拋出了一個字串常數!! */
  }
  catch (const char *str)     /* 所以進行型別比對,如果是字串常數,才來這邊 */
  { cout << str ;  }
  catch (int x)               /* 如果拋出一個整數,就會在這邊處理 */
  { cout << x ;    }
  catch (...)                 /* 你沒看錯 "..." 表示什麼例外通吃
  { cout << "..."; }

  cout << "try catch end";    /* 不論是否補捉到,try-catch 完之後就接這邊 */

--

樣板(template)的使用 - 背起來

template <class T, class U>   /* 允許前後型別不同   */
T add ( T x, U y)             /* 吃兩個不同型別變數 */
{                             /* 注意,回傳型別是 T 記得考慮資料精確度 */
  return (x+y);
}

int main()
{
  cout << add <double,int> (12.7 , 10);  /* 也可直接寫成 add(12.7, 10) */
  return 0;
}

上面是 template 用在函式上面;如果用在類別上面,寫法會不同(一場災難):

template <class T>
class myClock
{
private:
  T hour, min;
public:
  myClock(T x, T y) {hour=x, min=y;}
  void setValue(T x, T y) { hour=x, min=y; }   /* 實作在裡面比較省事 */
  void getValue(); /* 用來示範如何在類別外實作,很麻煩!! */
};

template <class T>            /* 不要忘記寫這行,這樣下面函式的 T 才有作用 */
void myClock<T>::getValue()   /* 這個 <T> 的位置也要放對,非常小心 */
{ cout << hour << endl << min; }

int main()
{
  myClock <int>obj(9,23);     /* (易忘)用的時候也要小心,型別要放在物件前 */
  obj.getValue();             /* 這邊只有一個 <int> 而不是 <int, int>  */
  return 0;
}

底下這個例子跟上面一模一樣,但允許傳入 2 個型別。

template <class T, class U>
class myClock
{
private:
  T hour;
  U min;
public:
  myClock(T x, U y) { hour=x , min=y; }
  void setValue(T x, U y);
  void getValue();
};

template <class T, class U>
void myClock<T, U>::setValue(T x, U y)
{ hour=x, min=y; }

int main()
{
  myClock <int, float>obj(12,34);     /* 也是一樣,使用時要先講好,載入的格式 */
  return 0;
}

--

討論一下繼承


class Shape
{
private:
  int width, height;
public:
  Shape()
  {
    cout << "Shape Create";
    width = height = 0;
  }
  void setWidth(int x) { width = x; }
  int getWidth() { return width; }
};

class Circle:public Shape
{
private:          /* 在 Java 中可以使用 super.func() 來呼叫父類的方法 */
  int color;      /* 但 C++  則是該使用 父類別::func() 來進行呼叫,別弄混了 */
public:
  void getWidth() { cout << Shape::getWidth(); }
  void setWidth(int x) { Shape::setWidth(x); }   /* 呼叫父類的 setWidth() */

};

int main()
{
  Circle obj;
  obj.setWidth(18);
  obj.getWidth();
  return 0;
}

--


父類別            |    子類別
public:           |    public:
show_member()     +--> show_member()
                  |
private:          |    private: (子類別成員不能存取)
id, width, height +--> id, width, height
                  |
建構元            +--> 不能繼承
                  |

class father
{ public: show_member();
  private: int id, width, height;
  father()
}

class son:public father      /* 使用 public 方式來繼承,原本屬性不變 */
{
  - 兒子可以呼叫 show_member()
  - 兒子擁有 id, width, height 變數,但是不能存取,要透過父類函式。
  - 父親的建構元是不會繼承給兒子的
}

在 C++ 繼承中,建立子類別物件時,會先呼叫父類別中沒有引數的建構元。
再執行子類別的建構元。

兒子若想呼叫父親特定建構元呢?!
在兒子建構子後面加上  :父類建構子()
就像 son(int x, int y):father(x ,y)   /* 把 x y 傳給父建構子 */

class father
{
  father(int, int, int)
  father()
  father(char, int)
}

class son:public father
{
  son()      :father(10,20,30)    /* 這樣就會呼叫特定父親的建構元 */
  son(int  n)                     /* 這一會對應到 father() */
  son(char c):father (c, 28)
}

son obj;        /* 建構子對應到 son() 且會去呼叫 father(10,20,30) */
son obj(28);    /* 建構子對應到 son(int) 且會去呼叫 father() */
son obj('q');   /* 建構子會對到 son(char) 且會把傳入的字元,再傳給父建構子 */


類別繼承的存取模式

父 (A)            子 B:public A | 子 B:protected A | 子 B:private A
public               public     |    protected     |    private
protected            protected  |    protected     |    private
private              無法存取   |    無法存取      |    無法存取

--

多載(overload)
多載可以使用一個函式名稱來執行不同的實作,這是一種「編譯時期」就需決定的方式,
這是「早期繫結」(Early binding)、「靜態繫結」(Static binding),因為在編譯
時就可以決定函式的呼叫對象,它們的呼叫位址在編譯時就可以得知。

--

多型()
虛擬函式(Virtual function)可以實現「執行時期」的多型支援,是一個「晚期繫
結」(Late binding)、「動態繫結」(Dynamic binding),也就是指必須在執行時期
才會得知調用的物件。 (白話:虛擬函式是達到多型的一種方法)

透過指標或參考的操作,來達到多型的表現。

class A
{ virtual void show() {cout << "from A \n"; } }  /* 宣告 show() 為虛擬函式 */

class B : public A    { void show() { cout << "from B\n"; } }

  A *ptr;    /* 父類別指標 */
  A obj1;
  B obj2;
  ptr = &obj1; ptr->show();   /* 得到 from A */
  ptr = &obj2; ptr->show();   /* 得到 from B 因為 show() 設成 virtual */

或者像這樣用...

class A            { virtual void show() {cout << "from A \n"; } }
class B : public A { void show() { cout << "from B\n"; } }

void call_show( A &obj ) { obj.show(); }  /* 會去呼叫函數內建的show() */

  A obj1;
  B obj2;

  call_show(obj1);   /* 得到 from A */
  call_show(obj2);   /* 得到 from B */

--

純虛擬函數 (pure virtual function)
上面那個議題在討論 virtual function 但在這邊要講的,叫做 pure virtual function
這種函式只有一個空殼。將來會在子類別中實現。

在 Java 中這種函數叫做 抽象函數(abstract function) ;
而在 C++ 中則稱為 純虛擬函數(pure virtual function)
具有 純虛擬函數 的類別,則稱為 抽象類別(abstract class)...這點跟 JAVA 一樣

講白了:pure virtual function 就是只有標頭,至於身體要在子類別中實作。

語法: virtual void function() = 0;     /* 宣告他 =0 , 表示父親這邊不會實作 */

一個類別中如果含有純虛擬函式,則該類別為抽象類別(Abstract class),
該類別只能被繼承,不能用來直接生成實例。

純虛擬函數,也是實現多型的一種技巧。雖然函數名稱相同,但執行時會因為型別不同
而去呼叫對應類別中的函式。

這有一個範例

class Shape
{
public:
  int hight, width;
  void setValue(int x, int y) { hight=x , width=y;}
  virtual int area()=0 ;  /* 宣告 area() 為純虛擬函數 */
};

/* 各子類別去實作 area() 函式 */
class Triangle : public Shape
{ public:     /* public 別忘了加,很重要! 不然其他人怎麼用 */
  int area() { return (hight * width * 0.5); }
};

class Square : public Shape
{ public:  int area() { return (hight*width); } };

使用時:
  Square obj;
  obj.setValue(12, 11);
  cout << obj.area();      /* 會呼叫到 Square 的 area() */

--

memory leak 的問題

  A *ptr = new A;
  A obj;

  ptr = &obj;   /* 把 ptr 改指向另一個物件,原本 new 出來的物件 失連 */
  ptr->show();

  delete ptr;   /* 而且 obj 物件並不是動態配置產生,所以 delete 是沒效的 */
  ptr->show();  /* 仍是照舊可以呼叫 show() */

kcw 發表在 痞客邦 留言(0) 人氣()

Pure Storm GT 穿線記錄

Racquet #A
2009.11.27 - SOLINCO TOUR BITE&VANQUISH
2010.04.14 - Babolat Addiction 16"

Racquet #B
2010.04.17 - Alpha Gut 2000 16

kcw 發表在 痞客邦 留言(0) 人氣()

各項目後面是參考價,實際總價 9900 nt

CPU (中央處理器):AMD AM3 X2-240(2.8G) ... 1850nt
MB (主機板):技嘉 MA785GMT-US2H ... 2800nt
RAM (記憶體):創見 DDR3 2GB ... 1500nt
VGA (顯示卡):內建
HDD (硬碟):WD 500G AAKS ... 1780nt
PSU (電源供應器):海韻 S12 II 330W 80PLUS 銅牌 ... 1750nt
CHASSIS (機殼):CoolerMaster Elite 341 (二大二小) ... 1200nt

Total: 9900 元

kcw 發表在 痞客邦 留言(0) 人氣()

[AMD solution]
CPU AMD AM3 X2-240(2.8G) 1750 nt
MB GA MA785GMT-US2H 2800 nt
RAM DDR3 2G-133 1450 nt
HDD WD SATA2 320G 1470 nt
PSU 藍晶鑽二代 350W 1450 nt
機殼 CoolerMaster Elite 341 1150 nt

kcw 發表在 痞客邦 留言(0) 人氣()

(1)國文

(2)法學,英文

(3)程式語言 (念中文書,C++JAVA、物件導向要熟)

Concepts of Programming LanguageRobert W. Sebesta

440《程式語言》(胡世雄,高點出版) (買新的)

 

(4)資料通訊

Computer NetworkANDREW S. TANENBAUM

 (中文版,電腦網路,邵喻美譯) (買新的)

663《資料通訊網路》 第四版 Forouzan(劉金順譯,麥格羅希爾) (買新的)

 

(5)資料結構

Fundamentals of Data Structures IN C++ 聖經本

《資料結構歷屆試題詳解》洪逸

 

(6)資訊系統與分析

553《系統分析與設計—理論與實務應用》吳仁和、林信惠 (2007四版,買新的)

578《物件導向系統分析與設計:結合MDAUML》吳仁和 (二手430,賺80)

 

(7)資料庫應用

425《資料庫應用》向宏 (高點出版,足以應付)

Fundamentals of Database SystemsRamez Elmasri

668資料庫系統原理 5/e (中文本,陳玄玲譯) (太厚 先不買)

 

(8)資訊管理

510《資訊管理─理論與實務》謝清佳、吳琮璠 (二手同價位)

578《資訊管理─e化企業的核心競爭能力》林東清 (最新第三版,二手480100)

《資訊管理概論 :企業e化建置實務》林震岩

kcw 發表在 痞客邦 留言(0) 人氣()

(1)國文

(2)法學知識與英文

(3)程式語言 (念中文書,C++、JAVA、物件導向要熟)
《Concepts of Programming Language》Robert W. Sebesta
《程式語言》(胡世雄,高點出版)

(4)資料通訊
《Computer Network》ANDREW S. TANENBAUM
+-(中文版,電腦網路,邵喻美譯)
《資料通訊網路》 第四版 Forouzan(劉金順譯,麥格羅希爾)
《Computer Networking: A Top-Down Approach》 (手邊有此書)

(5)資料結構
《Fundamentals of Data Structures IN C++》 聖經本
《資料結構歷屆試題詳解》洪逸

(6)資訊系統與分析
《系統分析與設計—理論與實務應用》吳仁和、林信惠
《物件導向系統分析與設計:結合MDA與UML》吳仁和

(7)資料庫應用
《資料庫應用》向宏 (高點出版,足以應付)
《Fundamentals of Database Systems》Ramez Elmasri
+--資料庫系統原理 5/e (中文本,陳玄玲譯)

(8)資訊管理
《資訊管理─理論與實務》謝清佳、吳琮璠
《資訊管理─e化企業的核心競爭能力》林東清
《資訊管理概論 :企業e化建置實務》林震岩

kcw 發表在 痞客邦 留言(0) 人氣()

  • Nov 14 Sat 2009 02:22
  • NB

ASUS UL30
SU7300 (1.3G) 2GB RAM 500GB Windows 7, 30900
SU7300 (1.3G) 2GB RAM 500GB Vista, 29900
SU2300 (1.2G) 2GB RAM 320GB Vista, 25800

Toshiba Portege T130
SU4100 (1.3GHz) 2G RAM 250G Win 7, 28800

Acer
3810TG, SU7300 , ATI HD4330 2G RAM, 500G 26600
3810TZG SU4100 , ATI HD4330 2G RAM, vista, 26500

kcw 發表在 痞客邦 留言(0) 人氣()

  • 這是一篇加密文章,請輸入密碼
  • 密碼提示:123
  • 請輸入密碼:
  • 這是一篇加密文章,請輸入密碼
  • 密碼提示:契爾氏
  • 請輸入密碼:
為了方便在自傳上唬爛...先看一下之前修過什麼課吧

[91.9 ~ 92.6 菜大一]
計概(一)
計概(二)、離散

[92.9 ~ 93.6 嫩大二]
線代、資結、訊號系統 || 開始在護理系打工(一年)
組語、通訊系統

[93.9 ~ 94.6 鳥大三]
機率、計組、計算機圖學(OpenGL)、程式規劃計巧
ALGO、OS、組合數學、高等資料結構

[94.9 ~ 95.6 老大四]
數位影像處理概論、系統管理
資訊安全、人工智慧概論、資料探勘

kcw 發表在 痞客邦 留言(0) 人氣()

(1) 更新 sources.list
#[Packages]-------------------------------
deb http://ftp.tw.debian.org/debian/ etch main contrib non-free
deb-src http://ftp.tw.debian.org/debian/ etch main contrib non-free
#[Security Update]------------------------
deb http://security.debian.org/ etch/updates main contrib non-free
deb-src http://security.debian.org/ etch/updates main contrib non-free

(2) 安裝常用套件
# apt-get install build-essential sudo screen unzip unrar tree vsftpd vim postfix mutt yafc

(3) 安裝 MySQL
# apt-get install mysql-server-5.0 mysql-client-5.0 mysql-common

替換設定檔my.cnf,使用:
/usr/share/doc/mysql-server-5.0/examples/my-small.cnf

關掉用不到的 Storage Engine:
skip-bdb
skip-innodb

設定 root 密碼:
mysqladmin -u root password

(4) 安裝 PHP5 與 Lighttpd

# apt-get install php5-cgi php5-gd php5-mysql
# apt-get install lighttpd

啟用 FastCGI、Virtual Host 模組
lighty-enable-mod fastcgi simple-vhost

(5) 新增一般用戶給予 sudo 權限(編輯 /etc/sudoers)
user ALL=(ALL) ALL

(6) 設定 vsftpd(編輯 /etc/vsftpd.conf)
# 允許上傳
write_enable=YES
# 帳號清單使用本地端 /etc/passwd
local_enable=YES
# 開放的 port
listen_port=1234
# 放寬檔案權限(預設太嚴格)
local_umask=022
# 設定登入後的根目錄
local_root=/home/ftp

(7) 變更 SSH Server 設定(編輯 /etc/ssh/sshd_config)
Port 1234
PermitRootLogin no

重新啟動 SSH:/etc/init.d/ssh reload

kcw 發表在 痞客邦 留言(0) 人氣()