JAVA 基礎程式設計班 [ 第 5 章 ] 字串 國立台灣大學資訊工程學系暨研究所 資訊系統訓練班 講師 : 宋浩
章節目錄 5-1 字串的基礎 5-2 StringBuffer 類別 5-3 StringBuilder 類別 5-4 字串比對與正規表示法 台灣大學資訊工程系資訊系統訓練班 2
5-1 字串的基礎 台灣大學資訊工程系資訊系統訓練班 3
字串的使用 字串是一種使用非常頻繁的資料型態 字串可以被視為一連串的字元所組合而成的資料型態 如果你參照 JDK 說明文件的內容, 雖然所看到的字串是以 char[] 型態來表示, 但在 Java 中, 字串和字元是屬於完全不同的資料型別 : 字元 是屬於 Character 類別或是 char 基本資料型態, 而 字串 是屬於 String 類別, 該類別是位在 java.lang 套件下 在 String 類別中擁有許多的方法可以被用來處理字串 由於字串內部是由字元陣列所組合而成的, 因此字串中的各個字元的排列方式也是和字元陣列相同 例如 : 字串 Java 的排列方式是 : J a v a [0] [1] [2] [3] 了解字串的這個特性將會對操作字串上會有很大的幫助 台灣大學資訊工程系資訊系統訓練班 4
字串的使用範例 public class BuildString { public static void main(string[] args) { // 使用字串常數建立字串 String str1 = new String(" 第一個字串 "); System.out.println(str1); // 使用字元陣列建立字串 char[] c = {' 第 ', ' 二 ', ' 個 ', ' 字 ', ' 串 '; String str2 = new String(c); System.out.println(str2); // 將字串常數指定給字串物件 String str3 = " 第三個字串 "; System.out.println(str3); 範例程式的執行結果 : 第一個字串第二個字串第三個字串 台灣大學資訊工程系資訊系統訓練班 5
Literal Pool (1) 因為字串是一種使用相當頻繁的資料型態, 為了使用上的方便性,Java 允許我們在程式中直接以字串常數來定義字串 : String str1 = " 這是一組字串 "; String str2 = " 這是一組字串 "; String str3 = new String (" 這是一組字串 "); String str4 = new String (" 這是一組字串 "); String str5 =" "; // 建構一個空字串 Java 的 Compiler 在遇到 String str2 = " 這是一組字串 "; 的宣告方式時, 會自動在所謂的 literal pool 中尋找是否有相同內容的字串常數 若有則傳回該字串常數的地址 若沒有, 則會建立一個新的 String 物件 台灣大學資訊工程系資訊系統訓練班 6
Literal Pool (2) 以下的範例程式示範這兩種方式建立的字串物件的比較結果 : class String1 { public static void main(string[] args){ String str1 = " 這是一組字串 "; // 利用字串常數建立字串 String str2 = " 這是一組字串 "; // 再利用字串常數建立字串 String str3 = new String(" 這是一組字串 "); String str4 = new String(" 這是一組字串 "); System.out.println("str1 和 str2 是否參考到同一物件 :" + (str1 == str2)); System.out.println("str1 和 str3 是否參考到同一物件 :" + (str1 == str3)); System.out.println("str3 和 str4 是否參考到同一物件 :" + (str3 == str4)); System.out.println("str1 和 str2 的內容是否相同 :" + str1.equals(str2)); System.out.println("str1 和 str3 的內容是否相同 :" + str1.equals(str3)); System.out.println("str3 和 str4 的內容是否相同 :" + str3.equals(str4)); 程式的執行結果為 : 台灣大學資訊工程系資訊系統訓練班 7
String 物件的常用方法 方法 char charat(int index) String concat(string str) boolean equals(object anobject) byte[] getbytes() int hashcode() int indexof(int ch) int length() String replace(char oldchar,char newchar) String substring(int beginindex) String substring(int beginindex,int endindex) char[] tochararray() String tolowercase() String touppercase() String trim() 公用取行字串中的 index 位置的字元將傳入的 str 字串連在呼叫該方法的字串後方比較字串物件和 anobject 物件是否相同將字串以位元陣列的型態傳回傳回字串的 hashcode 傳回 ch 字元在字串的位置取得字串的長度將字串的 oldchar 字元傳換成 newchar 字元從字串中第 beginindex 位置開始, 取出子字串取出字串中從 beginindex 位置到 endindex 位置的子字串將 String 物件的內容傳換為 char 陣列並傳回將 String 物件中的英文字轉為小寫並傳回將 String 物件中的英文字轉為大寫並傳回將字串兩端的空格移除 台灣大學資訊工程系資訊系統訓練班 8
字串屬性的取得及轉型 (1) class StringMethod1 { public static void main(string[] args) { String str = " 字串的操作 ABc"; // 宣告 String 物件, 並指定內容 int i; int slength = str.length(); System.out.println("str 字串的長度為 :" + slength); char[] tmpchar = str.tochararray(); // 將 str 轉換為 char 陣列 System.out.print("tmpChar 陣列的內容為 :"); for (i = 0; i < tmpchar.length; i++){ System.out.print(tmpChar[i]); System.out.println(); byte[] tmpbyte = str.getbytes(); // 將 str 轉換為 byte 陣列 System.out.print("tmpByter 陣列的內容為 :"); for (i = 0; i < tmpbyte.length; i++){ System.out.print(tmpByte[i] + " "); // 注意到每個中文字佔兩個 byte System.out.println(); String tmplower = str.tolowercase(); // 將字串中的英文字轉為小寫 System.out.println(" 英文字轉為小寫後的內容 :" + tmplower); String tmpupper = str.touppercase(); // 將字串中的英文字轉為大寫 System.out.println(" 英文字轉為大寫後的內容 :" + tmpupper); 台灣大學資訊工程系資訊系統訓練班 9
字串屬性的取得及轉型 (1) 程式的執行結果為 : 台灣大學資訊工程系資訊系統訓練班 10
字串內容的取得及搜尋 利用 charat 方法可以從字串中取出某個索引值位置的字元 indexof 方法可以用來在字串中搜尋特定的子字串 參考以下的範例 : class StringMethod2 { public static void main(string[] args) { String str = " 字串的操作 ABc, 字串方法的使用 "; int i; System.out.println("str 字串的內容是 :" + str); i = 2; // 設定 index 的值為 2 char find = str.charat(i); // 找出第三個字 System.out.println("str 字串的第三個字為 :" + find); // 宣告 String 物件, 並指定內容 String findstr = " 字串 "; // 設定需要搜尋的字串內容 i = str.indexof(findstr); // 找尋 字串 的位置 System.out.println(" 字串 在 str 中的第一個出現的位置是 :" + i); i = str.lastindexof(findstr); // 找尋 字串 最後出現的位置 System.out.println(" 字串 在 str 中的最後一個出現的位置是 :" + i); findstr = "Java"; // 重新設定字串的內容 i = str.indexof(findstr); // 找尋 Java 的位置, 這次找不到 System.out.println(" Java 在 str 中的第一個出現的位置是 :" + i); 程式的執行結果為 : 台灣大學資訊工程系資訊系統訓練班 11
字串內容的處理 (1) 除了使用 + 運算子之外, 使用 concat 方法也可連接字串 replace 方法可以用來將字串中的某個字元取代成另一個字元 substring 方法可以用來取出子字串 split 方法, 可以依照某個規則來分割字串 範例如下頁 台灣大學資訊工程系資訊系統訓練班 12
字串內容的處理 (2) class StringMethod3 { public static void main(string[] args){ String str = " 枯藤, 老樹, 昏鴉, "; // 宣告 String 物件, 並指定內容 String resultstr; System.out.println("str 字串的內容是 :" + str); resultstr = str.trim(); // 將原字串前後的空白刪除 System.out.println("==== 將字串的前後空白清除 ======="); System.out.println(" 新字串的內容是 :" + resultstr + "\n"); String addstr = " 小橋, 流水, 人家 "; System.out.println("==== 將原字串再連接新的字串 ======="); resultstr = resultstr.concat(addstr); // 再連接一組字串 System.out.println(" 連接後, 字串的內容是 :" + resultstr + "\n"); System.out.println("==== 取出原字串第 4 個字開始的內容 ======="); String tmpstr = resultstr.substring(3); // 取出第 4 個字 ( 含 ) 之後的所有內容 System.out.println(" 取出後, 新字串的內容是 :" + tmpstr + "\n"); System.out.println("==== 取出原字串第 4,5 個字的內容 ======="); tmpstr = resultstr.substring(3, 5); // 取出第 4~5 位置個字 ( 含 ) 之後的所有內容 System.out.println(" 取出後, 新字串的內容是 :" + tmpstr + "\n"); System.out.println("==== 將字串中的, 取代為 ======="); tmpstr = resultstr.replace(",", " "); System.out.println(" 取代後, 新字串的內容是 :" + tmpstr + "\n"); String[] splitstr; System.out.println("==== 在原字串中的 位置, 分成字串陣列 ======="); splitstr = tmpstr.split(" "); int i; for(i = 0; i < splitstr.length; i++){ System.out.println(splitStr[i]); 台灣大學資訊工程系資訊系統訓練班 13
字串內容的處理 (3) 程式的執行結果為 : 台灣大學資訊工程系資訊系統訓練班 14
課堂練習 (pt5-1) 大小寫轉換程式 (PT51.java): 設計一個程式能將輸入的英文字串字母中大寫的部份轉為小寫 小寫部份轉為大寫 例如 : 設定的字串為 :Hello Java 輸出的字串為 :hello java 台灣大學資訊工程系資訊系統訓練班 15
String 物件的內容無法更改 (1) String 物件一旦建立後, 其內容就無法再 更改 (immutable) 了 即使將該 String 變數重新指定新的內容,Java 的運作方式是新建立一個 String 物件, 在將新的 String 物件指定給 String 變數 要了解這個觀念前, 需要先了解 String 的儲存方式 如果希望在儲存 String 物件後, 並可以快速的再次找到該物件, 最好的方法就是將這些物件存在 雜湊表 (hash table) 中 Hash table 使用特定的演算法算出物件的 hash code, 然後再利用 hash code 到 table 中找出該物件 物件都能被存在 hash code 中, 不同的物件會有不同的 hash code 以 String 物件而言, 我們可以利用 hashcode 找出 String 的儲存位置, 而這個方法示覆寫自 Object 類別中的 hashcode 方法 參考以下的範例程式可以更了解這個概念 : class HashCode { public static void main(string[] args){ String str = "Hello World"; // 宣告 String 物件, 並指定內容 System.out.println(" 變更前,str 的 hash Code 為 :" + str.hashcode()); str = "Hello Java"; // 現在更改 str 的內容 System.out.println(" 變更後,str 的 hash Code 為 :" + str.hashcode()); 程式執行結果為 : 在執行範例程式時, 所得到的數值不會和上述的執行結果相同, 但 str 變更前後的 hash Code 是不會相同的 這告訴我們, 我們所謂的變更 String 物件的內容其實是另一個新的 String 物件的產生 台灣大學資訊工程系資訊系統訓練班 16
String 物件的內容無法更改 (2) class StringMethod4 { public static void main(string[] args){ String str = " Java "; // 宣告 String 物件, 並指定內容 System.out.println(" 相連前,str 字串的內容是 :" + str); String addstr = "Hello"; System.out.println("addstr 字串的內容是 :" + addstr); String resultstr; resultstr = str.concat(addstr); // 將字串相連並傳回 System.out.println(" 相連後,str 字串的內容是 :" + str); System.out.println(" 相連後,resultStr 字串的內容是 :" + resultstr); 程式執行的結果為 : 從程式第 8 行的執行結果可以觀察到,str 的內容一直都沒有變更過, 而 resultstr 物件變數指向的是一個新產生的 String 物件 台灣大學資訊工程系資訊系統訓練班 17
5-2 StringBuffer 類別 台灣大學資訊工程系資訊系統訓練班 18
StringBuffer 類別 (1) 雖然寫作程式時常會用到 String 物件, 但由於 Stiring 物件的內容無法變更, 且長度固定, 因此如果要處理一個需要時常變更內容的字串時, 直接利用 String 物件會比較不適合 因為每次變更字串內容時, 系統都會產生新的 String 物件, 並且必須對舊的 String 物件作資源回收的工作 這樣的作法會影響系統的效能 一般的作法是會利用 java.lang 套件中的 StringBuffer 類別來處理會變更內容的字串 StringBuffer 提供三種建立方式 ( 建構子 ): StringBuffer() 建構子 StringBuffer(int length) StringBuffer(String str) 作用 建構初步含資料的 StringBuffer 物件, 預設情況下,Java 會將該物件的初始化成可以儲存 16 個字元的情況 自行定義儲存字元的長度, 不含資料 以傳入的 str 參數建構出 StringBuffer 物件 StringBuffer 物件是可以變更長度及內容的, 雖然可以事先定義一個可以儲存 16 個字元的 StringBuffer 物件, 但使用時卻需要更大的容量時,JVM 會自動配置更多的儲存空間 台灣大學資訊工程系資訊系統訓練班 19
StringBuffer 類別 (2) 以下的範例都可以定義出 StringBuffer 物件 : // 定義一個可以儲存 16 字元的 StringBuffer 物件 StringBuffer str1 = new StringBuffer(); // 定義一個可以儲存 30 字元的 StringBuffer 物件 StringBuffer str2 = new StringBuffer(30); // 定義一個 StringBuffer 物件, 內容為 Hi StringBuffer str3 = new StringBuffer("Hi"); 更改 StringBuffer 物件的內容並不會產生一個新的物件, 這點和 String 物件不同 台灣大學資訊工程系資訊系統訓練班 20
StringBuffer 類別 (3) 以下的範例是使用 hashcode 方法找出 StringBuffer 物件的內容變更前後得儲存位置 : class HashCode1 { public static void main(string[] args){ StringBuffer str = new StringBuffer("Hello World"); // 宣告 StringBuffer 物件, 並指定內容 System.out.println(" 變更前,str 的 hash Code 為 :" + str.hashcode()); System.out.println(" 變更前,str 的內容為 ----- " + str); str.append(" Hello Java"); // 現在更改 str 的內容 System.out.println(" 變更後,str 的 hash Code 為 :" + str.hashcode()); System.out.println(" 變更後,str 的內容為 ----- " + str); String newstr = new String(str); System.out.println(" 新建立的 String 物件, 內容為 :" + newstr); System.out.println(" 新建立的 String 物件,hash Code 為 :" + newstr.hashcode()); 程式執行結果為 : 台灣大學資訊工程系資訊系統訓練班 21
StringBuffer 的方法 (1) StringBuffer 類別提供的方法和 String 類別的方法的使用大致相同, 但 StringBuffer 類別中提供額外的字串的操作方法有 : 方法 StringBuffer append(object obj) int capacity() StringBuffer delete(int start,int end) StringBuffer deleteat(int index) 功用 將 obj 物件增加到 StringBuffer 物件的緩衝區後 取得 StringBuffer 緩衝區的大小 移除緩衝區中由 start 到 end 位置的字元 移除緩衝區中的 index 位置的字元 StringBuffer insert(int offset,object obj) 將 obj 物件加入 StringBuffer 物件中的 offset 位置之後 StringBuffer reverse() 將緩衝區中的字串反向排列 台灣大學資訊工程系資訊系統訓練班 22
StringBuffer 的方法 (2) 在 StringBuffer 類別中, 除了可以使用 length() 方法取得物件的長度之外, 也可以使用 capacity() 方法來取得物件的緩衝區的大小, 例如 : class SB1 { public static void main(string[] args){ StringBuffer sb = new StringBuffer(); //sb 的緩衝區有 16 個字元 System.out.println(" 目前 sb 的緩衝區為 :" + sb.capacity()); sb.append("hello"); // 儲存了 5 個字元 System.out.println("sb 的長度為 :" + sb.length()); System.out.println(" 現在 sb 的緩衝區為 :" + sb.capacity()); 程式執行結果為 : 範例程式第 3 行定義了一個 StringBuffer 物件, 預設的緩衝區大小為 16 個字元 緩衝區的大小是物件儲存的內容在加上預留的空間的大小, 它不是固定的是數值 程式的第 6 行的內容變更了 StringBuffer 物件的內容, 該長度為 5 你可以觀察到目前的緩衝區的大小仍是 16 台灣大學資訊工程系資訊系統訓練班 23
StringBuffer 來操作字串 (1) class SB2 { public static void main(string[] args){ // 建構 StringBuffer 物件 StringBuffer sb = new StringBuffer("This is a book"); System.out.println(" 目前 sb 的內容為 :" + sb); System.out.println(" 開始前,sb 的 HashCode 為 ----" + sb.hashcode()); // 利用 setcharat 設定字串緩衝區的內容 sb.setcharat(2, 'a'); sb.setcharat(3, 't'); System.out.println(" 使用 setcharat 後,sb 的內容為 :" + sb); // 使用 append 新增字串緩衝區的內容 sb.append(", or a magazine"); System.out.println(" 使用 append 後,sb 的內容為 :" + sb); // 使用 insert 新增字串到緩衝區中的特定位置 sb.insert(0, "I guess "); System.out.println(" 使用 insert 後,sb 的內容為 :" + sb); // 使用 delete 刪除字串緩衝區的內容 sb.delete(0, 8); System.out.println(" 使用 delete 後,sb 的內容為 :" + sb); // 使用 replace 取代字串緩衝區的內容 // 將 That 更改為 This sb.replace(0, 4, "This"); System.out.println(" 使用 replace 後,sb 的內容為 :" + sb); // 使用 reverse 將字串緩衝區的內容反轉 sb.reverse(); System.out.println(" 使用 reverse 後,sb 的內容為 :" + sb); System.out.println(" 操作後,sb 的 HashCode 為 ----" + sb.hashcode()); 台灣大學資訊工程系資訊系統訓練班 24
StringBuffer 來操作字串 (2) 程式執行結果為 : 範例程式的內容很容易理解 但是請注意整個範例程式中我們只使用了 sb 這個 StringBuffer 物件, 而且在整個程式的操作過程中, 並沒有新的物件產生 台灣大學資訊工程系資訊系統訓練班 25
課堂練習 (pt5-2) 加密程式 (PT52.java): 設計一個加密程式, 該程式能夠將各英文字元轉換成下一個字元順序的字元, 例如 : 輸入 a, 輸出 b 轉換完成後, 再將字串反向輸出 例如 : 輸入 Hello 會得到 Ifmmp, 反向後輸出為 pmmfi 台灣大學資訊工程系資訊系統訓練班 26
5-3 StringBuilder 類別 台灣大學資訊工程系資訊系統訓練班 27
StringBuilder 類別 效能比 StringBuffer 快! 缺點 : 沒有 thread safe ( 不支援多執行緒 ) 因此在沒有需要多執行緒的環境中 使用 StringBuilder 會得到較高的效能! StringBuffer sb = new StringBuffer(); 改成 : StringBuilder sb = new StringBuilder(); 台灣大學資訊工程系資訊系統訓練班 28
5-4 字串比對與正規表示法 台灣大學資訊工程系資訊系統訓練班 29
比對字串的內容 (1) class StringMatches { public static void main(string[] args) { if (args[0].matches("allan")) { System.out.print("Hi Allan 歡迎你!"); else { System.out.print(" 請問你是哪位?"); matches 方法看起來跟 equals() 功能沒什麼兩樣, 但 matches 方法功能強大多! 台灣大學資訊工程系資訊系統訓練班 30
比對字串的內容 (2) 剛剛的程式有個缺點, 如果使用者輸入的是小寫開頭 allan, 程式會判斷成 false! 當然, 你可以改成 if else if else 的,Allan allan 各比對一次 但其實有更好的作法, 請看下面的範例 : class StringMatches2 { public static void main(string[] args) { if (args[0].matches("[aa]llan")) { System.out.print("Hi Allan 歡迎你!"); else { System.out.print(" 請問你是哪位?"); 這樣輸入 Allan 或 allan 就都能得到 Hi Allan 歡迎你! 的正確訊息了! 台灣大學資訊工程系資訊系統訓練班 31
正規表示法 (1) Regular Expression 剛剛我們用的 [Aa] 其實是使用了正規表示法, 正規表示法對於字串處理 判斷是非常重要的技術 http://download.oracle.com/javase/6/docs/ api/java/util/regex/pattern.html 介紹了正規表示法的內容 台灣大學資訊工程系資訊系統訓練班 32
正規表示法 (2) 正規表示法的表示字串的內容主要可以分成兩大類 : Characters: 一般字元 ( 文數字元 ), 所代表的意義與原字面的意義相同 Operators: 特殊字元 ( 非文數字字元 ), 代表某種特殊規則的意義 若要取消其代表意義, 必須使用 \ 跳脫字元 台灣大學資訊工程系資訊系統訓練班 33
正規表示法 (3) "foo" 的 RE 表示字串 "foo" 的意思 "[Ff]oo" 的 RE 表示字串 "Foo" 或字串 "foo" 的意思 "F*" 的 RE 表示 F 這個字元會出現 0 次或多次 "F\*" 的 RE 表示字串 "F*" 的意思 台灣大學資訊工程系資訊系統訓練班 34
正規表示法 (4). 句號 (period) 代表任意一個字元, 如.at 可符合 bat, cat, rat 等任何字開頭, 結尾是 at 的單字 [ ] 中括號 (brackets) 代表集合中的任一字元, 如 [01256] 代表 0,1,2,5,6 這個集合中的任何一個字元 - 連字號 (dash) 在中括號內表示 範圍, 如 [0-9] 代表 0 到 9 的任一個單一的數字 ^ (carat) 在中括號內表示 否定, [^aeiou] 代表除了 a,e,i,o,u 這幾個母音之外的字元 台灣大學資訊工程系資訊系統訓練班 35
正規表示法 (5) (pipe) 表示可選擇的, 如 cat dog bird 代表 cat, dog, bird 其中之一皆可 (or 的概念 )? 問號 (question mark) 表示前面的字元或集合出現 0 次或 1 次, 如 colou?r 代表 u 這個字可出現也可不出現 + 加號 (plus) 表示前面的字元或集合出現 1 次或多次, 如 ap+le 代表 p 這個字至少出現 1 次 * 星號 (asterisk) 表示前面的字元或集合出現 0 次或多次, 如 section [0-9]* 代表數字可出現也可不出現 { 大括號 (curly-braces) 表示前面的字元或集合出現的次數, 如 c{5,8 代表 c 這個字重複出現 5 到 8 次 台灣大學資訊工程系資訊系統訓練班 36
正規表示法 (6) 整理一下 [abc] a b 或 c [^abc] 非 a b c 的其它字元 [a-za-z] a 到 z 或 A 到 Z( 範圍 ) [a-d[m-p]] a 到 d 或 m 到 p( 聯集 ) [a-z&&[def]] d e 或 f( 交集 ) [a-z&&[^bc]] a 到 z, 除了 b 與 c 之外 ( 減集 ) [a-z&&[^m-p]] a 到 z 且沒有 m 到 p(a-lq-z)( 減集 ) X? X 出現一次或完全沒有 X* X 出現零次或多次 X+ X 出現一次或多次 X{n X 出現 n 次 X{n, X 出現至少 n 次 X{, m X 出現不超過 m 次 X{n, m X 出現至少 n 次, 但不超過 m 次 台灣大學資訊工程系資訊系統訓練班 37
正規表示法 (7) 練習 1 [15]0* 10{2,41 1. 1 1. 101 2. 6 2. 1001 3. 50 3. 10001 4. 600 4. 100001 5. 1000 5. 1000001 6. 5000 台灣大學資訊工程系資訊系統訓練班 38
正規表示法 (8) 練習 2 1. 5am 2. p43 3. mma 4. qk4 5. bom [k-q].[^4-9] 1. 4 2. 54 3. m0 4. s4a 5. mq [^a-k]+[0-9]?. 台灣大學資訊工程系資訊系統訓練班 39
正規表示法的應用 (1-1) 日期格式驗證 : 中式寫法 :YYYY-MM-DD (2011-12-31) 西式寫法 :MM/DD/YY (12/31/11) 日期格式規則 : 只有數字,1 ~ 4 位數 只有 0~9 / - [0-9] {1,4[\\-/]?[0-9]{1,2[\\-/]?[0-9]{1,4 台灣大學資訊工程系資訊系統訓練班 40
正規表示法的應用 (1-2) class CheckDate { public static void main(string[] args) { String input = args[0]; String pattern = " [0-9]{1,4[\\-/]?[0-9]{1,2[\\-/]?[0-9]{1,4"; if (input.matches(pattern)) { System.out.print(" 日期格式正確!"); else { System.out.print(" 你輸入的不是日期!"); 台灣大學資訊工程系資訊系統訓練班 41
正規表示法的應用 (2-1) 電子郵件地址格式驗證 : 帳號 @ 網域 ( 只能有一個 @) 帳號規則 : 英文 數字 或有. (dot) 或 _ (underscore) 或 - (dash) 網域規則 : 至少要有一個. (dot) 例 csie.org 也有可能有 n 個. 例 mail.ntu.edu.tw 英文 數字 或有. (dot) 或 _ (underscore) 或 - (dash) [^@]+@[a-za-z0-9\\._\\-]+\\.[a-za-z]+ 台灣大學資訊工程系資訊系統訓練班 42
正規表示法的應用 (2-2) class CheckEmail { public static void main(string[] args) { String input = args[0]; String pattern = "[^@]+@[a-za-z0-9\\._\\-]+\\.[a-za-z]+"; if (input.matches(pattern)) { System.out.print("Email 格式正確!"); else { System.out.print(" 你輸入的不是 Email!"); 台灣大學資訊工程系資訊系統訓練班 43
課堂練習 (pt5-3) 電話號碼格式驗證 (PT53.java): 使用正規表示法寫一個能驗證是否符合電話號碼 ( 含行動電話 ) 的程式 手機號碼 :0912345678 / 0912-345-678 一般號碼 :(02)23939889 / 02-2393-9889 電話號碼規則 : 最少大約 6 個號碼 最多呢? 只有 0~9 ( ) - 與空白 台灣大學資訊工程系資訊系統訓練班 44
正規表示法的應用 (3-1) 中華民國身分證字號驗證 先講講規則 :A123456789 (1) 第 1 個字元代表地區, 轉換方式為 :A 轉換成 1,0 兩個字元,B 轉換成 1,1 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 10 11 12 13 14 15 16 17 34 18 19 20 21 22 35 23 24 25 26 27 28 29 32 30 31 33 (2) 第 2 個字元代表性別,1 代表男性,2 代表女性 (3) 第 3 個字元到第九個字元為流水號碼 (4) 第 10 個字元為檢查號碼 台灣大學資訊工程系資訊系統訓練班 45
正規表示法的應用 (3-2) 1 每個相對應數字乘上權數 A 1 2 3 4 5 6 7 8 1 0 x8 x7 x6 x5 x4 x3 x2 x1 x1 X9 檢查號碼 9 2. 將乘上權數後之積相加 3. 相加後之值除以模數 10 取其餘數 121 / 10 = 12 餘數 1 4. 由模數減去餘數得檢查號碼, 若餘數為 0 時, 則設定其檢查碼為 0 10 1 = 9 台灣大學資訊工程系資訊系統訓練班 46
public class CheckPersonalID { public static void main(string[] args) { boolean check = false; String input = args[0]; if (input.matches("[a-za-z]{1[0-9]{9")) { check = checkpid(input); if (check) { System.out.println(" 身份證字號正確!"); else { System.out.println(" 身份證字號錯誤! 請檢查看看!"); public static boolean checkpid(string input) { // 第一個字母對應的數字表 int[] num = {10, 11, 12, 13, 14, 15, 16, 17, 34, 18, 19, 20, 21, 22, 35, 23, 24, 25, 26, 27, 28, 29, 32, 30, 31, 33; // 把第一個字母轉成大寫 String inputtoupper = input.touppercase(); byte[] idtobyte = inputtoupper.getbytes(); int[] idtocount = new int[idtobyte.length + 1]; // 處理第一個字 int firstchar = num[idtobyte[0] - 65]; idtocount[0] = (int)math.floor(firstchar / 10); idtocount[1] = (firstchar % 10); // 取出第一個字母對應的數字 // 第一個字母的第一個數字 // 第一個字母的第二個數字 // 第一個數字開始及以後的數字 for (int i =1; i < idtobyte.length; i++) { idtocount[i+1] = (idtobyte[i] - 48); // 開始計算總和 int total = idtocount[0]; for (int i = 1; i < idtocount.length - 1; i++) { total += (idtocount[i] * (10 - i)); return (idtocount[idtocount.length - 1] == (10 - (total % 10)))? true : false; 台灣大學資訊工程系資訊系統訓練班 47
回家作業 HW5 1. 解密程式 (HW51.java): 設計一個能將 PT52.java 的程式加密過的字串解密回原始字串的解密程式 2. 驗證網址程式 (HW52.java): 請用正規表示法設計一個可以驗證是否為真實網址的程式網址的規則 : 一定是 http:// 開頭至少有一個. (dot) 最後一個. 後面的只能為英文字母最後一個. 前面至少有一個字元例 :http://google.com http://www.hinet.net http://www.ntu.edu.tw 3. 進階排序程式 (HW53.java): 請寫一個程式讓使用者可以用自己輸入的 n 個數字做排序用正規表示法檢查使用者輸入的是否是數字並輸出排序後的結果 台灣大學資訊工程系資訊系統訓練班 48
繳交回家作業 pt5 ( 課堂練習 ) 與 hw5 ( 回家作業 ) 請一起繳交 把相關 *.java 檔案以 zip 或 rar 壓縮並取名為 學號.zip 或 學號.rar 並附件到 email 中寄到 : 主旨 :[JAVA245][hw][5] 姓名 收件人 :allan@csie.org Deadline: 下一次上課前 台灣大學資訊工程系資訊系統訓練班 49