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