請注意: 做好習題請到 e3.nctu.edu.tw 本題討論版依照規定 post,
   且 Subject: LAB07 from 學號姓名
   信件內容是心得, 還有別忘了交待你在系上網頁的完整 URL (網址)!!!
   其他包括Running Script 與帶Line numbers程式碼當夾檔副件

LAB07 練習用網頁(HTML) + JavaScript 寫出身分證驗證程式
     注意 JavaScript 不是 Java, 這版本整個就只有一個 HTML 檔! 

Due: 2011/04/17 Sunday 23:59 
   (先看看我寫的電腦猜人想的公牛母牛JavaScript版再開始寫!)
  (提醒大家快要期中考了喔!)
Purpose: 
  了解 JavaScript 這種所謂Script Language(腳本語言)在網頁內的好用:-)
  在 JavaScript 與網頁間透過 Object(物件) 溝通!!
Description:
    (1)首先當然要有個簡單的網頁: 
           假設你在系上 Unix 工作站的帳號是 ggyy
        (a) 請找學長或課程助教或是三樓值班助教教你簡單 Unix 用法,
            花五分鐘左右學一點點基本的就可, 其實都不會 Unix 也沒關係 :-)
        (b) 登入本系 cs 子網任一工作站 (例如 linux2.cs.nctu.edu.tw 或
            bsd3.cs.nctu.edu.tw 等機器)
        (c) 登入後造一個子目錄 public_html
            然後在該子目錄內建立一個文字檔案 index.html
            那就是你在系上的網頁囉:
        用 Browser (IE, Firefox 等)打 http://www.cs.nctu.edu.tw/~ggyy
         注意此處 ggyy 是你在系上 Unix 工作站的帳號; 不要真的打 ggyy 
         搞不清你帳號密碼請拿你學生證到三樓值班櫃檯問!
         若你沒有資工系帳號請到三樓值班櫃檯問如何申請!!  
    (2)都不登入工作站仍可以完成上述工作, 有很多工具可以幫忙完成這工作
       在這 http://www.cs.nctu.edu.tw/~tsaiwn/introcs/TOOLS/
       可以抓  sftp.exe  這工具回你 Winodws, 
      用滑鼠點兩下執行後, 連入系上任一 Linux 或 BSD 機器,
      然後從你的 Windows 就可以造子目錄以及把網頁檔案"上傳"到你在系上工作站的目錄!
    (3)從網頁(HTML文件)內可以叫用JavaScript寫的function, 
      JavaScript function則可透過"Object物件"屬性改變網頁上的資料!!
      JavaScript 通常放同一檔案內, 若太大也可以另外放檔案(.js檔), 
      再從 HTML文件中用src=指定 include 進來  
      所以本題就是要把你的身分證檢查程式改成一個含 Javascript的網頁,
      全部寫在 HTML檔, 或是把 Javascript 部份另外存一檔案也可以!隨你高興!
    * 關於 Java Script 只要看這我寫的電腦猜人之BullCows範例就差不多了:
 http://www.cs.nctu.edu.tw/~tsaiwn/oop/03_Labs/Lab07/sampleJavaScript/
    * 建議先練習把該子目錄裡面我寫的電腦猜人之 BullCows 的 JavaScript
      cowBull.htm  抓了丟到你的網頁目錄先測試看看! (捲到此頁後面有 Link)
      別忘了也要抓裡面的 hello.txt, 不然問候語部份不會隨時間變化!
      但是沒有抓 hello.txt 仍能正常運作,
      因為我在 cowBull.htm 內有用 try { ... } catch ... 方式
      去使用 hello.txt 內的 function; 這樣若沒有 hello.txt 也不會當掉!
  

   * 參考上學期與身分證有關的習題
     
     http://www.cs.nctu.edu.tw/~tsaiwn/introcs/story/idcheck.htm 
     或自行上網找身分證編碼資料, 了解如何判斷一個身分證號碼是合法的?
   * C++ 範例程式只會印出一種錯誤..  思考若要對一個輸入 ID 印出
     所有可能的錯誤要怎麼修改?  (想不出就看我給的C範例 idcheck.c)


(4)LAB07 練習用網頁(HTML) + JavaScript 寫出身分證驗證程式
   注意 JavaScript 不是 Java, 這版本整個就只有一個 HTML 檔
   多看一些網頁按檢視 ==> 原始碼 就可偷看到一些 JavaScript 
   此程式只要偷看幾個網頁就會, 不必看 JavaScript 的書, 這站看看就夠用: 
 http://residence.educities.edu.tw/brencar/JsTeach/JsTeach_grammar.html  
   或這裡有完整語法與教學:
        http://www.w3schools.com/jS/    
   再不然自己用 gogle.com 查看 JavaScript 教學  
  另外, sampleJavaScript 子目錄內我寫了一個從 cowBull.c 改的範例!
       ./sampleJavaScript/cowBull.htm 
 

(5)LAB08 網路版的身分證驗證程式(用Java寫簡易的網路程式)
    把 LAB04 的 Java application 改成網路版(用你寫版本來改),
     配合我給的 TCP Server 範例稍作修改, 搭配執行, 阿就變成網路版了!

(6)Extra credit: 
   練習用網頁(HTML) + CGI 程式 寫出身分證驗證程式,
   即輸入 ID 後送到 Server 端由 CGI 程式判斷身分證號碼是否合法
   再把結果用網頁送回 Browser. 
   注意所謂 CGI 程式是指會在 Server 端執行任何語言寫的程式 
   可用 google.com找 "FORM 與 CGI"
   * 你的 CGI 程式可以用 C 或 PERL 或其它你喜歡的語言
   * 也可用 PHP 或 其它類似如 ASP, JSP
   注意這項對 ID 檢查的工作是在 Server 端, 不是在 client 端的 Browser
參考: http://webdesign.about.com/od/cgi/ss/aa022299.htm
      http://www.ck.tp.edu.tw/~thyu/perl-cgi-faq/pcp_faq.html

     或自己用 gogle.com 找 FORM CGI 教學   
這是你們學長以前寫的 簡易 HTML 教學
(花十幾分鐘看看阿你網頁就很厲害了, 不然就用DreamWeaver 或 FrontPage)
You are the free hit counters -th visitors to this page.
idcheck.c (其他請看LAB04目錄)
     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(

抓這 LAB07 全部的壓縮檔 Lab07.jar (zip格式) (大約 1550 KBytes)

More hints to translate C programs into Java programs
電腦猜人想的公牛母牛 JavaScript 範例 (看完這範例JavaScript就很厲害了 )
JavaScript 參考(教學)網站
    JavaScript 語法檢查工具 javaScriptLint_Syntax_Checker
另一個 JavaScript 語法檢查工具 JSLint: http://www.jslint.com/lint.html
(註: 第一支在 Unix 上可幫忙分析 C 程式錯誤的程式叫做 lint)

又另一個 JavaScript 語法檢查工具 JavascriptLint: http://www.javascriptlint.com/

這是你們學長以前寫的 簡易 HTML 教學
(花十幾分鐘看看阿你網頁就很厲害了, 不然就用DreamWeaver 或 FrontPage)
            回到作業目錄             回到課程目錄

關於用 PERL 寫 CGI 的 FAQ(常問問題) ../Lab04/for_Extra_credit/      
You are the free hit counters visitors to this page.