Почему у циклов есть проблема (замена pset2) - PullRequest
0 голосов
/ 30 апреля 2020

У меня работала замена CS50X pset2. Я думаю, что это почти сделано. Когда я ввожу один символ, такой как A или B D и т. Д., Зашифрованный текст даст правильный результат. (например, A получит J, "B" получит T и D получит E и т. д. *

Однако, если я введу ABC, зашифрованный текст покажет только J, а другой не сможет показать. Что я сделал не так?

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


int ciphertext = 0;

//Key
//JTREKYAVOGDXPSNCUIZLFBMWHQ

int main(int argc, string argv[])
{
     //Check that program was run with one command-line argument
    if (argc == 2)
    {

        string key = argv[1];



        //check the key does it validate
        for (int i = 0, n = strlen(key); i < n; i++)
        {

            string plaintext = get_string("plaintext: ");
            printf("ciphertext: \n");

            int u = 64;


            for (int k = 0, p = strlen(plaintext); k < p; k++)
            {
                if (isupper(plaintext[k]) != 0)
                {
                    for (int j = 0; j < 26; j++)
                    {

                        u = u + 1;
                        //printf("u is %c\n", u);


                        if (u == plaintext[k])
                        {
                            ciphertext = key[j];
                            printf("Key is %c\n", key[j]);
                            printf("Plaintext is %c\n", plaintext[k]);
                            printf("ciphertext is %c\n", ciphertext);
                            //break;
                        }

                    }
                }

                else
                {
                    printf("%c", plaintext[k]);
                }
            }

            return 0;
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 30 апреля 2020

Я тоже пытаюсь определить нижний ключ, но результат не тот, который я хочу. Я ввод "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');
    }
}
0 голосов
/ 30 апреля 2020

Ваши проблемы - логические c ошибки, которые появляются в результате изменений, которые вы пытались внести в код, который вышел из-под контроля. У вас есть ненужные циклы и неиспользуемая переменная в вашем коде. Вам нужно изменить область действия объявления u, чтобы она повторно инициализировалась на каждой итерации. Вам просто нужно удалить for (int i = 0, n = strlen(key); i < n; i++) l oop, ни i, ни n не используются. То же самое для ciphertext и l (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

Упрощение логики c

Если вы думаете о том, что на самом деле делает код выше, его можно уменьшить до:

#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 l oop сводится к простому:

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

И поскольку нет необходимости звонить strlen(plaintext), вы можете полностью исключить string.h и просто l oop for (int k = 0; plaintext[k]; k++), начиная с plaintext является строкой с нулевым символом в конце, вся ваша программа может уменьшиться до:

#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 Таблица и описание

В целом, ваш for l oop может быть записан как:

    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

Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.

...