C++ Code:
  1. #include <iostream>
  2. #include <conio.h>
  3.  
  4. using namespace std;
  5.  
  6. void pause()
  7. {
  8.     cout <<"\n\n";
  9.     system("pause");
  10.     cout <<"\n\n";
  11. }
  12.  
  13. /*  Hàm nhập ngày tháng năm sinh dạng d(d)/m(m)/yy(yy)
  14.     Với 3 tham số đầu vào là số nguyên (ngày, tháng năm)
  15.     Nếu tại 1 thời điểm mà nhập sai, thì không cho nhập tiếp.
  16.  
  17.     Ví dụ, chưa có ký tự nào mà nhập / thì trên màn hình ko hiện gì cả
  18.     không được nhập 2 dấu // gần nhau và bắt buộc có 2 / trong dãy
  19.     Nếu nhập 2 ký tự đầu là số vd 12. thì ký tự tiếp theo bắt buộc phải là dấu /. vì đâu có ngày 123 (3 chữ số)
  20.     Nếu ký tự đầu tiên là 4 trở lên thì ký tự thứ 2 chỉ được nhập / chứ k cho nhập số. vd 4/ chứ k thể nhập 41 vì làm gì có ngày 41
  21.     Nếu ký tự đầu là 3 thì ký tự thứ 2 lớn hơn thì ko có hiện tưởng gì trên màn hình hết (y như các phím bị vô hiệu hóa vậy)
  22.     Nếu chưa nhập xong, hoặc năm=0 hoặc nhập ngày 29/2 năm ko nhuận thì nhấn enter không có tác dụng
  23.    
  24.     Nếu chuỗi đang là 31/0 thì không cho nhập tiếp số 0 hoặc /  hoặc các số tháng ko phù hợp (->> 31/00 hay 31/0/ là sai cú pháp, còn 31/02 hay 31/04 thì sai vì tháng 2 và tháng 4 không có 30 ngày)
  25.    
  26.     Nói chung, phải bắt buộc người dùng nhập đúng cú pháp và đúng ngày tháng (vd đã nhập ngày 31 thì không thể nhập tháng 11)
  27.     Nếu người dùng cố tình nhập sai thì trên màn hình chẳng hiện gì hết, trạng thái vẫn y như cũ
  28.     ví dụ trên màn hình đang là "12/" nếu người dùng nhập / (để thành 12// ) thì không được gì hết
  29.     Khi đó trên màn hình vẫn là "12/"
  30.     Hoặc nếu trên màn hình đang là "31/" . Nếu người dùng nhập số 6 (để thành 31/6) thì cũng ko có hiện tượng gì, trên màn hình vẫn hiện "31/"
  31.  
  32.     Khi ngày tháng đã hợp lệ, nếu người dùng nhấn Ok thì
  33.     Hàm trả về 3 số nguyên ngày, tháng, năm
  34. */
  35.  
  36.  
  37.  
  38. bool namnhuan (int n)   // hàm kiểm tra năm nhuận
  39. {
  40.     if ((n%4==0) && ( (n%100!=0) || (n%400==0) ) ) return 1;
  41.     return 0;
  42. }
  43.  
  44. void indate (int &a, int &b, int &c)
  45. {
  46.     int n,xoec=0, index=0;  // index là chỉ số mảng s, xoec là biến đếm số ký tự / n là biến để lấy mã ascii
  47.     a=b=c=0;    // a = ngày, b= tháng, c= năm
  48.     char s[30]; // s lưu chuỗi ngày tháng đang nhập trong quá trình thực hiện
  49.     do
  50.     {
  51.         //cout <<"\n\n A= " <<a <<", b=" <<b <<" c=" <<c <<", xoec = " <<xoec <<", index=" <<index <<", s=" <<s <<"\n\n";
  52.         loop:;  // đặt mốc lặp lại, dùng cho goto
  53.         n=getch();  // lấy mã ascii
  54.         if (n>='/' && n<='9' &&index<10)        // nếu nằm trong các kí tự cho phép
  55.         {
  56.  
  57.             if (index==0)       // nếu là kí tự đầu tiên
  58.             {
  59.                 if (n=='/');    // kí tự đầu ko thể là dấu cách
  60.                 else            // ngược lại
  61.                 {
  62.                     cout <<char(n); // xuất ra
  63.                     a=n-48;         // lưu vào a
  64.                     s[index++]=char(n); // lưu vào s
  65.                 }
  66.             }
  67.  
  68.             else if (index==1)      // nếu là ký tự thứ 2
  69.             {
  70.                 if (s[index-1]>'3' && n!='/');          // nếu kí tự đầu lớn hơn 3 thì ko cho nhập số nữa, chỉ co nhập / (ví dụ không thể nhập thành ngày 40 or 41, mà phải 4/)
  71.                 else if (n>'1' && s[index-1]=='3'); // nếu ký tự đầu là 3 thì chỉ được nhập 0 và 1 (thành 30, 31, không thể nhập 32,33...)
  72.                 else                            // ngược lại
  73.                 {
  74.                     if ( (n=='/' || n=='0') && s[index-1]=='0');    // nếu ký tự đầu là 0 thì k thể nhập tiếp số 0 hoặc / (ví dụ 00/ hay 0/)
  75.                     else
  76.                     {
  77.                         if (n=='/') xoec++; // nếu là xoec thì tăng xoec 1 (5/ - 7/ - 2/)
  78.                         else a=10*a+n-48;   // là số thì đưa vào a       (23 -> a=23)
  79.                         cout <<char(n);     // xuất ra màn hình, dù là xoec hay số
  80.                         s[index++]=char(n); // đưa vào s dù là xoec hay số
  81.                     }
  82.                 }
  83.             }
  84.  
  85.             else if (index==2)  // nếu ký tự thứ 3
  86.             {
  87.                 if (xoec==0 && n!='/');     // nếu chưa có dấu xoec nào thì bắt buộc phải nhập xoec, vì ngày chỉ tối đa 2 ký tự (vd: 12 không thể nhập số tiếp thành 121 mà phải 12/)
  88.                 else if (xoec==1 && n=='/');    // nếu là xoec, nhưng đã có  (1/ thì không thể nhập / nữa)
  89.                 else
  90.                 {
  91.                     if (n=='/' && xoec==0) xoec++;  // nếu là / thì tăng xoec (10/ -> xoec=1)
  92.                     else b=n-48;                    // nếu là số thì tăng b. vd 3/1 ->> a=3, b=1
  93.                     cout <<char(n);                 // xuất ra
  94.                     s[index++]=char(n);             // đưa vào s
  95.                 }
  96.             }
  97.  
  98.             else if (index==3)  // nếu là ký tự thứ 4
  99.             {
  100.                 if (s[1]=='/' && s[2]>'1' && n!='/');           // nếu có dạng sau: 3/2 thì không cho nhập số nữa, chỉ cho nhập dấu / vì nếu ->> 3/21 thì làm gì có tháng 21
  101.                 else if (n=='/' && s[index-1]=='/');            // nếu có dạng 10/ thì không được nhập / nữa
  102.                 else if (s[1]=='/' && s[2]=='1' && n>='3');     // nếu có dạng 4/1 thì chỉ đươc nhập tiếp số 2 trở xuống vì nếu nhập 3 trở lên ->> 4/13 mà đâu có tháng 13
  103.                 else if (a==31 && (n=='2' || n=='4' || n=='6' || n=='9'));  // nếu dạng 31/ thì không được nhập 2,4,6,9 vì các tháng đó đâu có ngày 31 (31/2, 31/4)..
  104.                 else if (a==30 && n=='2');                      //  không được nhập ngày 30/2
  105.                 else if (xoec==1 && s[1]=='/' && s[index-1]=='0' && (n=='0' || n=='/'));    // nếu dạng 3/0 thì không cho nhập tiếp số 0 or / vd: (3/00 or 3/0/ là sai)
  106.                 else
  107.                 {
  108.                     cout <<char(n);
  109.                     if (n=='/') xoec++;
  110.                     else b=10*b+n-48;   // lưu vào b. vd 1/10 ->> b=10. hoặc 12/3 ->> b=3
  111.                     s[index++]=char(n);
  112.                 }
  113.             }
  114.  
  115.             else if (index==4)  // nếu là ký tự thứ 5
  116.             {
  117.                 if (xoec==1 && s[1]=='/' && n!='/');    // nếu dạng: 8/12 không cho nhập tiếp số, bắt phải nhập /
  118.                 else if (n=='/' && s[index-1]=='/');    // nếu dạng 3/6/ không cho nhập / nữa vì có / trước nó
  119.                 else if (s[2]=='/' && s[index-1]>'1' && n!='/');    // 11/2 không cho nhập thêm số thành 11/22 vì lố tháng. nhưng cho nhập / thành 11/2/
  120.                 else if (s[2]=='/' && s[index-1]=='1' && n>'2');    // 11/1 chỉ cho phép nhập thành 11/10 or 11/11 or 11/12
  121.                 else if (xoec==1 && s[2]=='/' && s[index-1]=='0' && (n=='0' || n=='/'));    // nếu 10/0 thì k cho nhập thêm 0 hoặc / để thành 10/00 hoặc 10/0/
  122.                 else if (a==31 && s[index-1]=='0' && (n=='2' || n=='4' || n=='6' || n=='9'));   // không được nhập các tháng có tối đa 30 ngày, ví dụ 31/0 thì ko thể nhập tiếp 2 or 4..
  123.                 else if (a==31 && s[index-1]=='1' && n=='1');   // nếu dạng 31/1 thì ko được nhập số 1. vì 31/11 ->> ko có ngày 31/11
  124.                 else if (a==30 && s[index-1]=='0' && n=='2');   // tương tự áp dụng cho tháng 2
  125.                 else
  126.                 {
  127.                     if (n=='/') xoec++;     // nếu 12/1/ thì xoec tăng
  128.                     else if (xoec<2) b=10*b+n-48; // 10/11 ->> lưu vào b, b thành 11.
  129.                     else c=n-48;    //  1/1/2 thì lưu 2 vào c ->> c==2
  130.                     cout <<char(n);
  131.                     s[index++]=char(n);
  132.                 }
  133.             }
  134.  
  135.  
  136.             else if (index==5)  // nếu là ký tự thứ 6
  137.             {
  138.                 if (xoec==1 && s[2]=='/' && n!='/');        // 11/11 không cho nhập số nữa, bắt nhập dấu /
  139.                 else if (n=='/' && s[index-1]=='/');        // 1/12/ không cho nhập / nữa bắt buộc nhập số
  140.                 else if (n=='/' && xoec==2);                // 3/6/2 không cho nhập / nữa
  141.                 else
  142.                 {
  143.                     if (n=='/') xoec++; //  11/11/ thì tăng xoec
  144.                     else c=10*c+n-48;   // nếu 1/12/3 thì c=3. hoặc nếu 1/2/34 thì c=34
  145.                     cout <<char(n);
  146.                     s[index++]=char(n);
  147.                 }
  148.             }
  149.  
  150.             else    // nếu ký tự thứ 7 trở lên. chắc chắn những ký tự này thuộc phần năm
  151.             {
  152.                 if (n=='/');    // cho nên không cho nhập / nữa
  153.                 else if (xoec==2 && (index-5!=1) && (index-5!=2) && s[index-5]=='/');   // nếu 1/1/1111 hoặc 11/1/1111 hoặc 1/11/1111 hoặc 11/11/1111 thì không cho nhập nữa vì năm đã có 4 ký tự.
  154.                 else                                                                    // khi đó tồn tại 2 / và / thứ 2 nằm cách index 5 ký tự
  155.                 {
  156.                     c=10*c+n-48;    // tăng c
  157.                     cout <<char(n);
  158.                     s[index++]=char(n);
  159.                 }
  160.             }
  161.         }
  162.         else if (n=='\b' && index>0)    // nếu là backspace
  163.         {
  164.             cout <<"\b \b";
  165.             if (s[index-1]=='/') xoec--;    // nếu là back ký tự / thì giảm xoec
  166.             if (xoec==2) c/=10; // khi xoec=2 thì index đang trong phạm vi của năm, nên giảm c
  167.             else if (xoec==1 && s[index-1]!='/') b/=10; // nếu xoec=1 mà ký tự back ko phải là / thì giảm b. vì nếu ký tự back là / mà giảm b là sai. vd: khi 12/12/ lúc này b=12 và xoec=2. nếu back 1 cái thì xoec còn 1, và b bị giảm còn 1 (nhưng thực chất b vẫn là 12)
  168.             else if (xoec==0 && s[index-1]!='/') a/=10; // giảm a, tương tự như b ở trên
  169.             s[--index]=0;   // xóa ký tự cuối trong s
  170.         }
  171.  
  172.         else if ( (n==13 && c==0)  ||  (n==13 && a==29 && b==2 && !namnhuan(c))  ) goto loop;   // nếu nhập 29/2 năm không nhuận hoặc chưa nhập đến năm thì k cho kết thúc
  173.  
  174.     }
  175.     while (n!=13);
  176.    
  177.    
  178. }
  179. void main ()
  180. {
  181.     cout <<"Ngay sinh: ";
  182.     int ngay, thang, nam;
  183.     indate (ngay,thang,nam);
  184.  
  185.     cout <<"\n\nBan vua nhap: " <<ngay <<"/" <<thang <<"/" <<nam;
  186.  
  187.     pause();
  188. }