JavaRush /Blog Java /Random-VI /Harvard CS50: Bài tập tuần 2 (Bài 5 và 6)
Masha
Mức độ

Harvard CS50: Bài tập tuần 2 (Bài 5 và 6)

Xuất bản trong nhóm
bài tập cs50 bài 5 và 6 Các bài giảng CS50 có tại đây: https://cdn.javarush.com/images/article/155cea79-acfd-4968-9361-ad585e939b82/origen.pngcs50.html . Tài liệu này bao gồm 3 nhiệm vụ, thông tin lý thuyết về chúng và hướng dẫn hành động.

Bàn thắng

• Đi sâu hơn vào các hàm và thư viện • Làm quen với mật mã, triển khai một số mật mã đơn giản

Tài liệu bổ sung

https://reference.cs50.net/ - giải thích các chức năng thư viện được sử dụng trong quá trình đào tạo. Bằng tiếng Anh. http://computer.howstuffworks.com/c.htm trang 11 – 14 và 39

Sự chuẩn bị

Đăng nhập vào cs50.io update50 để đảm bảo phiên bản không gian làm việc của bạn được cập nhật. Nếu bạn vô tình đóng cửa sổ terminal, hãy chuyển đến menu View và đảm bảo rằng có dấu kiểm bên cạnh mục Console (đánh dấu nếu không có). Harvard CS50: Bài tập tuần 2 (Bài 5 và 6) - 1 Bấm vào (+), bên trong vòng tròn xanh trên khung cửa sổ terminal, chọn New Terminal . Harvard CS50: Bài tập tuần 2 (Bài 5 và 6) - 2 Tạo một thư mục làm việc: mkdir ~/workspace/pset2 Lưu ý rằng có khoảng cách giữa mkdir~/workspace/pset2 . Tóm lại, ~ có nghĩa là thư mục gốc, ~/workspace là một thư mục có tên là không gian làm việc bên trong thư mục gốc, ~/workspace/pset2 là một thư mục có tên pset2 bên trong ~/workspace . Bây giờ hãy chạy: cd ~/workspace/pset2 để thay đổi thư mục mới. Dòng lệnh trông giống như thế này: username:~/workspace/pset2 $ Nếu có gì sai, hãy lặp lại các bước. Bạn cũng có thể gọi một lệnh history để xem một số lệnh cuối cùng theo thứ tự thời gian. Bạn cũng có thể đặt con trỏ lên dòng lệnh và nhấn mũi tên lên trên bàn phím để xem tất cả các lệnh theo thứ tự từ lệnh được nhập cuối cùng đến lệnh đầu tiên. Sử dụng nút xuống, bạn có thể quay lại. Nhân tiện, thay vì mỗi lần gõ cùng một lệnh, bạn có thể cuộn qua các lệnh bạn đã gõ và thực hiện lại chúng bằng cách nhấn Enter. Bạn có thể nhận thấy rằng David thực hiện chính xác điều này trong các bài giảng của mình. Nhiệm vụ của tuần thứ hai sẽ được lưu trong pset2 .

Nhiệm vụ 0. Khởi tạo

Chúng ta hãy xem xét kỹ hơn các dòng. Trong tệpinits.c , hãy viết chương trình yêu cầu tên người dùng (sử dụng hàm GetString, chúng tôi lấy tên dưới dạng chuỗi) và sau đó hiển thị các chữ cái đầu tiên của tên (hoặc tên) và họ bằng chữ hoa không có dấu cách, dấu chấm hoặc các ký tự khác, chỉ với nguồn cấp dữ liệu dòng ( \n ). Chúng tôi giả định rằng người dùng chỉ nhập các chữ cái (chữ thường hoặc chữ hoa hoặc cả hai) cộng với một khoảng trắng giữa các từ. Hãy xem xét những kẻ tên Joseph Gordon-Levitt, Conan O'Brien hoặc David J. Malan sẽ không sử dụng chương trình. Để kiểm tra hoạt động chính xác của chương trình, hãy gọi check50: Bạn có muốn chơi thử việc thực hiện chương trình do nhân viên CS50 chuẩn bị không? Nhập dòng: username:~/workspace/pset2 $ ./initials Zamyla Chan ZC username:~/workspace/pset2 $ ./initials robert thomas bowden RTBcheck50 2015.fall.pset2.initials initials.c~cs50/pset2/initials
mật mã
Mật mã học, môn khoa học về mã hóa và giải mã thông tin... Trên thực tế, tin nhắn được mã hóa đã tồn tại từ xa xưa và được quân đội sử dụng để truyền tải những tin nhắn bí mật. Chà, giờ đây mật khẩu của bạn trên Facebook và các mạng khác được lưu trữ ở dạng mã hóa.

