为什么循环有问题(pset2替换)

时间:2020-04-30 06:55:08

标签: c cs50

我一直在进行CS50X pset2替换。我认为这差不多完成了。当我输入 </div> </div> {% endfor %} A B等单个字符时,密文将得到正确的结果。 (例如D将获得A,“ B”将获得J,而T将获得D,依此类推...

但是,如果我输入E,则密文将仅显示ABC,而其他密文则无法显示。我做错了什么?

J

2 个答案:

答案 0 :(得分:0)

您的问题是逻辑错误,似乎是由于您试图对失控的代码进行更改而导致的。您的代码中有不必要的循环和未使用的变量。您需要更改u声明的范围,以便在每次迭代时将其重新初始化。您只需要完全删除for (int i = 0, n = strlen(key); i < n; i++)循环,就不使用inciphertextl(ell)也是如此。

您需要在int u = 64;之后立即移动if (isupper(plaintext[k])),以便在每次迭代时将其重置。

我怀疑所有printf语句都用于调试,而您实际上只想要key输出。综上所述,您可以将代码重新排列为:

#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>

int main (int argc, string argv[]) {

    if (argc == 2) {    /* validate key given */

        string key = argv[1];
        string plaintext = get_string("plaintext: ");
        printf("ciphertext: ");

        for (int k = 0, p = strlen(plaintext); k < p; k++) 
        {
            if (isupper(plaintext[k])) 
            {
                int u = 64;
                for (int j = 0; j < 26; j++) 
                {
                    u = u + 1;
                    if (u == plaintext[k]) {
                        printf("%c", key[j]);
                        break;
                    }
                }
            }
            else
                printf("%c", plaintext[k]);
        }
        putchar ('\n');
    }
}

使用/输出示例

$ ./bin/cs50_cypher2 JTREKYAVOGDXPSNCUIZLFBMWHQ
plaintext: ABD
ciphertext: JTE

简化逻辑

如果考虑以上代码的实际作用,可以将其简化为:

#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>

int main (int argc, string argv[]) {

    if (argc < 2) {    /* validate key given */
        fputs ("usage: ./program key\n", stderr);
        return 1;
    }

    string key = argv[1];
    string plaintext = get_string("plaintext: ");
    printf("ciphertext: ");

    for (int k = 0, p = strlen(plaintext); k < p; k++) 
    {
        if (isupper(plaintext[k]))
            putchar (key[plaintext[k] - 'A']);
        else
            putchar (plaintext[k]);
    }
    putchar ('\n');
}

或者,如果您使用三元运算符,则for循环会简化为:

    for (int k = 0, p = strlen(plaintext); k < p; k++) 
        putchar (isupper(plaintext[k]) ? key[plaintext[k] - 'A'] : plaintext[k]);

并且由于不需要调用strlen(plaintext),因此您可以完全消除string.h,而只需循环for (int k = 0; plaintext[k]; k++),因为plaintext是一个以Null结尾的字符串,因此整个程序可以减少为:

#include <cs50.h>
#include <stdio.h>
#include <ctype.h>

int main (int argc, string argv[]) {

    if (argc < 2) {    /* validate key given */
        fputs ("usage: ./program key\n", stderr);
        return 1;
    }

    string key = argv[1];
    string plaintext = get_string("plaintext : ");
    printf("ciphertext: ");

    for (int k = 0; plaintext[k]; k++) 
        putchar (isupper(plaintext[k]) ? key[plaintext[k] - 'A'] : plaintext[k]);

    putchar ('\n');
}

处理小写字母

您知道作为第一个参数输入的key都是大写的。因此,如果要输出小写的key,则在应用偏移量后必须在键上调用tolower()。由于对于大写字母,您只想知道要使用的26个字符的键中的偏移量,因此只需找出当前字母来自'A'的字母数,然后在key[]中获取该偏移量,例如

    key[plaintext[k] - 'A']

对于小写输入,您需要找出key中的偏移量以找出小写字母的差异,然后将tolower()应用于键,例如

    tolower(key[plaintext[k] - 'a'])

请参见ASCII Table & Description

总而言之,您的for循环可以写为:

    for (int k = 0; plaintext[k]; k++) {
        if (isupper(plaintext[k]))
            putchar (key[plaintext[k] - 'A']);
        else if (islower(plaintext[k]))
            putchar (tolower(key[plaintext[k] - 'a']));
        else
            putchar (plaintext[k]);
    }

使用/输出示例

$ ./bin/cs50_cypher4 JTREKYAVOGDXPSNCUIZLFBMWHQ
plaintext : AbZ 50
ciphertext: JtQ 50

仔细检查一下,如果还有其他问题,请告诉我。

答案 1 :(得分:0)

我也尝试检测低调,但是结果不是我想要的。我输入“ AbZ 50”。假设答案是“ JtQ 50”。但是,它是“ JTQ 50”

#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>

int main (int argc, string argv[]) {

    if (argc == 2) {    /* validate key given */

        string key = argv[1];
        string plaintext = get_string("plaintext: ");
        printf("ciphertext: ");

        for (int k = 0, p = strlen(plaintext); k < p; k++)
        {
            if (isupper(plaintext[k]))
            {
                int u = 64;
                for (int j = 0; j < 26; j++)
                {
                    u = u + 1;
                    if (u == plaintext[k]) {
                        printf("%c", key[j]);
                        break;
                    }
                }
            }
            else if (islower(plaintext[k]))
            {
                int l = 96;
                for (int j = 0; j < 26; j++)
                {
                    l = l + 1;
                    if (l == plaintext[k]) {
                        printf("%c", key[j]);
                        break;
                    }
                }
            }
            else
                printf("%c", plaintext[k]);
        }
        putchar ('\n');
    }
}