Bài tập về vòng lặp cho người mới bắt đầu

Liên hệ QC
BÀI 01: MÃ HÓA 1 ĐOẠN VĂN BẢN​

ABCDEFTS4BIQTOI YEU GIAI PHAP EXCEL TU 2006
GHIJKLRA5CJV
MNOPQRU06DKW?
STUVWXO17ELX
YZ0123N28FMY
456789G39HPZ
NM
Ta có bảng N với 36 ký tự & ký số được sắp xếp theo 1 trật tự qui ước



& bảng M cũng những kí tự & ký số đó ta bố trí theo mật mã có chìa khóa là 'TRUONG SA'

Đề bài yêu cầu chúng ta mã hòa câu "TOI YEU GIAI PHAP EXCEL TU 2006"

Xin lưu ý: Đề bài chỉ dành ch những lập trình viên VBA trình độ sơ cấp
Rất mong nhận được nhiều ý kiến & lời giải

[Gọi ý lần 1] (Sau 3 giờ): 'YEU' => 'NI7'
 
Lần chỉnh sửa cuối:
Ở đây tôi đang giải thích về sự khác biệt giữa cách viết code có cấu trúc và không cấu trúc.
Khi trình dịch đọc đến từ khoá FOR thì nó biết đây là mở đầu một vòng lặp, và nó tự biết rằng đến từ khoá NEXT gần nhất thì khẳng định đó là kết vòng lặp ấy. Nếu trước khi gặp NEXT mà gặp một FOR khác thì nó tự biết là cái FOR trước phải bọc ngoài cái FOR này. Đó là có cấu trúc.
nói chung bác nói cũng đúng chứ không sai ^^ , với quan điểm của bác thì phân ra hai loại có cấu trúc và không cấu trúc để dễ phân biệt
nhưng cũng có quan điểm khác họ chỉ coi là các cách để lặp lại thôi, một cái gọi là không cấu trúc thì cũng phải theo 1 cấu trúc nào đó , lan man tí thì vòng lặp có cấu trúc tuy dễ hiểu nhưng bị trình biên dịch hạn chế năng lực , nên chỉ giải được 1 số dạng toán nhất định , nếu với các dạng toán vét cạn dùng đến đệ quy , thì có thể thiết kế bằng vòng lặp goto cũng tốt tương đương !
 
Upvote 0
... nếu với các dạng toán vét cạn dùng đến đệ quy , thì có thể thiết kế bằng vòng lặp goto cũng tốt tương đương !
Việc này là vấn đề khác. Nó là cách trải phẳng đệ quy phi tuyến chứ đâu có liên quan gì đến code khó bị đánh cắp. Ba cái mớ nhiều nhánh đương nhiên là khó hiểu, nếu không có chú thích thì khó mò. Chân lý là vậy.
Tôi đâu có tranh luận về "dùng hay không dùng Goto" ở đây.
Ở đây, tôi chỉ cảnh báo với quý vị cần học về vòng lặp, và tôi lặp lại rằng:
Goto là lệnh rẽ nhánh chỉ dùng khi đã tự định cho mình những luật lệ đi kèm. Không tuân thủ những luật tự kềm chế mình thì code sẽ nát bét hết.

Và ở những bài trước, tôi khuyên người học nên hỏi lại người viết code giải thích các luật lệ của mình. Không có những giải thích này thì code chỉ là loại code sao chép đem về dùng chứ chả học được gì cả. Trừ phi người học biết kỹ thuật tái cấu trúc code (refactor và reverse engineering).
 
Upvote 0
nhìn chung không phải chỉ có nghề code két này mới có việc keep job như thế , nhiều nghề khác cũng vậy thôi ,
giống như nhà em thuê thợ sửa cái máy lạnh , thợ đấu điện ngoằn ngoèo làm bác sau mệt bở hơi tai , ^^
nhưng ấy chỉ là tiểu xảo của nghề , và nếu cứ làm thế thì chỉ đạt tầm manh mún , không phát triển lên được !
nói chung em cũng đa tạ bác vì đã chia sẻ 1 tinh thần học tập và làm việc đúng đắn ^^
 
Upvote 0
Cái này như kiểu là lấy đủ tên đó rồi còn thừa ký tự nào thì bỏ sang bên canh.Mà có giải thưởng không bác Sa.

C++ góp vui tí
Mã:
#include <iostream>
#include <iostream>
#include <conio.h>
#include<cstring>
using namespace std;

