B1 Viết chương trình thực hiện công việc sau: đoán nhận một xâu có theo đúng định d ạng "BK D" hay không? Nếu xâu không đúng định dạng thì ta có các thông báo sau: + nếu trong xâu không có chữ BK đứng riêng (viết thường hoặc hoa) thì in ra câu "Not available service". Chẳng hạn: "Toi viet BBK D" hoặc "BKK D" (sai) hoặc "toi viet 4BK D" (sai) + Nếu trong câu có BK đứng riêng nhưng NGAY sau BK không có D đứng riêng biệt với chữ cái nào thì in ra câu "Unknown". Chẳng hạn: "Toi viet BK DA". + Nếu trong câu có BK đứng riêng, ngay sau BK là D. Và nếu có kí tự đi ngay sau D thì ch ỉ ch ấp nhận mọi ký tự không phải chữ cái. Khi thỏa mãn điều kiện trên thì in ra "OK". Ví dụ các xâu sau là hợp lệ: "BK D", "Bk d dsdssd", "toi viet bK D", "19023783434 BK D!!!!45634uuusdf" b) Làm tương tự với "KQ XS" Chú ý: không nên dùng regular expression trong bài toán này, không nên ch ỉ dùng if...else mà phải kết hợp khéo léo với kế thừa và ghi đè (override) Để làm trọn vẹn các trường hợp, chúng ta phải sử dụng một lý thuyết về Automat hữu hạn đơn định rời rạc Một Automat dùng để đoán nhận nội dung của một xâu thì Automat đó phải có: - Xâu đầu vào - Tập các trạng thái khi đoán nhận xâu. Trong đó có trạng thái bắt đầu là trạng thái đọc được phần tử đầu tiên trong xâu - Trong các trạng thái có xác định điều kiện để chuyển trạng thái, duyệt một chữ cái trong xâu ứng với việc kiểm tra điều kiện chuyển trạng thái. - Trạng thái kết thúc là trạng thái được đặc trưng đoán nhận thành công xâu - tức xâu tuân th ủ theo đúng định dạng. Nếu sau khi đoán nhận xâu mà trạng thái hiện t ại là trạng thái k ết thúc => xâu đúng định dạng. Automat được sử dụng rất nhiều trong việc xây dựng trình biên dịch. Nhưng các h ệ th ống khác đều có sử dụng automat trong việc xây dựng mô hình chuyển trạng thái của nó. Chẳng hạn nh ư Unity Automat khi được vẽ ra hình thì được đặc trưng bằng một đồ thị có các nút và các cung. Trạng thái 0: trạng thái bắt đầu đoán nhận xâu. Trạng thái 1: trạng thái nhận được ký tự "B" đầu tiên, trước B không có chữ cái hoặc con số nào cả Vậy 0 -> 1: nếu B là ký tự đầu tiên trong xâu. Trạng thái 2: Nếu ký tự đầu tiên không phải là "B" và không phải là kho ảng trắng. 0 -> 2: nếu ký tự đầu tiên trong xâu không phải là "B" và khoảng trắng (space) 0 -> 0: nếu ký tự đọc được là khoảng trắng 2 -> 2: nếu ký tự đọc được tiếp theo không phải là khoảng trắng 2 -> 0: nếu ký tự đọc được tiếp theo là khoảng trắng Vậy bản chất trạng thái 0 là trạng thái chờ "B" còn trạng thái 2 là trạng thái chờ space Trạng thái 3: trạng thái đã nhận được "K" 1->3 : nếu ký tự đọc được là "K" 1-> 2: nếu ký tự đọc được khác "K" và khác space 1->0: nếu ký tự đọc được là space Trạng thái 4: trạng thái đã nhận được space, sau khi đã đoán nhận được "BK". 3->4: nếu ký tự tiếp theo là space 3->2: nếu ký tự tiếp theo khác space
4->4: nếu ký tự tiếp theo là space Trạng thái 5: trạng thái đã nhận được "D", sau khi đoán nhận được xâu "BK " 4->5 nếu ký tự tiếp theo là "D". Và 4->2 nếu ký tự tiếp theo khác D và khác space Trạng thái 5 là trạng thái kết thúc, nếu sau khi đoán nhận xâu, trạng thái cu ối cùng là tr ạng thái 5 thì ta nói xâu có chứa "BK D" Trạng thái 6: là trạng thái đoán nhận được sau "BK D" có chứa ký tự không phải là ch ữ cái 5 -> 6 nếu ký tự tiếp theo không phải là chữ cái (chữ cái là từ A đến Z) Từ 5->2 nếu ký tự tiếp theo là chữ cái. 6->6 với mọi ký tự tiếp theo. Ví dụ đoán nhận xâu: "BK D" => trạng thái cuối là trạng thái 5. Mà 5 là trạng thái kết thúc => xâu có chứa "BK D" "Toi viet BBK D" => duyệt hết xâu, trạng thái cuối là trạng thái 2 => xâu không ch ứa "BK D" hoặc "BKK D" "Toi viet BK DA" => ? trạng thái nào? "toi viet 4BK D" => trạng thái nào? Code C#: namespace Automat002 { class Program { static void Main(string[] args) { string s = "Toi viet Bkkkk"; s = s.ToUpper(); string trace = ""; State0 state = new State0(); for (int j = 0; j < s.Length; j++) { int x = state.getNextState(s[j]); if (trace.Length == 0) trace = "" + x; else { if (!("" + x).Contains (trace[trace.Length - 1])) { trace = trace + x; } } state = Factory.getState(x); } state.show(trace); Console.WriteLine(); } } class State0 {
public virtual int getNextState(char c) { if (c == ' ') return 0; if (c == 'B') return 1; return 2; } public virtual void show(string x) { Console.Write("Not available Service"); } } class State1 : State0 { public override int getNextState(char c) { if (c == 'K') return 3; if (c == ' ') return 0; return 2; } } class State2 : State0 { public override int getNextState(char c) { if (c == ' ') return 0; return 2; } public override void show(string x) { for (int j = x.Length - 1; j >= 0; j--) { if (x[j] == '4' || x[j] == '5') { Console.Write("Unknown"); return; } } Console.Write("Not available service"); } } class State3 : State0 { public override int getNextState(char c) { if (c == ' ') return 4; return 2; }
public override void show(string x) { Console.Write("Unknown"); } } class State4 : State3 { public override int getNextState(char c) { if (c == ' ') return 4; if (c == 'D') return 5; return 2; } } class State5 : State4 { public override int getNextState(char c) { if (c <= 'Z' && c >= 'A') return 2; return 6; } public override void show(string x) { Console.Write("OK"); } } class State6 : State5 { public override int getNextState(char c) { return 6; } } class Factory { public static State0 getState(int x) { switch (x) { case 1: return new State1(); case 2: return new State2(); case 3: return new State3(); case 4: return new State4(); case 5: return new State5(); case 6: return new State6(); } return new State0();
} } }
B2 BĂ i automat <TG $-Y> class Program { static void Main(string[] args) { do { Console.Clear(); Console.WriteLine("Nhap xau cua ban: "); string xau = Console.ReadLine(); string s = xau; s = s.ToUpper(); string trace = ""; State0 state = new State0(); for (int j = 0; j < s.Length; j++) { int x = state.getNextState(s[j]); if (trace.Length == 0) trace = "" + x; else { if (!("" + x).Contains(trace[trace.Length - 1]))
{ trace = trace + x; } } state = Factory.getState(x); } state.show(trace); Console.WriteLine("Conrinues? (y/n)"); } while (Console.ReadLine().ToString().ToUpper()=="Y"); } } class State0 { public virtual int getNextState(char c) { if (c == ' ') return 0; if (c == 'T') return 1; return 8; } public virtual void show(string s) { Console.WriteLine("Not Available"); } } class State1: State0 { public override int getNextState(char c) { if (c == 'G') return 2; if (c == ' ') return 0; return 8; } } class State2 : State0 { public override int getNextState(char c) { if (c == ' ') return 3; return 8; } public override void show(string s) { Console.WriteLine("Unknow"); } } class State3 : State2 {
public override int getNextState(char c) { if (c == '$') return 4; if (c == ' ') return 3; return 8; } } class State4 : State3 { public override int getNextState(char c) { if (c == '-') return 5; if (c == ' ') return 4; return 8; } } class State5 : State4 { public override int getNextState(char c) { if (c == 'Y') return 6; if (c == ' ') return 5; return 8; } } class State6 : State5 { public override int getNextState(char c) { if (c>='A'&&c<='Z') return 8; return 6; } public override void show(string s) { Console.WriteLine("OK"); } } class State7 : State6 { public override int getNextState(char c) { return 7; } } class State8 : State0 { public override int getNextState(char c) {
if (c == ' ') return 0; return 8; } public override void show(string s) { for (int i = 0; i < s.Length; i++) { if (s[i] == '3' || s[i] == '4' || s[i] == '5') { Console.WriteLine("Unknow"); return; } } Console.WriteLine("Not Available"); } } class Factory { public static State0 getState(int x) { switch (x) { case 1: return new State1(); case 2: return new State2(); case 3: return new State3(); case 4: return new State4(); case 5: return new State5(); case 6: return new State6(); case 7: return new State7(); case 8: return new State8(); } return new State0(); } }
B3 Bài 1 đếm số thi giữa kì ngày 13/4 với X=32. cùng một số đáp án của STT khác. (th ấy đề ch ỗ điều kiện (4) còn dấu "=>" chẳng biết nó có ý ngh ĩa nào khác không n ữa, nhưng cho vào code nó ko chạy nên mình xóa luôn để cho đúng delegate ) Biểu tượng cảm xúc smile Với X là 32 ta có j chạy từ 32 -> 42, j+2 chạy từ 34->44 Với điều kiện (1) if (x % 5 <= 1) obj = new C(); Điều kiện (2) if (x * x % 7 >= 4) obj = new B(); Điều kiện (3) if (x % 3 == 2 && obj is C && obj != null) { (obj as C).event1 += (s, e) => { Console.Write("A"); }; } Điều kiện (4) if (x % 4 == 2 && obj is C && obj != null) { (obj as C).action= delegate() {Console.Write("B");}; } Ta kẻ được bảng trên. theo đề bài ta có: 1)khi gọi new A() sẽ in ra “B” 2) khi gọi new B() sẽ in ra “BC” vì B kế thừa A, và ptkd in thêm “C” 3) khi gọi new C() sẽ in ra “BC” vì C kế thừa B và ptkd ko in thêm gì Như vậy nhìn từ bảng ta có: -4lần gọi new C() => in ra 4 lần BC => 4B 4C -3 lần gọi new B() => in ra 3 lần BC =>3B 3C -5 lần gọi new A() => 5 lần in ra B =>5 B -Tổng : 12B, 7C Với câu lệnh main như sau : A obj = new A(); for (int j = X; j < X + 11; j++) { obj = F.getA(j + 2); obj.show();
} Gọi new A() 1 lần => in ra 1 B => Tổng 13B, 7C Từ obj đã xét ở bảng ta có: -5 lần gọi show của lớp A => in ra 5 lần ”C” -3 lần gọi show của lớp B=> in ra 3 lần “A” -3 lần gọi show của lớp C => in ra 3 lần “D” -Tổng: 3A,13B,12C,3D Với Điều Kiện (3) event ≠ null ở j=33 và j=39 => in ra 2 lần “A” (in lúc gọi obj.show()) Với điều kiện (4) không có action nào thỏa mãn điều kiện Vậy đáp án cuối cùng là 5A,13B,12C,3D
B4 public delegate void Show( ) ; class C { public event Show show; public C( ) { } public virtual void Notify( ) { if(show != null) show( ) ; ConW("D"); } } class D : C { public override void Notify( ) { base.Notify( ); ConW("C") ; } } public static C getC(int x) { C obj = new C( ); if(x % 3 == 2){ //Đk1 obj = new D( ) ; obj.show += delegate( ) { ConW("A") ; }; } if(x % 5 == 2){ //Đk2 obj = new C( ); obj.show += delegate( ) { ConW("B"); }; } if(x % 4 <= 1) obj = new D( ); //Đk 3 if(x % 6 >= 4) obj = new C( ); //Đk 4 return obj ?? new D( ); }//Nếu obj = null thì obj = new D( ) cho vòng lặp như sau: for(int j = X; j < X + 17; j++){ C obj = getC(j + 1) ; obj.Notify( ) ; } Hỏi CT sẽ in ra gì? Với X = 19 ================================================ Bài làm: Biến j chạy từ 19 đến 35 Tham số truyền vào cho getC là chạy từ 20 đến 36 ĐK(1) đúng với x bằng 20, 23, 26, 29, 32, 35
ĐK (2) đúng với x = 22, 27, 32 if(x % 4 <= 1) đúng với x = 20, 21, 24, 25, 28, 29, 32, 33, 36 if(x % 6 >= 4) đúng với x = 22, 23, 28, 29, 34, 35 Lập bảng (Xem ảnh) Các trường hợp obj = new D mà show của obj bằng null là: khi x bằng 20, 21, 24, 25, 32, 33, 36 Khi đó obj.Notify sẽ in ra "D" và "C" => A = B = 0 và C = D =7 Các trường hợp obj = new D mà show của obj KHÁC null là: x bằng 26 => obj.Notify sẽ in ra A, D, C => A = 1; B = 0; C = D = 8 Các trường hợp obj = new C mà show của obj bằng null là: khi x bằng 22, 23, 28, 29, 30, 31, 34, 35 => obj.Notify sẽ in ra D => A= 1, B = 0, C = 7, D = 16 Các trường hợp obj = new C mà show của obj KHÁC null là: khi x = 27, => obj.Notify sẽ in ra B, D => A = 1, B = 1, C = 8 và D = 17
B5 KẾ THỪA TRONG C# 1) Khai báo kế thừa: C# cho phép đơn kế thừa, dùng dấu : để thiết lập kế thừa: class A { } class B : A { } //Lớp B kế thừa lớp A 2) Ghi đè (override) phương thức: Một phương thức ở lớp cha nếu có từ khóa public ở trước sẽ được lớp con kế thừa nếu phương thức có từ khóa virtual thì lớp con sẽ ghi đè được nội dung phương thức class A { public virtual void show( ) { ConW("B") ; } } class B : A { public override void show( ) { ConW("A"); } }//Đã ghi đè Tại vì trong C# cho phép sử dụng từ khóa new class C : A { public new void show( ) { ConW("C") ; } } Nếu ta viết A x1 = new A( ); x1.show( ) ; //in ra "B" A x2 = new B( ); x2.show( ) ; //in ra "A", gọi show của B A x3 = new C( ) ; x3.show( ); //in ra "B", tức gọi show của A B x4 = new B( ) ; x4.show( ); //in ra "A", gọi show của B
C x5 = new C( ); x5.show( ) ; //in ra "C", gọi show của C Dùng từ khóa base để gọi pt của lớp cha class D { public D(int x) { ConW("A"); } public D( ) { ConW("B") ;} public virtual void show( ) { ConW("F"); } } class E : D{ public E( ) : base(6) { ConW("C"); } public E(float y) : base( ) { ConW("D"); } public override void show( ) { ConW("G"); base.show( ) ; } } thì E obj1 = new E( ); //sẽ in ra "A", "C" và E obj2 = new E(8f) ; //sẽ in ra "B", "D" Thì obj1.show( ); //in ra G, sau đó là F new D( ).show( ); // in ra "F" Đa hình: việc khai báo kiểu lớp của đối tượng là lớp cha, gọi đến phương thức của lớp cha nhưng việc thực hiện các phương thức lại được đảm nhiệm ở lớp con Lớp A có ptkd in ra "B", pt virtual void show của A sẽ in ra "C". Lớp B kế thừa lớp A, ptkd của B in ra "A". Pt show của B sẽ ghi đè sao cho in ra "B". Cho lớp F có pt static như sau: public static A getA(int x) { if(x % 3 == 1) return new A( ); return new B( ); } Cho vòng lặp for như sau: for(int j = X ; j < X + 7; j++) { A obj = new A( ); obj = F.getA(j+1); obj.show( ); } Hãy xác định chương trình trên in ra bao nhiêu A, B, C? X = 27 Khi X= 27, biến j chạy từ 27 đến 33 Trong mỗi vòng lặp, biến obj lại được khởi tạo new A => in ra "B" 7 lần Mỗi vòng lặp, hàm getA được gọi với tham số (j+1) tức nhận giá trị từ 28 đến 34 if(x % 3 == 1) => đúng với (j+1) bằng 28, 31, 34 => 3 lần gọi new A( ) => 3 lần in ra "B" => B = B + 3 = 10 Còn lại 4 lần gọi new B( ), mà mỗi lần sẽ in ra "B", "A" => A = 4; B = B + 4 = 14 Mặc khác 3 lần gọi đến show của A => 3 lần in ra C => A = 4; B =14; C = 3 Còn 4 lần gọi đến show của B => 4 lần in ra "B" => A = 4; B = 18; C = 3 Lớp A có ptkd in ra "D", pt virtual void show của A sẽ in ra "A". Lớp B kế thừa lớp A, ptkd của B in ra "C". Pt show của B sẽ ghi đè sao cho in ra "B". Lớp C kế thừa B. ptkd không in ra gì. Pt show của C sẽ được ghi đè sao cho in ra "C" Cho lớp F có pt static như sau: public static A getA(int x) { if(x % 5 == 1) return new A( );
if(x % 3 == 1) return new B( ); return new C( ); } Cho vòng lặp for như sau: A obj = new A( ); for(int j = X ; j < X + 17; j++){ obj = F.getA(j); obj.show( ); } Hãy xác định chương trình trên in ra bao nhiêu A, B, C, D? X = 45 Biến j chạy từ 45 đến 61 A obj = new A( ) => in ra "D" (x % 5 == 1) => có 46, 51, 56, 61 => 4 lần gọi show của A => 4A và 4D (x % 3 == 1) => có 49, 52, 55, 58, => 4 lần new B và 4 lần gọi show c ủa B => 4C và 4B và 8D Còn lại 17 - (4 +4) = 9 lần new C và gọi show của C => ptkd 9 lần in ra D, C và show sẽ 9 lần in ra C => A = 4; B = 4; C = C + 9*2 = 22;