2021年8月30日 星期一

JAVA 例外處理-02 各種例外

  本程式在 try 區的程式碼只有三種可能會出現的例外,除以 0 、陣列溢位、使用方法的輸入參數不符、物件為 null 的情況,但我 catch 的部份還是多寫了儲存陣列元素型態不符,主要是為了日後查指令時方便。

  主程式中利用亂數決定要用陣列的哪個元素進行轉整數與相除運算,所以每一次出現的情況可能會不同,可能順利的完成,也可能產生例外。

  順道一題, catch 捕捉的物件名稱都一樣,只是型別不同,這跟多載(過載)相同, JAVA 會自動找合適的 catch 去捕捉物件。

程式碼:

public class Main {

// 類別方法,顯示例外訊息。
static void showErr(Exception ecp){
// Exception 是其它例外類別的父類別,所以可以用渣男寫法。
System.out.println("發生例外:" + ecp.getMessage());
//System.out.println("原因如下:");
}

public static void main(String[] args){
String[] text = { null, "44", "22", "11", "0",
"愛未未","恨已已","情深深","仇切切"};

try{ // 這邊寫可能會出現例外的程式碼,執行時若出現例外,會丟出例外物件給 catch

int i,ratio;
double r = Math.random()*10;
i = (int)(r);
System.out.println("亂數 r = " + r + ",小數捨去化為整數 i = " + i);
ratio = Integer.parseInt(text[i])/Integer.parseInt(text[i+1]);
System.out.println("參數比例 = "+ratio);
}
catch (ArithmeticException ecp){ // 捕捉【除以 0 的例外物件】。
showErr(ecp);
}
catch (ArrayIndexOutOfBoundsException ecp){ // 補捉【陣列溢位的例外物件】。
showErr(ecp);
}
catch (ArrayStoreException ecp){ // 捕捉【陣列儲存型態不符的例外物件】。
showErr(ecp);
}
catch (IllegalArgumentException ecp){
// 捕捉【使用的方法時,丟入的參數型態不同的例外物件】。
showErr(ecp);
}
catch (NullPointerException ecp) { // 捕捉【物件值為 null 的例外物件】。
showErr(ecp);
}

finally {
System.out.println("無論有沒有出現例外都會出現這一行!");
}

System.out.println("程式結束了!");

}
}

結果:

亂數 r = 5.228886020103869,小數捨去化為整數 i = 5
發生例外:For input string: "愛未未"
無論有沒有出現例外都會出現這一行!
程式結束了!

Process finished with exit code 0


我手邊的書還有丟出例外與自訂例外類別,暫且就先跳過。執行緒的部份,不想花時間改程式碼以避開著作權,所以決定練習不放上來。

2021年8月26日 星期四

JAVA 例外處理-01 try、catch、finally

例外處理的目的是為了避免程式崩潰,可以處理的例外有數學運算產生的,例如除以 0 、陣列索引在設定之外產生的、儲存陣列元素的型態不符產的、呼叫方法時,參數型態不同產生的、物件值為 null 產生的。

主程式 

public class Main {
public static void main(String[] args){
int i,j;
j=0;

try{
for (i = 2; i > -100; i--){
System.out.println("i= " + i + ",則 10/i = " + 10/i);
j=j+1;
}
// 如果沒有問題的話,程式會跑完迴圈,但這邊故意設了一個會除以 0 的情況,
// 該情況下會出錯,所以 catch 段的程式會執行,而且迴圈只會執行到此斷點。

System.out.println("出現此行,表示迴圈有跑完。");
// 實際上上面這一行不會出現在結果中,因為更前面已經出現例外了。
}
catch (ArithmeticException gg){
// 如果沒有例外,此區塊的程式碼不會被執行。
// 這邊的 gg 是送到 catch 方法裡面的 ArithmeticException 物件名稱,
// 名字可以隨便取。
System.out.println("例外說明:" + gg.getMessage());
// 展示 gg 物件得到的系統訊息。
System.out.println("例外原因:");
gg.printStackTrace();
// 有了上面這一行,出現例外的情況下,程式在執行完後會顯示程式呼叫的執行過程。
}
finally {
System.out.println("例外處理結束!迴圈共跑了 " + j + " 次。");
// 無論有沒有例外,上面這一行都會出現,表示此區程式一定會執行。
}

System.out.println("程式結束!");
}
}

結果:

i= 2,則 10/i = 5
i= 1,則 10/i = 10
例外說明:/ by zero
例外原因:
例外處理結束!迴圈共跑了 2 次。
程式結束!
java.lang.ArithmeticException: / by zero
	at Main.main(Main.java:8)

Process finished with exit code 0

其中 catch 的區塊可以有好幾個,最保險的方式是 try 區塊中的程式可能出現多少種例外,就有多少個 catch 來以確保程式不會崩潰。

2021年8月9日 星期一

c++ 判斷質數練習

  這個是小孩子的作業,其實我以前也用 python 做過類似的練習,那時是找出某個數字以下的所有質數,這次只是判斷一個數字。

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

#include <iostream>

// 這個程式功用是判斷數字是否為質數,在數字不大的情況下,這應該是簡單度與效率的最好比例了。 

using namespace std;

int main() { 


unsigned int a,b,c,d;

//cout << "請輸入數字 \n";

//cin >> a;

//a=2147483647;

a=4294967291;

b=1;

d= a/2;

c=1;

//cout << c << endl; 

while( b<d and c!=0) 

{

b=b+1;

c=a%b;

}

if(c==0){

cout << "不是質數!\n";

}

else{

cout << "質數!\n";

}

cout << "程式結束!";

    return 0; 

}

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

以下是執行結果:

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

請輸入數字

2147483647

質數!

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

我對質數有些好奇,但研究的人實在太多了,意即我投入時間研究大概也很難有新發現,但或許未來有空,還是可以探索一下的。所以留下 C++ 讀取與輸出文字檔的範例連結給未來的自己。

讀取:https://shengyu7697.github.io/cpp-read-text-file/

寫入:https://shengyu7697.github.io/cpp-write-text-file/

另外是質數研究的介紹:https://math.ntnu.edu.tw/~horng/letter/hpm16011.pdf