CS50 第 2 周凯撒练习

问题描述 投票:0回答:2

我的代码似乎工作正常,除了应该打印最终输出的时候。问题是输入一个字符串并输出一个加密版本。加密的工作原理是添加一个定义为密钥的 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");
    }
}
c string integer cs50
2个回答
0
投票

您遇到了一些问题。在向其他人寻求帮助之前,请务必仔细阅读作业。

作业要求您:

  • 仅对字母字符进行编码。请查看函数
    isalpha()
    来了解这一点。
  • 准确编码大写和小写字符。请注意,在 ASCII 中,大写字母和小写字母是单独的实体。 意味着,您的代码必须能够处理这两种情况,因为它们的处理方式不同。
    • 也许花一些时间坐下来研究 ASCII 表可能会对您有所帮助,因为它将帮助您了解添加密钥时
    • 真正
    • 发生了什么。
    使用正确的公式对字母进行编码。第i个明文字母p
  • i
  • 对应的第i个密文字母ci定义为ci = (pi + k) % 26
    您的代码与此公式等效,但它不考虑换行、大写/小写字母等。项目规范不仅仅要求您重复该公式,它要求您使用它来解决问题。为此,您必须了解它。随后我会详细解释。
  • 我推荐:

就地修改文本。目前,您计算密文并打印它。如果您添加用于修改文本所在位置的代码,则可以更轻松地忽略非字母字符。
  • 修改公式。
  • 其中 𝚨 是大写或小写字符开头的 ASCII 字符代码,公式可能如下所示:
      • ci = (pi - 𝚨 + k) % 26 + 𝚨
      • 这个修改后的公式的作用是首先获取 P
      • i
      • 的 ASCII 代码,并将其转换为一个数字,表示它是字母表中的哪个字母,忽略大小写。然后,您可以添加密钥(移动密码)。在此结果上使用 % 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)
    


0
投票

你应该只对字母进行编码
  • 您应该减去第一个字母的代码
  • '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;
}

© www.soinside.com 2019 - 2024. All rights reserved.