Nhiệm vụ 1. Kính chào Caesar!

Thông tin lý thuyết
Chúng ta sẽ nghiên cứu một trong những mật mã đơn giản nhất - mật mã Caesar, được đặt theo tên của hoàng đế La Mã. Trong mật mã này, mỗi chữ cái của văn bản được thay thế bằng một chữ cái khác, đó là một số chữ cái cố định thấp hơn trong bảng chữ cái. Số lượng chữ cái cố định này được gọi là khóa . Vì vậy, khóa 1 biến chữ C Latinh thành chữ D và Z qua chu trình thành A. Nếu khóa là 3 thì chữ C sẽ chuyển thành F và Z thành C. Ví dụ: chúng ta sử dụng mật mã Caesar với phím 5 trên chữ mèo. c -> h a -> f t -> y Caesar (cat, 5) = hfy Key = 7, word = máy tính c->j o->v m->t p->w u->b t->a e->l r->y Caesar(computer,7) = jvtwbaly Harvard CS50: Bài tập tuần 2 (Bài 5 và 6) - 3 Mật mã Caesar rất đơn giản, nhưng than ôi, không đáng tin cậy (đây là những thứ được kết nối với nhau!): đối với bảng chữ cái tiếng Anh chỉ có 25 tùy chọn mã hóa, thật dễ dàng để xem qua tất cả các tùy chọn ngay cả khi không có máy tính. Tuy nhiên, mật mã Caesar thường được sử dụng như một bước trong các mật mã khác, chẳng hạn như mật mã Vigenère (xem thêm về điều đó trong đoạn tiếp theo). Hãy "toán học hóa" mật mã Caesar. Hãy biểu thị bản rõ bằng chữ p, pi là chữ cái trong văn bản p ở vị trí số i. Hãy gọi chữ cái khóa bí mật là k, c là bản mã và ci là chữ cái trong bản mã ở vị trí i. Sau đó, bạn có thể tính toán từng chữ cái của mật mã bằng công thức: ci = (pi + k) % 26 Làm quen với cách hình thức hóa này, nó cho phép bạn lập trình thuật toán và thể hiện ý nghĩa của mật mã một cách chính xác và chính xác. Nếu khóa k = 13 và văn bản gốc p là "Hãy nhớ uống Ovaltine của bạn!", thì đây là mật mã chúng ta nhận được: Or fher gb qevax lbhe Binygvar! Lưu ý rằng O (chữ cái đầu tiên trong bản mã) được dịch chuyển 13 vị trí so với chữ cái B (chữ cái đầu tiên trong bản mã). chữ cái đầu tiên trong văn bản gốc). Điều tương tự với chữ r (chữ cái thứ hai trong mã hóa) được dịch chuyển 13 chữ cái so với e (chữ cái thứ hai trong bản gốc). Chữ cái thứ ba trong mã hóa, f, được dịch chuyển 13 chữ cái từ s (chữ thứ ba trong bản gốc), ở đây chúng ta đi theo một vòng tròn từ z đến a. Mật mã Caesar có khóa 13 có tên đặc biệt ROT13 . Nó có tính đối xứng: áp dụng nó hai lần, chúng ta quay lại văn bản gốc. Tất nhiên là còn có ROT26, cái này nói chung là siêu an toàn, nhưng chỉ khi bạn không bày tỏ suy nghĩ rõ ràng thôi =).
Tình trạng
Viết vào tệp caesar.c một chương trình mã hóa văn bản bằng mật mã Caesar. Cung cấp một đối số dòng lệnh làm đầu vào cho chương trình: một số nguyên không âm. Để đơn giản, hãy gọi nó là k. Nếu người dùng thực thi chương trình mà không có đối số dòng lệnh hoặc có nhiều hơn một đối số, ứng dụng sẽ khiếu nại và trả về giá trị 1 (đây là cách biểu thị lỗi): return 1; Trong tất cả các trường hợp khác, chương trình sẽ nhắc người dùng nhập văn bản để mã hóa, sau đó hiển thị văn bản được mã hóa bằng khóa k (tức là dịch chuyển k vị trí sang phải trong suốt chu trình). Nếu văn bản chứa các ký tự nằm ngoài bảng chữ cái tiếng Anh thì chương trình sẽ không thay đổi chúng. Sau khi in bản mã, ứng dụng thoát ra, main trả về 0: return 0; Nếu main không trả về 0 một cách rõ ràng, nó sẽ tự động trả về (int thực sự là kiểu trả về của main, nhưng sẽ nói nhiều hơn vào lúc khác). Theo quy ước (các quy tắc về hình thức tốt trong lập trình), nếu bạn trả về 1 một cách rõ ràng để chỉ ra lỗi thì bạn cũng nên trả về 0 làm con trỏ để hoàn thành thành công chương trình. Mặc dù bảng chữ cái tiếng Anh chỉ có 26 chữ cái nhưng k có thể lớn hơn 26. Về cơ bản, khóa k = 27 sẽ cho kết quả tương tự như k = 1, tuy nhiên bạn cần cho phép người dùng nhập bất kỳ số không âm nào không vượt quá 2^31 – 26 (phải vừa với int). Chương trình cũng phải tính đến việc các chữ cái viết thường được mã hóa thành chữ thường và chữ cái viết hoa được mã hóa thành chữ hoa. Chúng ta bắt đầu từ đâu? Vì ứng dụng phải chấp nhận trực tiếp giá trị của k trong chuỗi đối số nên tiêu đề hàm chính của chúng ta trông như thế này: int main(int argc, string argv[]) Từ Chương 6, bạn đã biết rằng argv là một mảng các chuỗi. Mảng này có thể được coi như một dãy tủ đựng đồ trong phòng tập thể dục. Mỗi người trong số họ có một số ý nghĩa ẩn giấu. Trong trường hợp của chúng tôi, bên trong mỗi ô có một đối số như string Để mở tủ đầu tiên, chúng tôi sử dụng argv[0], thứ hai - argv[1], v.v. Nếu chúng ta có n khóa thì chúng ta cần dừng lại ở argv[n - 1], vì argv[n] không còn tồn tại (hoặc tồn tại nhưng thuộc về người khác, tốt nhất chúng ta không nên chạm vào nó). Vì vậy, bạn có thể truy cập đối số k như thế này: string k = argv[1]; Chúng tôi tin rằng thực sự có một cái gì đó ở đó! Hãy nhớ lại rằng argc là một biến int bằng số hàng trong argv. Điều này có nghĩa là tốt hơn hết bạn nên kiểm tra giá trị của argc trước khi thử mở ô, vì có thể nó không tồn tại. Lý tưởng nhất là argc = 2. Tại sao lại như vậy? Bên trong argv[0] thường là tên của chương trình. Nghĩa là, argc luôn ít nhất là 1. Nhưng chương trình của chúng ta cần người dùng cung cấp đối số dòng lệnh k, do đó, argc = 2. Đương nhiên, nếu người dùng nhập nhiều hơn một đối số trên dòng lệnh, argc cũng phát triển và có thể lớn hơn 2 Nếu người dùng nhập một số nguyên vào một chuỗi, điều này không có nghĩa là giá trị đã nhập sẽ tự động được lưu dưới dạng int. Chính xác hơn là KHÔNG. Nó sẽ là một chuỗi, ngay cả khi nó trông giống hệt một int! Vì vậy chúng ta cần phải tự chuyển đổi chuỗi thành int. May mắn thay, có một chức năng gọi là atoi được thiết kế cho mục đích này. Cú pháp của nó là: int k = atoi(argv[1]); Lưu ý rằng k có kiểu int, vì vậy bạn có thể thực hiện phép tính với nó. Với hàm này, bạn không phải lo lắng về việc người dùng nhập số nguyên hay, chẳng hạn như foo: trong trường hợp đó, atoi sẽ trả về 0. Hàm atoi được khai báo trong thư viện stdlib.h , vì vậy hãy chắc chắn # đưa nó vào đầu chương trình. Mã sẽ biên dịch mà không cần hàm này vì chúng tôi đã đưa hàm này vào thư viện cs50.h. Tuy nhiên, tốt hơn là nên tin tưởng vào các thư viện gốc. Vì vậy, bạn đã lưu k dưới dạng int. Bây giờ hãy yêu cầu nhập văn bản. Nếu bạn đã làm bài tập của tuần đầu tiên thì bạn đã quen với hàm GetString trong thư viện CS50. Cô ấy sẽ giúp chúng tôi. Sau khi bạn đã nhận được k và văn bản ban đầu, hãy bắt đầu mã hóa. Tóm lại, bạn có thể lặp qua tất cả các ký tự của một chuỗi và in chúng bằng vòng lặp sau: for (int i = 0, n = strlen(p); i < n; i++) { printf("%c", p[i]); } Nói cách khác, giống như argv là một mảng các chuỗi, chuỗi là một mảng các ký tự. Do đó, chúng ta có thể sử dụng dấu ngoặc vuông để truy cập các phần tử chuỗi riêng lẻ giống như cách lấy các chuỗi riêng lẻ trong argv. Tất nhiên, không có gì mật mã khi in từng ký tự. Hoặc, về mặt kỹ thuật, khi k = 0. Nhưng chúng ta phải giúp Caesar mã hóa văn bản của anh ấy! Xin chào, Caesar! Để sử dụng strlen, bạn cần thêm một thư viện khác . Vì chúng tôi đang tự động hóa một số thử nghiệm xác thực nên chương trình sẽ hoạt động chính xác như thế này: username:~/workspace/pset2 $ ./caesar 13 Be sure to drink your Ovaltine! Or fher gb qevax lbhe Binygvar! Ngoài atoi , bạn có thể tìm thấy các hàm thú vị khác trong thư viện ctype.hstdlib.h . Để làm điều này, hãy theo liên kết và lục lọi xung quanh đó một chút. Ví dụ, isdigit rõ ràng là một cái gì đó thú vị =). Khi đi từ Z đến A (hoặc từ z đến a), đừng quên toán tử modulo %bằng ngôn ngữ C. Ngoài ra, hãy nghiên cứu bảng , nó hiển thị các ký tự ASCII không chỉ cho các chữ cái. Để kiểm tra xem chương trình có hoạt động chính xác với check50 hay không , hãy làm như sau: check50 2015.fall.pset2.caesar caesar.c Và nếu bạn muốn chơi với mã do nhân viên CS50 tạo, hãy chạy lệnh: ~cs50/pset2/caesar Nhân tiện, uggc://jjj.lbhghor.pbz/jngpu ?i=bUt5FWLEUN0 .
Phân tích nhiệm vụ
  1. Lấy chìa khóa
  2. Nhận văn bản
  3. Mã hóa
  4. Hiển thị tin nhắn được mã hóa