const int Max = 100;
char BanRo[] = "TRUONGSA"; // Bang M
char* BanMa;
int nStr = strlen(BanRo);
int M[Max];


void ConverterNumberToChar(int kt);
void ConverterCharToNumber(char* Str);

int main()
{
   cout<<"Bang ro: "<<endl;
   cout<<BanRo<<endl;
   ConverterCharToNumber(BanRo);
   cout<<"\nBang ro dang so (Z26):"<<endl;
   for(int i = 0; i < nStr; i++)
      cout<<M[i]<<" ";
   cout<<endl;

   // Cac ham ma hoa va giai ma
   // dat o day.

   cout<<"\nChuoi ban dau la: "<<endl;
   for(i = 0; i < nStr; i++)
      ConverterNumberToChar(M[i]);
   cout<<endl;

   getch();
   return 0;
}
// Trong Z26 ta gan so cho ky tu nhu sau:
// A B C D E F G H I ... Z
// 0 1 2 3 4 5 6 7 8 ... 25
void ConverterNumberToChar(int kt)
{
   char digit[26] ={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
   int i;
   i = kt%26;
   kt = kt/26;
   if(i>=26)
      cout<<digit[i%10];
   else
      cout<<digit[i];
}
void ConverterCharToNumber(char* Str)
{  
   char* Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
   int StrStr = strlen(Str), StrAlphabet = strlen(Alphabet);
   for(int k = 0; k < StrStr; k++)
      for(int j = 0; j < StrAlphabet; j++)
      {
         if(BanRo[k] == Alphabet[j])
         {
            M[k] = j;break;
         }
      }
}
 
Upvote 0
Code lủng củng lắm. Thử chỉnh lại đi.
Điển hình 1:
char digit[26] ={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
làm như vầy hơi nguy hiểm vì digit bắt buộc phải là mảng, không thể coi như string vì nó không có \0 ở sau
char digit[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
sẽ được trình dịch cho thêm cái \0 ở cuối
Điển hình 2:
Hàm ConverterNumberToChar code quá sức cẩu thả
i = kt%26; ---> chắc chắn i < 26
kt = kt/26; ---> trị này tính xong chả làm gì cả
if(i>=26) ---> theo cách tính i ở trên thì chuyện này không bao giờ xảy ra
Code dùng nhiều lần "magic number" 26. Đáng lẽ phải đặt nó là const (C++), hoặc #define (C)

Gợi ý thêm:
1. C++ dùng nhiều từ khoá const hơn
2. Theo quan niệm mới bây giờ, người ta ít khi viết hàm void. Nếu hàm xử lý chuỗi thì trả về con trỏ chuỗi.
3. Code trên chỉ là C, thêm cái phần i/o của C++. Nếu thực sự là C++ thì viết quách một cái class chứa hết mọi phương thức vào mã, giải mã...
 
Lần chỉnh sửa cuối:
Upvote 0
Thay vì phải sử dụng ví dụ mã hóa chuỗi cho vòng lặp cơ bản ta có thể tham khảo một số code dưới đây:

Một số ví dụ về vòng lặp:
1. Lặp sử dụng Step:
PHP:
For I = 1 to 10 Step 2
   Debug.Print I
Next
2. Lặp sử dụng phương pháp thêm bớt giá trị:
PHP:
For I = 1 to 10 Step 1
   Debug.Print I
   I = I + 1
Next
For J = 10 to 1 Step -1
   Debug.Print J
   J = J - 1
Next
3. "Nhảy" trong Vòng Lặp lòng một Vòng Lặp sử dụng Goto:
PHP:
For I = 1 to 10
   For J = 1 to 10
      If J = 7 Then Goto LockCondition
   Next J
   If False Then
LockCondition:
     J = J + 3
   End If
Next I
4. "Nhảy" trong Vòng Lặp lòng một Vòng Lặp sử dụng Gosub:
PHP:
Sub Exam_00A()
For I = 1 to 10
   For J = 1 to 10
      If J = 7 Then Gosub LockCondition: Exit For
   Next J
Next I
Exit Sub
LockCondition:
   J = J + 3
Return
End Sub

5. Vòng lặp Biến I nằm trong Vòng lặp của Biến I:
PHP:
Sub Exam_00B()
  Dim I&
  For I = 1 To 100
    GoSub NewI
    Debug.Print I
  Next I
  Exit Sub
NewI:
  For I = I To I + 1
    If 100 Mod I = 2 Then Exit For
  Next I
Return
End Sub

Tất cả các phương thức Vòng lặp trong VBA:
PHP:
Sub basic_loop_For()
'For...Next()'
Dim I As Long
For I = 0 To 1

Next I
'For Each...Next()'
Dim Ia:
For Each Ia In Array(1, 2, 3)
  Exit For
Next Ia
'Do ... Loop  ----> Endless Loop - sTop by Exit Do'
Do
  DoEvents
  If True Then Exit Do
Loop
I = 1
Do While I < 5 '(Loop If True <> Exit If False)'
  I = I + 1
  Debug.Print "Do While", I
Loop
I = 1
Do
  I = I + 1
  Debug.Print "Loop While", I
Loop While I < 5 '(Loop If True <> Exit If False)'
I = 0
Do Until I > 5 '(Loop If False <> Exit If True)'
  I = I + 1
  Debug.Print "Do Until", I
Loop
I = 0
Do
  I = I + 1
  Debug.Print "Loop Until", I
Loop Until I > 5 '(Loop If False <> Exit If True)'
'While ... Wend  -----> sTop by Condition False'
I = 0
While I <= 10
  Debug.Print "While Wend", I
  I = I + 1
Wend
End Sub
Mã:
Do While Arr(i, 285) >= 96
                For j1 = 10 To 257 Step 8
                    If Arr(i, 285) < 96 Then
                        Exit For
                    ElseIf Arr(i, j1 + 2) > 1.5 Then
                        Arr(i, j1 + 2) = Arr(i, j1 + 2) - T1
                        Arr(i, 278) = Arr(i, 278) - 1
                        Arr(i, 285) = Arr(i, 285) - 1
                    End If
                Next j1
            Loop
Code này của em sai ở đâu mà không tài nào thoát được vòng lặp anh nhỉ?
 
Upvote 0
Mã:
Do While Arr(i, 285) >= 96
                For j1 = 10 To 257 Step 8
                    If Arr(i, 285) < 96 Then
                        Exit For
                    ElseIf Arr(i, j1 + 2) > 1.5 Then
                        Arr(i, j1 + 2) = Arr(i, j1 + 2) - T1
                        Arr(i, 278) = Arr(i, 278) - 1
                        Arr(i, 285) = Arr(i, 285) - 1
                    End If
                Next j1
            Loop
Code này của em sai ở đâu mà không tài nào thoát được vòng lặp anh nhỉ?
Không thoát được là đúng rồi vì Nó thỏa mãn điều kiện Arr(i,285) >=96.Mà ở đây giá trị của i luôn bằng giá trị khi thỏa mãn điều kiện nếu mình đoán không sai.Bạn phải làm cách nào cho biến i nó chạy chứ để thế kia nó luôn thỏa mãn điều kiện vòng lặp Do loop thì nó chẳng chạy hoài à.
 
Upvote 0
Không thoát được là đúng rồi vì Nó thỏa mãn điều kiện Arr(i,285) >=96.Mà ở đây giá trị của i luôn bằng giá trị khi thỏa mãn điều kiện nếu mình đoán không sai.Bạn phải làm cách nào cho biến i nó chạy chứ để thế kia nó luôn thỏa mãn điều kiện vòng lặp Do loop thì nó chẳng chạy hoài à.
Giá trị Arr(i, 285) có thay đổi ở dòng này:
Arr(i, 285) = Arr(i, 285) - 1
Tuy nhiên, vì dòng ấy nằm trong điều kiện:
ElseIf Arr(i, j1 + 2) > 1.5 Then
cho nên nếu Arr(i, j1 + 2) <= 1.5 trước khi Arr(i, 285) giảm xuống dưới 96 thì vòng lặp sẽ vô tận.
 
Upvote 0
Giá trị Arr(i, 285) có thay đổi ở dòng này:
Arr(i, 285) = Arr(i, 285) - 1
Tuy nhiên, vì dòng ấy nằm trong điều kiện:
ElseIf Arr(i, j1 + 2) > 1.5 Then
cho nên nếu Arr(i, j1 + 2) <= 1.5 trước khi Arr(i, 285) giảm xuống dưới 96 thì vòng lặp sẽ vô tận.
Cảm ơn hai anh để em xem lại nhé. Chúc mọi người an toàn trong mùa dịch!
 
Upvote 0
Web KT
Back
Top Bottom