//id.java import java.io.*; class id { BufferedReader cin = null ; PrintStream cout = null; int rand( ) { return (int)(Math.random( ) * 32768.0); } public static void main(String xxx[ ]) { new id( ); } id( ) { prepareIO( ); main( ); // original main( ) in C }//id( id(BufferedReader cin, PrintStream ooo) { ////////// this.cin = cin; cout = ooo; main( ); // original main( ) in C }//id( void prepareIO( ) { try { cin = new BufferedReader( new InputStreamReader( System.in ) ); cout = new PrintStream( System.out ); }catch(Exception e) { } } // IO ok /************* //idcheck.c -- by tsaiwn@csie.nctu.edu.tw #include #include void genID( ), squeeze(char*); // 宣告兩個 function int testID(char*); // 查驗身分證各種可能的錯誤 並傳回錯誤代碼 void printError(int code); // print error message according code // Java 不需要宣告, 因為在 class 內沒有先後關係 //寫個程式可以檢查身分證號碼是否正確 //Extra credit: 輸入 999 則產生一個可用的合法身分證號碼 *************************************************************/ int main( ) { String id=null; // static char id[99]; // 夠'長吧 :-) 身分證才 10 碼啦 int code = 0; // 用來記住錯誤代碼 while(38 == 38) { // for( ;; ) { cout.printf("請輸入身分證號碼 Input ID: "); try{ id = cin.readLine( ) ; //fgets(id, sizeof(id), stdin); // 整列讀入 到 id }catch(Exception e) { e.printStackTrace( ); } if(id==null) break; //if(feof(stdin)) break; id = id.replace(" ", ""); //squeeze(id); // 把所有空白都去掉 white space if(id.equals("-1") ) break; //if(strcmp(id, "-1") == 0) break; if(id.equals("quit") ) break; //if(strcmp(id, "quit") == 0) break; if(id.toUpperCase( ).equals("quit".toUpperCase( )) ) break; if(id.equals("999") ) {genID( ); continue; } // if(strcmp(id, "999") == 0) {genID( ); continue; } code = testID(id); // 取得錯誤代號, 0 表示無錯 :-) cout.printf(" ID %s is ", id); if(code==0) cout.printf(" OK.\n"); // 印出說這號碼正確 else { cout.printf(" Error! Reason(s):\n"); printError(code); // 依據 code 印訊息 }//if }// while( cout.printf("\r\nThank you and bye bye!\n"); return 0; } // main( /****** Java 沒用 !!! //關於 squeeze(char*) 這好用的 function, 因為 C 程式庫沒有,自己寫: void squeeze(char*p) { // 擠掉所有的 white space char*p2 = p; if(*p == 0)return; while(*p2 !=0) { // white space 請看 K&R課本第二章與附錄 B if(isspace(*p2)) { ++p2; continue; } // 丟掉 white space *p = *p2; p++; ++p2; // advance one char }//while *p = *p2; // 0 == '\0' == NULL }// squeeze( ******************************************/ // 關於 int testID(char* id) : 依據身分證規則查看 id 傳回錯誤代碼 int yy[ ]={ 10,11,12,13,14,15,16,17, 34, //ABCDEFGH I 18,19,20,21,22, 35, //JKLMN O 23,24,25,26,27,28, //PQRSTU 29,32,30,31, 33 }; //VWXY Z /***** int checkSum(char * id){ // 幫忙算 checkSum 給 testID(id) 用 *******/ int checkSum(String idid){ String id = idid; while(id.length() < 10) id = id+"0"; // 防呆 int sum, i; // 因編碼沒完全照字母順序, 用算的要很多 if(... int ynum; // 用查表法 table look up 查出字母對應的兩位數較簡單直覺 ! // 先建個表 int yy[ ] = { 10, 11, 12, 13, ...}; // 照規定 AB.. // 然後 Let i = id[0]字母減去 'A' 得到 0..25 // 再查出 yy[i] 拿來用: ynum = yy[i]; // 10..O是35..Z不是35 !! i = Character.toUpperCase( id.charAt(0) ) - 'A'; ynum = yy[i]; sum = ynum/10 + 9* (ynum%10); // weight 1, 9, [876543211] for(i=1; i<=8; ++i) sum += (id.charAt(i) - '0') *(9-i); // 87654321 sum += (id.charAt(9) - '0') ; // *1 檢查碼 weight 也是 1 return sum; // 我只負責算出 checksum }//checkSum( /****** int testID(char* id) { //傳回錯誤代碼, 可用 bitwise "&" 運算找出 ********/ int testID(String idid) { String id = idid; if(id.length( ) < 1) id = "?"; // 防呆 if(id.length( ) < 2) id = id+"?"; // 防呆 int i, ans = 0, sum=0; // sum 用來算 weighted check sum char id00 = Character.toUpperCase(id.charAt(0)); // 轉為大寫 if(!Character.isLetter(id00)) ans = ans + 1; // 1 號錯 ans = ans | 1; if(id.charAt(1) != '1' && id.charAt(1) != '2') ans += 2; // 2 號錯 男生女生? if(id.length( ) < 10) ans += 4; // 太短 if(id.length( ) > 10) ans += 8; // 太長 for(i=1; i<= id.length( )-1; ++i) if(!Character.isDigit(id.charAt(i))) ans = ans | 16; // 非數字 if((ans&16) != 0) return ans; // 有非數字不用再算 check sum 啦 if(ans != 0) return ans; // 有任何錯就..就不用再算 check sum 啦 sum = checkSum(id); // 假設沒有其他怪字就算出 check sum if(sum%10 != 0) ans |= 32; // 必須除以 10 除得盡才對 return ans; }// testID( String what[ ]={ "對啦!!這是合法的身份證字號", //訊息0 "ㄟ..第一個字非字母", // 訊息1 "你是第三性嗎?", // 訊息2 "太短了!不足碼唷!!", // 訊息3 "怎麼會有這麼多碼!!", // 訊息4 "打錯啦!!應該是數字喔!!", // 訊息5 "神秘數字算出來是錯的??" // 訊息6 }; // String what[ ] = { ....}; void printError(int code) { int i, yy[ ] = {0, 1, 2, 4, 8, 16, 32, 64, 128}; if(code == 0) { cout.printf("%s\n", what[0]); return; } for(i=1; i <= 6; ++i)if((code&yy[i])!=0) cout.printf("\r%s\n", what[i]); }// printError( void genID( ) { String id = ""; //char id[11]={ 0 }; int i; id = id + (char)( 'A' + rand( ) % 26) ; // 'A' .. 'Z' id += (char)( '1' + rand( ) % 2 ); // '1' .. '2' for(i=2; i<=8; ++i) { id += (char)( '0' + rand( )%10 ); // 用亂數生出 id[2] .. id[8] } // /// id[9] 是檢查碼, 要算, 可先塞 '0' 偷叫 checkSum( )再調整 int sum = checkSum( id+"0"); sum = 10 - (sum%10); if(sum == 10) sum = 0; id = id + sum; // sum 會自己變成字串 cout.printf(" Good ID: %s\n", id); }// genID( }//class