1. Chúng ta tạo hàm main để người dùng nhập key trên dòng lệnh và kiểm tra key xem có đúng không. int main(int argc, string argv[]) argc: • int • số đối số được nhập trên dòng lệnh • nếu argc = 2 thì mọi thứ đều ổn. Nếu không, hãy in hướng dẫn và đóng chương trình. • Nếu argc = 2 chúng ta kiểm tra xem khóa có phải là số nguyên hay không • Argv là một mảng các chuỗi, một danh sách có các đối số được nhập vào. Mảng là cấu trúc dữ liệu chứa các dữ liệu khác nhau cùng loại trong các ô khác nhau. Harvard CS50: Bài tập tuần 2 (Bài 5 và 6) - 4 Ví dụ người dùng nhập chuỗi blastoff Team Rocket thì: Harvard CS50: Bài tập tuần 2 (Bài 5 và 6) - 5 Sử dụng hàm atoi(), chúng ta chuyển số kết quả thành số nguyên. Nếu không thể, hàm sẽ trả về 0. Harvard CS50: Bài tập tuần 2 (Bài 5 và 6) - 6 2. Nhắc người dùng nhập văn bản. Rất đơn giản: mọi thứ người dùng nhập vào đều là một chuỗi. 3. Mã hóa. Thuật toán rất đơn giản, nhưng làm thế nào bạn có thể giải thích cho máy tính những chữ cái nối tiếp nhau? Đã đến lúc ghi nhớ bảng ASCII! Harvard CS50: Bài tập tuần 2 (Bài 5 và 6) - 7 Tuy nhiên, có thể có nhiều chữ cái hơn trong một chuỗi... Trước khi chuyển sang thay đổi chuỗi, hãy tưởng tượng rằng bạn chỉ cần thay đổi một ký tự. Chúng tôi muốn thay đổi các chữ cái từ văn bản ban đầu chứ không phải các dấu hiệu hoặc số. Chúng ta nên làm gì? Đầu tiên chúng ta cần kiểm tra xem ký tự này có trong bảng chữ cái hay không. Điều này có thể được thực hiện bằng cách sử dụng hàm isalpha() . Nếu ký tự nằm trong bảng chữ cái, hàm này trả về true và false nếu không. Hai hàm hữu ích hơn - isupper()islow() trả về true nếu chữ cái lần lượt là chữ hoa hoặc chữ thường. Do đó: Isalpha(‘Z’) -> true Isalpha(‘;’) -> false Isupper(‘Z’) ->true Isupper(‘z’) -> false Islower(‘Z’) -> false Islower(‘z’)->true Nếu isalpha trả về true, chúng ta cần thay đổi ký tự này bằng phím. Hãy xem xét và phân tích chương trình của Zamili, trợ lý CS50 làm ví dụ. Bạn có thể thắc mắc tại sao 'A' lại là số nguyên khi nó rõ ràng là một chữ cái. Hóa ra các ký hiệu và số nguyên có thể hoán đổi cho nhau. Bằng cách đặt chữ A trong dấu ngoặc đơn, bạn có thể nhận được mã ASCII của nó ở dạng int. Hãy cẩn thận: bạn cần dấu ngoặc đơn; nếu không có chúng, trình biên dịch sẽ tìm một biến có tên A chứ không phải một ký hiệu. Sau đó, chúng ta thêm giá trị khóa vào mã ASCII của chữ cái và lưu trữ chúng trong một biến số nguyên. Ngay cả khi kết quả là int, câu lệnh printf vẫn sử dụng phần giữ chỗ %c cho các ký tự. Vì vậy chương trình in ra ký tự liên quan đến kết quả số nguyên. Trong trường hợp thứ hai, chúng tôi hiển thị số bằng cách sử dụng trình giữ chỗ %d. Bạn có thể nhập mã này vào cs50 IDE và chơi với nó. Hãy kiểm tra cách hoạt động của asciimath đối với các khóa khác nhau. Lấy giá trị 25, chúng ta sẽ thấy hình sau: Và bây giờ đặt khóa là 26: Chúng ta có [, và không có chữ A. Nó chỉ là ký tự ASCII tiếp theo sau Z. Vì vậy, chỉ cần thêm khóa sẽ không công việc. Chúng ta cần sử dụng công thức mật mã để quay về đầu bảng chữ cái ngay khi hết chữ cái. Hãy nhớ rằng, chúng tôi đã viết ở trên: /* * asciimath.c * by Zamyla Chan * * Calculates the addition of a char and an integer, * and displays both the resultant character and its * ASCII value. * * Usage: ./asciimath key [char] * */ #include #include #include int main(int argc, string argv[]) { if (argc != 2) { printf("print the key next time \n"); return 1; } // key is the second command line argument int key = atoi(argv[1]); //преобразование строки в int int letter = 'A'; printf("\nCalculating '%c' + %d...\n", letter, key); int result = (letter + key); printf("The ASCII value of %c is %d.\n\n", result, result); return 0; } int result = (letter + key);Harvard CS50: Bài tập tuần 2 (Bài 5 và 6) - 8Harvard CS50: Bài tập tuần 2 (Bài 5 và 6) - 9ci = (pi + k) % 26 Trong đó ci là chữ cái số i trong bản mã, pi là chữ cái số i trong bản rõ, k là khóa và %26 là phần dư của phép chia cho 26 (hoặc “modulo 26”). Hãy áp dụng công thức này cho chữ Y. Lấy k = 2. Tính ('Y' + 2) %26 Mã ASCII của chữ 'Y' = 89. Khi đó ('Y' + 2) %26 = (89 + 2 )% 26 = 91%26 = 13 Nhưng đây không phải là giá trị ASCII của chữ A mà chúng ta cần, mà là 65. Bây giờ, hãy đặt cho mỗi chữ cái trong bảng chữ cái một giá trị từ 0 đến 25 theo thứ tự. Trong trường hợp này, Y = 24. (24+2)%26 = 0 Chữ A có chỉ số như vậy. Do đó, công thức này đề cập đến chỉ mục theo thứ tự bảng chữ cái của các chữ cái chứ không phải giá trị ASCII của chúng. Để in một ký tự được mã hóa, bạn sẽ cần giá trị ASCII của nó. Và tìm ra cách chuyển đổi giữa giá trị ASCII và một số trong bảng chữ cái. Khi đã tìm ra công thức cho một ký tự, chúng ta cần áp dụng công thức đó cho từng chữ cái trong chuỗi được nhập từ bàn phím. Nhưng chỉ khi đây là những chữ cái! Và hãy nhớ, chữ in hoa và chữ nhỏ đòi hỏi những ý nghĩa khác nhau. Đây là lúc hàm isupper và islow phát huy tác dụng. Bạn có thể có hai công thức, một cho chữ in hoa, một cho chữ thường, các hàm sẽ giúp bạn chọn công thức nào để áp dụng. Làm cách nào để áp dụng công thức cho từng ký tự trong một chuỗi? Hãy nhớ rằng một chuỗi chỉ là một mảng các ký tự. Hàm strlen (độ dài chuỗi) sẽ giúp bạn xác định số lần lặp trong một vòng lặp .Harvard CS50: Bài tập tuần 2 (Bài 5 và 6) - 10

Nhiệm vụ 2. Parlez-vous français?

Lý thuyết
Mật mã Vigenère có phần an toàn hơn mật mã Caesar: nó sử dụng một từ làm khóa và rất khó bẻ khóa thủ công chỉ bằng cách sử dụng phân tích tần số hoặc dùng vũ lực. Mỗi chữ cái của khóa tạo ra một số và kết quả là chúng ta nhận được một số phím để dịch chuyển các chữ cái. Ví dụ: p = Meet me in the park at eleven am В качестве ключевого слова возьмем k = bacon Длина messages p = 25 В то время How длина k = 5 Поэтому его нужно повторять 5 раз. Harvard CS50: Bài tập tuần 2 (Bài 5 và 6) - 11 Nếu số chữ cái trong tin nhắn không chia hết cho khóa thì chúng ta chỉ sử dụng một phần của nó trong ứng dụng cuối cùng của khóa: Harvard CS50: Bài tập tuần 2 (Bài 5 và 6) - 12 Để tìm giá trị cho phần bù, chúng ta sử dụng vị trí của từng chữ cái trong khóa thịt xông khói của chúng ta trong bảng chữ cái (từ a đến z). Chúng tôi đếm từ đầu, giống như những lập trình viên thực thụ. Và mỗi chữ cái trong văn bản gốc được dịch chuyển bởi một số nhất định, như trong mật mã Caesar, nếu cần, sẽ quay lại đầu bảng chữ cái sau Z. Vậy M sẽ di chuyển 1, e thứ nhất không chuyển động và e thứ hai sẽ di chuyển 2 vị trí. Dưới đây bạn sẽ thấy tin nhắn gốc, chìa khóa được viết và kết quả ứng dụng của nó. Harvard CS50: Bài tập tuần 2 (Bài 5 và 6) - 13 Tất nhiên, mật mã Vigenère mạnh hơn nhưng nếu bạn biết độ dài của khóa thì rất dễ bị phá. Làm thế nào để xác định nó? Nếu văn bản gốc đủ dài để một số từ xuất hiện nhiều lần trong đó thì bạn sẽ thấy một số từ lặp lại: Bạn Harvard CS50: Bài tập tuần 2 (Bài 5 và 6) - 14 cũng có thể sử dụng vũ lực, nhưng có nhiều tùy chọn: 26^n – 1 trong đó n là độ dài của khóa không xác định . Nhưng thông thường điều này là rất nhiều. Đúng, đây không phải là vấn đề đối với máy tính. Và bây giờ là phép toán của mật mã: Giả sử p là một văn bản nào đó, k là từ khóa, kj là chữ cái thứ j của khóa, pi là chữ cái số i trong văn bản gốc, ci là số chữ cái i trong mã hóa . Sau đó: ci = (pi + kj) % 26
Bài tập
Điều kiện Viết chương trình vigenere.c mã hóa tin nhắn bằng mật mã Vigenere. Chúng tôi cung cấp một đối số dòng lệnh cho đầu vào của chương trình: từ khóa k, bao gồm các chữ cái trong bảng chữ cái tiếng Anh. Nếu ứng dụng được khởi chạy với nhiều hơn một đối số hoặc có một đối số không có trong bảng chữ cái, thì cần phải hiển thị thông tin lỗi và kết thúc chương trình. Nghĩa là, main sẽ trả về 1 - trong trường hợp này, các bài kiểm tra tự động của chúng tôi sẽ hiểu rằng mọi thứ ở đây đều ổn và điều kiện này sẽ được tính đến. Nếu mọi việc đều ổn, chương trình sẽ tiến hành yêu cầu một chuỗi văn bản p mà chúng ta mã hóa bằng khóa k thu được ở trên, in kết quả và hoàn thành chương trình, trả về giá trị 0. Làm rõ Cần phải đảm bảo rằng trong khóa k ký tự A và a được ký hiệu là 0, B và b là 1, ..., Z và z là 25. Chương trình chỉ phải áp dụng mật mã Vigenère cho các chữ cái của văn bản p. Các ký tự còn lại (số, dấu chấm câu, dấu cách) phải được xuất ra mà không thay đổi. Nếu thuật toán áp dụng ký tự thứ j k cho ký tự thứ i p không có trong bảng chữ cái, hãy áp dụng ký tự khóa thứ j đó cho ký tự chữ cái tiếp theo trong văn bản; bạn không thể bỏ nó và chuyển sang một ký tự khác trong k. Cuối cùng, chương trình phải bảo toàn kiểu chữ của từng chữ cái trong p .
Bạn không biết bắt đầu từ đâu?
Harvard CS50: Bài tập tuần 2 (Bài 5 và 6) - 15
Dưới đây là một số lời khuyên từ Zamilya, trợ lý khóa học CS50
May mắn thay, chương trình này rất giống với mật mã Caesar, chỉ có khóa là một chuỗi chứ không phải số nguyên. Nếu bạn đã thực hiện thành công mật mã tên của người cai trị La Mã, đó có thể là bước khởi đầu tuyệt vời cho nhiệm vụ thứ hai. Có thể bạn đã nhận ra rằng mật mã Vigenère với một chữ cái làm khóa cũng giống như mật mã Caesar. Thuật toán Vigenère sử dụng các bước tương tự như Caesar:
  1. Lấy chìa khóa
    • từ mã là đối số dòng lệnh thứ hai argv[1]
    • phải có trong bảng chữ cái: hàm isalpha
  2. Nhận văn bản
  3. Mã hóa
  4. In văn bản mật mã
Vì vậy, hãy kiểm tra đối số dòng lệnh thứ hai argv[1] để xem liệu nó có thuộc các ký tự chữ cái hay không. Chúng tôi thực hiện việc này bằng cách sử dụng isalpha vốn đã quen thuộc . Nếu khóa đúng, chúng tôi nhận được một chuỗi từ người dùng và bắt đầu mã hóa. Công thức mật mã Vigenère tương tự như công thức mật mã Caesar. Làm thế nào để bạn chuyển đổi một chữ cái sang độ lệch mật mã tương ứng? Hãy thử so sánh các giá trị bằng bảng ASCII. Harvard CS50: Bài tập tuần 2 (Bài 5 và 6) - 16 Rất có thể, bạn sẽ có thể tìm thấy mẫu giữa các chữ cái và chỉ mục theo thứ tự bảng chữ cái của chúng bằng cách sử dụng các chuỗi trong bảng. Bạn đã tìm ra cách trừ một chữ cái này khỏi chữ cái khác để có được kết quả mong muốn chưa? Độ lệch cho chữ hoa và chữ thường là như nhau nên bạn sẽ phải xác định hai công thức tương tự nhau để xác định độ lệch cho chữ thường và riêng cho chữ in hoa. Cũng nên nhớ rằng vòng lặp văn bản nên bỏ qua các ký tự không phải tiếng Anh. Và đừng quên bảo quản hộp thư. Nếu bạn nhìn vào công thức mật mã: ci = (pi + kj) % 26 bạn sẽ thấy hai biến chỉ số là i và j. Một cái lưu vị trí trong văn bản nguồn, cái còn lại trong khóa. Nếu văn bản của bạn dài hơn khóa, chỉ mục trên khóa sẽ đi từ cuối khóa trở lại đầu. Làm thế nào để làm nó? Sử dụng phép chia modulo! Kết quả của phép tính là phần dư của phép chia hai số. Lợi ích thực tế của hoạt động này trong lập trình đơn giản là rất lớn! Hãy tưởng tượng rằng một nhóm lớn người cần được chia thành ba nhóm nhỏ. Một cách để làm điều này là yêu cầu họ trả tiền cho lần thứ nhất, thứ hai, thứ ba. Harvard CS50: Bài tập tuần 2 (Bài 5 và 6) - 17 Tức là người thứ nhất thuộc nhóm thứ nhất, người thứ hai thuộc nhóm thứ hai, người thứ ba thuộc nhóm thứ ba, người thứ tư thuộc nhóm thứ nhất, v.v. Bạn có thể sử dụng phép chia modulo để thực hiện thao tác tương tự. Hãy đánh số ba nhóm giống nhau từ đầu. Đây là cách thực hiện: Harvard CS50: Bài tập tuần 2 (Bài 5 và 6) - 18 Nếu bạn lấy một chỉ số và chia nó theo modulo cho giá trị lớn nhất thì kết quả thu được sẽ không bao giờ lớn hơn hoặc bằng giá trị đó. Hãy thử nguyên tắc này để trả lại từ khóa về đầu! Chỉ thay vì sắp xếp theo nhóm, bạn cần chỉ mục của từ khóa để có thể viết đúng chữ cái để bù đắp mà không vượt quá độ dài khóa. Vì chúng tôi đang tự động hóa một số kiểm tra mã của bạn nên chương trình sẽ hoạt động như minh họa bên dưới: jharvard@appliance (~/Dropbox/pset2): ./vigenere bacon Meet me at the park at eleven am Negh zf av huf pcfx bt gzrwep oz Bạn có thể kiểm tra chương trình bằng cách nào khác ngoài việc tính toán văn bản mã hóa theo cách thủ công? Chúng tôi rất tử tế: vì điều này, chúng tôi đã viết chương trình lệch lạc . Nó lấy một và chỉ một đối số dòng lệnh (từ khóa) và công việc của nó là lấy văn bản mã hóa làm đầu vào và trả về văn bản gốc. Chạy nó: ~cs50/pset2/devigenere k Trong đó k là từ khóa. Nếu bạn muốn kiểm tra tính chính xác của chương trình bằng check50, hãy chạy: check50 2014.fall.pset2.vigenere vigenere.c Và nếu bạn muốn đánh giá việc triển khai vigenere của chúng tôi, hãy nhập: ~cs50/pset2/vigenere

Cách xác thực mã của bạn và nhận điểm

Chú ý! Nếu điều quan trọng là bạn chỉ kiểm tra tính chính xác của các tác vụ thì hãy sử dụng cs50check. Nếu bạn muốn đạt điểm trên nền tảng edx, hãy làm theo quy trình được mô tả bên dưới. Hãy nhớ rằng quy trình này sử dụng cùng một cs50check để kiểm tra các tác vụ. Điểm khác biệt duy nhất là nó ghi nhớ kết quả và tính tổng điểm.
  1. Đăng nhập vào CS50 IDE
  2. Gần góc trên cùng bên trái của CS50 IDE , nơi đặt trình duyệt tệp của nó (không phải trong cửa sổ terminal), nhấp chuột phải vào tệp firsts.c của bạn nằm trong thư mục pset2 và nhấp vào Tải xuống . Bạn sẽ thấy trình duyệt đã tải tên viết tắt.c.
  3. Lặp lại cho caesar.c .
  4. Lặp lại cho vigenere.c .
  5. Trong một cửa sổ hoặc tab riêng, đăng nhập vào CS50 Gửi
  6. Bấm vào biểu tượng Gửi ở góc trên bên trái màn hình. Harvard CS50: Bài tập tuần 2 (Bài 5 và 6) - 19
  7. Trong danh sách thư mục bên trái, click vào thư mục Issue Set 2 , sau đó click vào nút Upload New Submission . Nó ở bên phải. Harvard CS50: Bài tập tuần 2 (Bài 5 và 6) - 20
  8. Trên màn hình xuất hiện, nhấp vào nút Thêm tệp .... Một cửa sổ để chọn tập tin từ máy tính của bạn sẽ mở ra. Harvard CS50: Bài tập tuần 2 (Bài 5 và 6) - 21
  9. Điều hướng đến thư mục nơi bạn giữ tên viết tắt.c. Rất có thể nó nằm trong thư mục Tải xuống của bạn hoặc bất cứ nơi nào trình duyệt của bạn đặt tệp theo mặc định. Khi bạn tìm thấy tên viết tắt.c , hãy nhấp vào nó một lần để chọn, sau đó nhấp vào Mở.
  10. Bấm vào Thêm tập tin một lần nữa.
  11. Tìm caesar.c và mở nó.
  12. Thực hiện tương tự với file vigenere.c .
  13. Nhấp vào Bắt đầu tải lên. Các tập tin của bạn sẽ được tải lên máy chủ CS50 .
  14. Trên màn hình xuất hiện, bạn sẽ thấy cửa sổ No File Selected . Nếu bạn di chuyển con trỏ chuột sang trái, bạn sẽ thấy danh sách các tệp đã tải xuống. Để xác nhận, hãy nhấp vào từng cái. Nếu bạn không chắc chắn về điều gì đó, bạn có thể tải lại tệp lên bằng cách lặp lại các bước tương tự. Bạn có thể làm điều này bao nhiêu lần tùy thích cho đến hết năm 2016.
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION