Here is the reference solution for Problem Set 2, vigenere.c // Encrypt a message using the Vigenère cypher, with a user-provided key. // This is CS50x pset2 vigenere.c // // Author: david@newtongwc.org // // Usage: vigenere <secret> // // "secret" must be a non-empty, purely alphabetic string. // // Reads the (new-line-terminated) clear-text message from stdin, writes the // crypt-text message to stdout. #include <stdio.h> #include <ctype.h> #include <string.h> #include <cs50.h> #define true 1 #define false 0 string kSecretError = "the Vigenère secret must be a non-empty," " alpha-numeric string"; int ArgsAreValid(int argc, string argv[]) { if (argc != 2) { printf("Error: You must supply exactly 1 argument to %s\n", argv[0]); return false; } string secret = argv[1]; if (strlen(secret) < 1) { printf("Error: %s", kSecretError); } for (int i = 0; i < strlen(secret); i++) { if (!isalpha(secret[i])) { printf("Error: %s", kSecretError); return false; } } return true; } bool ShouldAlter(char clear) { return isalpha(clear); } // Encrypt a single character by shifting it some number of places // up the alphabet, wrapping around from 'z' to 'a'. Works for both upper- and // lower-case letters, staying within the same case. Leaves non-alphabetic // characters unchanged. char EncryptChar(char clear, int shift) { char crypt = 0; if (isupper(clear)) { crypt = (clear - 'A' + shift) % 26 + 'A'; } else if (islower(clear)) { crypt = (clear - 'a' + shift) % 26 + 'a'; } else { crypt = clear; } return crypt; } // Determines the shift that corresponds to a particular character under // the Vigenère scheme. Treat both A and a as 0, B and b as 1, … , and Z and // z as 25. int ComputeVigenereShift(char c) { return (tolower(c) - 'a'); } // Encrypts a full message, one character at a time, using the provided // encryption secret. string Encrypt(string clear_text, string secret) { string crypt_text = malloc(strlen(clear_text) * sizeof(char)); int message_length = strlen(clear_text); int secret_length = strlen(secret); int secret_pos = 0; for (int i = 0; i < message_length; ++i) { if (ShouldAlter(clear_text[i])) { int shift = ComputeVigenereShift(secret[secret_pos]); crypt_text[i] = EncryptChar(clear_text[i], shift); secret_pos = (secret_pos + 1) % secret_length; } else { crypt_text[i] = clear_text[i]; } } return crypt_text; } int main(int argc, string argv[]) { if (!ArgsAreValid(argc, argv)) { return 1; } string secret = argv[1]; string clear_text = GetString(); string crypt_text = Encrypt(clear_text, secret); printf("%s\n", crypt_text); free(clear_text); free(crypt_text); return 0; } |