我的代码似乎工作正常,除了应该打印最终输出的时候。问题是输入一个字符串并输出一个加密版本。加密的工作原理是添加一个定义为密钥的 int,然后将该值添加到输入字符串的 ascii 值的每个字符中。我的问题是,当输出密文时,只有空格,没有字母甚至数字。
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, string argv[]) {
int key = atoi(argv[1]);
printf("%i\n", key);
if (argc != 2) {
printf("Usage: ./ceasar key\n");
} else {
string text = get_string("Plaintext: ");
for (int i = 0, len = strlen(text); i < len; i++) {
int cipher = text[i];
int ciphertext = cipher + key;
int ciphermod = ciphertext % 26;
printf("%c", ciphermod);
}
printf("\n");
}
}
您遇到了一些问题。在向其他人寻求帮助之前,请务必仔细阅读作业。
作业要求您:
isalpha()
来了解这一点。ci = (pi + k) % 26
。
您的代码与此公式等效,但它不考虑换行、大写/小写字母等。项目规范不仅仅要求您重复该公式,它要求您使用它来解决问题。为此,您必须了解它。随后我会详细解释。就地修改文本。目前,您计算密文并打印它。如果您添加用于修改文本所在位置的代码,则可以更轻松地忽略非字母字符。
ci = (pi - 𝚨 + k) % 26 + 𝚨
% 26
可确保结果介于 1 到 26 之间(始终为字母)。最后,我们加回 𝚨,使角色再次拥有案例。
// ...
for (int i = 0, n = strlen(text); i < n; i++) {
if (!isalpha(text[i])) continue;
if (isupper(text[i])) {
// the letter's ASCII code on its own.
int charcode = text[i];
// the letter's index in the alphabet. A = 0, B = 1, etc.
// this is no longer a valid ASCII code.
int alphabet_index = charcode - 'A';
// the letter's index in the alphabet, shifted by the key.
// note, this may shift the letter past the end/beginning of the alphabet.
int shifted_alphabet_index = alphabet_index + key;
// the letter's index in the alphabet, shifted by the key, wrapped around.
// the modulo operator (%) returns the remainder of a division.
// in this instance, the result will always be between 0 and 25,
// meaning it will always be a valid index in the alphabet.
int shifted_index_within_alphabet = shifted_alphabet_index % 26;
// this is the final ASCII code of the letter, after it has been shifted.
// we achieve this by adding back the 'A' offset so that the letter is
// within the range of the correct case of letters.
int final_shifted_charcode = shifted_index_within_alphabet + 'A';
text[i] = final_shifted_charcode;
}
else { // islower
int charcode = text[i];
int alphabet_index = charcode - 'a';
int shifted_alphabet_index = alphabet_index + key;
int shifted_index_within_alphabet = shifted_alphabet_index % 26;
int final_shifted_charcode = shifted_index_within_alphabet + 'a';
text[i] = final_shifted_charcode;
}
}
printf("ciphertext: %s\n", text);
// ...
这是简化的解决方案:
// ...
for (int i = 0, n = strlen(text); i < n; i++) {
if (!isalpha(text[i])) // if not alphabetic, skip
continue; //
if (isupper(text[i])) // if uppercase
text[i] = (text[i] - 'A' + key) % 26 + 'A'; //
else // if lowercase
text[i] = (text[i] - 'a' + key) % 26 + 'a'; //
}
printf("ciphertext: %s\n", text);
// ...
顺便说一句,声明
if (!isalpha(text[i]))
的作用类似于所谓的
guard Clause。这是一个需要了解的有用概念。使用保护子句可以让您拥有更简单、更具可读性的代码。想象一下,如果我将所有代码都嵌套在
if (isalpha(text[i]))
条件下的 for 循环内。阅读和理解会比较困难,并且很难匹配不同的括号对。编辑:我也会回应chqrlie所说的。在确认 argv[n]
之前,请勿使用
argc >= (n + 1)
你应该只对字母进行编码
'a'
'A'
您应该将第一个字母 'a'
'A'
的代码添加到编码索引中。
argv[1]
。 这是修改后的版本:
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, string argv[]) {
if (argc != 2) {
printf("Usage: ./ceasar key\n");
} else {
int key = atoi(argv[1]);
printf("%i\n", key);
string text = get_string("Plaintext: ");
for (int i = 0, len = strlen(text); i < len; i++) {
int c = text[i];
if (c >= 'a' && c <= 'z') {
int cipher = c - 'a';
int ciphertext = cipher + key;
int ciphermod = ciphertext % 26;
c = 'a' + ciphermod;
} else
if (c >= 'A' && c <= 'Z') {
int cipher = c - 'A';
int ciphertext = cipher + key;
int ciphermod = ciphertext % 26;
c = 'A' + ciphermod;
}
printf("%c", c);
}
printf("\n");
}
return 0;
}