1 //idcheck.c -- by tsaiwn@csie.nctu.edu.tw 2 //gcc idcheck.c 3 //寫個程式可以檢查身分證號碼是否正確 4 //Extra credit: 輸入 999 則產生一個可用的合法身分證號碼 5 //////////// 6 #include <stdio.h> 7 #include <ctype.h> 8 void generateID( ), squeeze(char*); // 宣告兩個 function 9 int testID(char*); // 查驗身分證各種可能的錯誤 並傳回錯誤代碼 10 void printError(int code); // print error message according code 11 12 // 注意 Java 不需要宣告, 因為在 class 內沒有先後關係 13 14 int main( ) { 15 static char id[99]; // 夠'長吧 :-) 身分證才 10 碼啦 16 int code = 0; // 用來記住錯誤代碼 17 while(38 == 38) { // for( ;; ) { 18 printf("請輸入身分證號碼 Input ID: "); 19 fgets(id, sizeof(id), stdin); // 整列讀入 到 id 20 // check EOF 21 if(feof(stdin)) break; //EOF == ^D in Unix; ^Z on DOS/Window 22 squeeze(id); // 把所有空白都去掉 white space 23 //printf("strlen(id)=%d\n", strlen(id)); 24 if(strcmp(id, "-1") == 0) break; //Java 用 id.equals("-1") 25 if(strcmp(id, ".") == 0) break; 26 if(strcmp(id, "quit") == 0) break; 27 if(id[1] == 'U') break; // QUIT ? // Java 用 id.charAt(1)== 28 if(strcmp(id, "999") == 0) {generateID( ); continue; } 29 code = testID(id); // 取得錯誤代號, 0 表示無錯 :-) 30 printf(" ID %s is ", id); 31 if(code==0) printf(" OK.\n"); // 印出說這號碼正確 32 else { 33 printf(" Error ID! Reason(s):\n"); 34 }//if 35 printError(code); // 依據 code 印訊息 36 }// while( 37 printf("\r\nThank you and bye bye!\n"); 38 return 0; 39 }//main( 40 41 //關於 squeeze(char*) 這好用的 function, 因為 C 程式庫沒有,自己寫: 42 //注意 NewLine 也算 white space, 所以這函數也會把尾巴的 '\n' 拿掉! 43 // 因為 fgets 讀入的資料尾巴有 NewLine; C++ 的 getline 則沒有 NewLine! 44 void squeeze(char*p) { // 擠掉所有的 white space; Java 要如何做呢? 45 char*p2 = p; 46 if(*p == 0)return; // NULL terminated, 一開始就字串結束: 空字串 47 while(*p2 !=0) { // white space 請看 K&R課本第二章與附錄 B 48 if(isspace(*p2)) { ++p2; continue; } // 丟掉 white space 49 *p = *p2; 50 p++; ++p2; // advance one char 51 }//while 52 *p = *p2; // 0 == '\0' == NULL 53 }// squeeze( 54 55 // 關於 int testID(char* id) : 依據身分證規則查看 id 傳回錯誤代碼 56 int yy[ ]={ 10,11,12,13,14,15,16,17, 34, //ABCDEFGH I 57 18,19,20,21,22, 35, //JKLMN O 58 23,24,25,26,27,28, //PQRSTU 59 29,32,30,31, 33 }; //VWXY Z 60 int checkSum(char * id){ // 幫忙算 checkSum 給 testID(id) 用 61 int sum, i; // 因編碼沒完全照字母順序, 用算的要很多 if(... 62 int ynum; 63 // 用查表法 table look up 查出字母對應的兩位數較簡單直覺 ! 64 // 先建個表 int yy[ ] = { 10, 11, 12, 13, ...}; // 照規定 AB.. 65 // 然後 Let i = id[0]字母減去 'A' 得到 0..25 66 // 再查出 yy[i] 拿來用: ynum = yy[i]; // 10..O是35..Z不是35 !! 67 i = id[0] - 'A'; 68 ynum = yy[i]; 69 sum = ynum/10 + 9* (ynum%10); // weight 1, 9, [876543211] 70 for(i=1; i<=8; ++i) sum += (id[i] - '0') *(9-i); // 87654321 71 sum += (id[9] - '0') ; // *1 檢查碼 weight 也是 1 72 return sum; // 我只負責算出 checksum 73 }//checkSum( 74 75 int testID(char* id) { //傳回錯誤代碼, 可用 bitwise "&" 運算找出 76 int i, ans = 0, sum=0; // sum 用來算 weighted check sum 77 id[0] = toupper(id[0]); // 轉為大寫 78 if(!isalpha(id[0])) ans = ans + 1; // 1 號錯 ans = ans | 1; 79 if(id[1] != '1' && id[1] != '2') ans += 2; // 2 號錯 男生女生? 80 if(strlen(id) < 10) ans += 4; // 太短 81 if(strlen(id) > 10) ans += 8; // 太長 82 for(i=1; i<=9; ++i) if(!isdigit(id[i])) ans = ans | 16; // 非數字 83 if((ans&16) != 0) return ans; // 有非數字不用再算 check sum 啦 84 if(ans != 0) return ans; // 有任何錯就..就不用再算 check sum 啦 85 sum = checkSum(id); // 假設沒有其他怪字就算出 check sum 86 if(sum%10 != 0) ans |= 32; // 必須除以 10 除得盡才對 87 return ans; 88 }// testID( 89 90 char what[ ][88]={ "對啦!!這是合法的身份證字號", //訊息0 91 "ㄟ..第一個字必須是字母啦!", // 訊息1 92 "你是第三性嗎?", // 訊息2 93 "太短了!不足碼唷!!", // 訊息3 94 "怎麼會有這麼多碼!!", // 訊息4 95 "打錯啦!!應該是數字喔!!", // 訊息5 96 "神秘數字算出來是錯的??" // 訊息6 97 }; // do NOT forget the ";" 98 // String what[ ] = { ... }; // in Java 99 void printError(int code) { // print all errors found use bitwise and 100 int i, yy[ ] = {0, 1, 2, 4, 8, 16, 32, 64, 128}; 101 if(code == 0) { printf("%s\n", what[0]); return; } 102 for(i=1; i <= 6; ++i)if((code&yy[i]) != 0)printf("%s\n", what[i]); 103 }// printError( 104 105 void generateID( ) { 106 char id[11]={ 0 }; // 會全放 0 (NULL) == '\0' == 0 107 int i; 108 id[0] = 'A' + rand( ) % 26; // 'A' .. 'Z' 109 id[1] = '1' + rand( ) % 2; // '1' .. '2' 110 for(i=2; i<=8; ++i) { 111 // 用亂數生出 id[2] .. id[8] 112 id[i] = '0' + rand( )%10; // '0' .. '9' 113 } // 114 /// id[9] 是檢查碼, 要算, 可先塞 '0' 偷叫 checkSum( )再調整 115 id[9] = '0'; 116 i = checkSum(id); // 借用 i 來存 checkSum 117 i = i % 10; 118 if(i != 0) id[9] = '0' + (10-i); // 更正檢查碼 119 printf(" Good ID: %s\n", id); // legal ID now 120 }// generateID(You are the
1 //idcheck.java -- by tsaiwn@csie.nctu.edu.tw 2 // Reference answer to the LAB04 3 class idcheck extends c2java { 4 // extends c2java 後只要把字串與指標以及用到 fgets, scanf 略改就可! 5 // 注意若不 extends c2java, 則須把 c2java.java 內容抄入這 6 /////// 但要注意 constructor 名稱! 7 public static void main(String xx[]) { 8 idcheck me = new idcheck( ); 9 me.main( ); 10 } 11 //idcheck.c -- by tsaiwn@csie.nctu.edu.tw 12 //gcc idcheck.c 13 //寫個程式可以檢查身分證號碼是否正確 14 //Extra credit: 輸入 999 則產生一個可用的合法身分證號碼 15 //////////// 16 //#include <stdio.h> 17 //#include <ctype.h> 18 //void generateID( ), squeeze(char*); // 宣告兩個 function 19 //int testID(char*); // 查驗身分證各種可能的錯誤 並傳回錯誤代碼 20 //void printError(int code); // print error message according code 21 22 // 注意 Java 不需要宣告, 因為在 class 內沒有先後關係 23 24 int main( ) { 25 //static char id[99]; // 夠'長吧 :-) 身分證才 10 碼啦 26 String id; 27 int code = 0; // 用來記住錯誤代碼 28 while(38 == 38) { // for( ;; ) { 29 printf("請輸入身分證號碼 Input ID: "); 30 //fgets(id, sizeof(id), stdin); // 整列讀入 到 id 31 id = fgets( ); 32 // check EOF 33 //if(feof(stdin)) break; //EOF == ^D in Unix; ^Z on DOS/Window 34 if(id== null) break; // EOF 35 //squeeze(id); // 把所有空白都去掉 white space 36 id = id.replace(" ", ""); 37 if(id.equals("") ) break; // empty string 38 // 注意先 check ==null, 再 replace(), 再 check .equald("") ... 39 //printf("strlen(id)=%d\n", strlen(id)); 40 //if(strcmp(id, "-1") == 0) break; //Java 用 id.equals("-1") 41 if(id.equals("-1")) break; 42 //if(strcmp(id, ".") == 0) break; 43 if(id.equals(".")) break; 44 //if(strcmp(id, "quit") == 0) break; 45 if(id.equals("quit")) break; 46 //if(id[1] == 'U') break; // QUIT ? // Java 用 id.charAt(1)== 47 if(id.length()>1 ) if(id.charAt(1) == 'U') break; 48 //if(strcmp(id, "999") == 0) {generateID( ); continue; } 49 if(id.equals("999")) {generateID( ); continue; } 50 code = testID(id); // 取得錯誤代號, 0 表示無錯 :-) 51 printf(" ID %s is ", id); 52 if(code==0) printf(" OK.\n"); // 印出說這號碼正確 53 else { 54 printf(" Error ID! Reason(s):\n"); 55 }//if 56 printError(code); // 依據 code 印訊息 57 }// while( 58 printf("\r\nThank you and bye bye!\n"); 59 return 0; 60 }//main( 61 62 63 // 關於 int testID(char* id) : 依據身分證規則查看 id 傳回錯誤代碼 64 int yy[ ]={ 10,11,12,13,14,15,16,17, 34, //ABCDEFGH I 65 18,19,20,21,22, 35, //JKLMN O 66 23,24,25,26,27,28, //PQRSTU 67 29,32,30,31, 33 }; //VWXY Z 68 int checkSum(String id){ // 幫忙算 checkSum 給 testID(id) 用 69 int sum, i; // 因編碼沒完全照字母順序, 用算的要很多 if(... 70 int ynum; 71 // 用查表法 table look up 查出字母對應的兩位數較簡單直覺 ! 72 // 先建個表 int yy[ ] = { 10, 11, 12, 13, ...}; // 照規定 AB.. 73 // 然後 Let i = id[0]字母減去 'A' 得到 0..25 74 // 再查出 yy[i] 拿來用: ynum = yy[i]; // 10..O是35..Z不是35 !! 75 i = Character.toUpperCase( id.charAt(0)) - 'A'; 76 ynum = yy[i]; 77 sum = ynum/10 + 9* (ynum%10); // weight 1, 9, [876543211] 78 for(i=1; i<=8; ++i) sum += (id.charAt(i) - '0') *(9-i); // 87654321 79 sum += (id.charAt(9) - '0') ; // *1 檢查碼 weight 也是 1 80 return sum; // 我只負責算出 checksum 81 }//checkSum( 82 83 int testID(String id) { //傳回錯誤代碼, 可用 bitwise "&" 運算找出 84 int i, ans = 0, sum=0; // sum 用來算 weighted check sum 85 //id[0] = toupper(id[0]); // 轉為大寫 86 char id0 = id.charAt(0); 87 if(!Character.isLetter(id0)) ans = ans + 1; // 1 號錯 ans = ans | 1; 88 if(id.length() > 1) 89 if(id.charAt(1) != '1' && id.charAt(1) != '2') ans += 2; // 2 號錯 男生女生? 90 if(id.length() < 10) ans += 4; // 太短 91 if(id.length() > 10) ans += 8; // 太長 92 for(i=1; i< id.length(); ++i) 93 if(!Character.isDigit(id.charAt(i)))ans = ans | 16; // 非數字 94 if((ans&16) != 0) return ans; // 有非數字不用再算 check sum 啦 95 if(ans != 0) return ans; // 有任何錯就..就不用再算 check sum 啦 96 sum = checkSum(id); // 假設沒有其他怪字就算出 check sum 97 if(sum%10 != 0) ans |= 32; // 必須除以 10 除得盡才對 98 return ans; 99 }// testID( 100 101 String what[ ]={ "對啦!!這是合法的身份證字號", //訊息0 102 "ㄟ..第一個字必須是字母啦!", // 訊息1 103 "你是第三性嗎?", // 訊息2 104 "太短了!不足碼唷!!", // 訊息3 105 "怎麼會有這麼多碼!!", // 訊息4 106 "打錯啦!!應該是數字喔!!", // 訊息5 107 "神秘數字算出來是錯的??" // 訊息6 108 }; // do NOT forget the ";" 109 // String what[ ] = { ... }; // in Java 110 void printError(int code) { // print all errors found use bitwise and 111 int i, yy[ ] = {0, 1, 2, 4, 8, 16, 32, 64, 128}; 112 if(code == 0) { printf("%s\n", what[0]); return; } 113 for(i=1; i <= 6; ++i)if((code&yy[i]) != 0)printf("%s\n", what[i]); 114 }// printError( 115 116 void generateID( ) { 117 //char id[11]={ 0 }; // 會全放 0 (NULL) == '\0' == 0 118 String id=""; 119 int i; 120 //id[0] = 'A' + rand( ) % 26; // 'A' .. 'Z' 121 id = "" + (char)('A' + rand( ) % 26 ); // 'A' .. 'Z' 122 //id[1] = '1' + rand( ) % 2; // '1' .. '2' 123 id += (char) ('1' + rand( ) % 2); // '1' .. '2' 124 for(i=2; i<=8; ++i) { 125 // 用亂數生出 id[2] .. id[8] 126 id += (char) ('0' + rand( )%10); // '0' .. '9' 127 } // 128 /// id[9] 是檢查碼, 要算, 可先塞 '0' 偷叫 checkSum( )再調整 129 //id[9] = '0'; 130 String id22 = id+"0"; // tmp id 131 i = checkSum(id22); // 借用 i 來存 checkSum 132 i = i % 10; 133 if(i != 0) id += (char)('0' + (10-i)); // 更正檢查碼 134 else id += "0";135 printf(" Good ID: %s\n", id); // legal ID now 136 }// generateID( 137 138 }//class
1 //c2java.java 2 import java.io.*; 3 import java.util.*; 4 //You can extends this class .. 5 // .. so that you can quickly translate your C into Java program 6 class c2java { 7 BufferedReader cin = null; 8 PrintStream cout = null; 9 PrintStream cerr = null; 10 c2java( ) { prepareIO( ); } // constructor 11 void prepareIO( ) { 12 try { 13 cin = new BufferedReader( 14 new InputStreamReader(System.in) ); 15 }catch(Exception e) {;} 16 cout = System.out; 17 cerr = System.err; 18 } 19 void printf(String fmt, Object... oo) { 20 System.out.printf(fmt, oo); 21 }//printf 22 void print(String fmt, Object... oo) { 23 System.out.printf(fmt, oo); 24 } 25 void println(String fmt, Object... oo) { 26 System.out.printf(fmt+"\n", oo); 27 }//println 28 int atol(String s) { // atoi, atol 29 int ans = 0; 30 try { 31 ans = Integer.parseInt(s); 32 }catch(Exception e) { ; } 33 return ans; 34 }//atol 35 double atof(String s) { 36 double ans = 0; 37 try { 38 ans = Double.parseDouble(s); 39 }catch(Exception e) { ; } 40 return ans; 41 }//atof 42 int rand( ) { 43 return (int) ( Math.random() * (1.0 + Integer.MAX_VALUE) ); 44 }//rand 45 void srand(int x) { 46 return; 47 } 48 String fgets( ) { 49 String buf=null; 50 try{ 51 buf = cin.readLine( ); 52 }catch(Exception e){;} 53 return buf; 54 }//fgets 55 }//calss c2java