Программа CS50 Caesar работает, но check50 говорит, что это не так - PullRequest
1 голос
/ 05 мая 2020

Я создал эту программу, но получаю ошибки на CS50, свидетельствующие о том, что я ничего не сделал правильно.

Требования следующие:

Реализуйте вашу программу в файле с именем caesar. c в каталоге с именем caesar.

Ваша программа должна принимать единственный аргумент командной строки, неотрицательное целое число. Для обсуждения назовем его k.

Если ваша программа выполняется без каких-либо аргументов командной строки или с более чем одним аргументом командной строки, ваша программа должна распечатать сообщение об ошибке по вашему выбору (с printf ) и немедленно верните из main значение 1 (что обычно указывает на ошибку).

Если какой-либо из символов аргумента командной строки не является десятичным числом di git, ваша программа должна распечатать сообщение Использование: ключ ./caesar и возврат из основного значения 1.

Не предполагайте, что k будет меньше или равно 26. Ваша программа должна работать для всех неотрицательных целых значений на k меньше чем 2 ^ 31 - 26. Другими словами, вам не нужно беспокоиться, если ваша программа в конечном итоге сломается, если пользователь выберет значение k, которое слишком велико или почти слишком велико, чтобы поместиться в int. (Напомним, что int может переполняться.) Но даже если k больше 26, алфавитные символы на входе вашей программы должны оставаться буквенными символами на выходе вашей программы. Например, если k равно 27,

A не должно становиться [даже если [находится на 27 позиций от A в ASCII, на http://www.asciichart.com/ [asciichart.com] ; A должен стать B, так как B находится на расстоянии 27 позиций от A, при условии, что вы переходите от Z к A.

Ваша программа должна выводить открытый текст: (без новой строки), а затем запрашивать у пользователя строку открытого текста (с использованием get_string).

Ваша программа должна выводить зашифрованный текст: (без новой строки), за которым следует соответствующий зашифрованный текст открытого текста, причем каждый алфавитный символ в открытом тексте «поворачивается» на k позиций; неалфавитные символы должны выводиться без изменений.

Ваша программа должна сохранять регистр: заглавные буквы, хотя и повернутые, должны оставаться заглавными буквами; строчные буквы, хотя и повернутые, должны оставаться строчными буквами.

После вывода зашифрованного текста вы должны напечатать новую строку. Затем ваша программа должна выйти, вернув 0 из main.

Мой код:

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

int main(int argc, string argv[])
{
    //check if k inputed
    if (argc != 2)
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }
    //value k is the number after ./caesar
    int k = atoi(argv[1]) % 26;
    int x = 0;
    int s = strlen(argv[1]);
    //check if k is a positive integer
    if (k < 0)
    {
        printf("Usage: .caesar key\n");
        return 1;
    }
    else
    {
        //check for arguments
        for (int i = 0; i < s; i++)
        {
            if (isalpha (argv[1][i]))
            {
                continue;
            }
            else if (isalnum (argv[1][i]))
            {
                x++;
            }
            else
            {
                continue;
            }
        }
        if (x != s)
        {
            printf("Usage: ./caesar key\n");
        }
        else if (x == s)
        {
            //get plaintext
            string plain_text = get_string("plaintext: ");
            printf("ciphertext: ");
            for (int y = 0; y <= strlen(plain_text); y++)
            {
                //change letters
                if (isalpha(plain_text[y]))
                {
                    char p = plain_text[y];
                    int cipher_int = p + k;
                    if (isupper(p))
                    {
                        while(cipher_int >= 90)
                        {
                            cipher_int -= 26;
                        }
                            char cipher_text = cipher_int;
                            printf("%c", cipher_text);
                    }
                    if (islower(p))
                    {
                        while(cipher_int >= 122)
                        {
                            cipher_int -= 26;
                        }
                            char cipher_text = cipher_int;
                            printf("%c", cipher_text);
                    }
                }
                else
                {
                    printf("%c", plain_text[y]);
                }
            }
            printf("\n");
        }
    }
    return 0;
}

Ответы [ 2 ]

1 голос
/ 05 мая 2020

Похоже, ваша упаковка работает некорректно. Я обнаружил это, когда использовал 3 в качестве ключа и поставил «Быстрая лиса перепрыгивает через ленивую коричневую собаку». как обычный текст, «коричневый» превратился в «eur`q» вместо «eurzq». Я думаю, вы используете >= в своих сравнениях упаковок, когда вам следует использовать >.

1 голос
/ 05 мая 2020

Ваша проверка цифр очень громоздка и не приводит к тому, что программа возвращает 1, как требуется, если аргумент неверен.

Вот более простой тест:

        //check for arguments
        for (int i = 0; i < s; i++) {
            if (!isdigit((unsigned char)argv[1][i])) {
                printf("Usage: ./caesar key\n");
                return 1;
            }
        }

Также обратите внимание, что вы должны остановить кодировку l oop, когда индекс == длина строки. следовательно, оператор должен быть <.

Другая проблема - использование isalpha() и аналогичных функций из <ctype.h> со значениями char. Эти функции не определены для отрицательных значений (кроме EOF). Некоторые платформы определяют char как подписанный по умолчанию, в результате чего isalpha(plaintext[y]) имеет неопределенное поведение, если пользователь вводит текст, отличный от ASCII. Чтобы избежать этой проблемы, приведите аргумент как (unsigned char).

Кроме того, вам не следует использовать жестко запрограммированные значения ASCII, такие как 90 и 122, используйте символьные константы, такие как 'a' и 'z' для лучшая читаемость. Это сделает еще одну ошибку в кодировке l oop более очевидной: while(cipher_int >= 90) должно быть if (cipher_int > 'A'), а while(cipher_int >= 122) должно быть if(cipher_int > 'z').

Вот измененная версия:

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

int main(int argc, string argv[])
{
    // check for a single command line argument
    if (argc != 2) {
        printf("Usage: ./caesar key\n");
        return 1;
    }
    char *arg = argv[1];
    if (*arg == '\0') {
        printf("caesar: key cannot be an empty string\n");
        return 1;
    }
    // check that the argument is a non negative number
    for (size_t i = 0; arg[i]; i++) {
        if (!isdigit((unsigned char)arg[i])) {
            printf("Usage: ./caesar key\n");
            return 1;
        }
    }
    // value k is the shift number after ./caesar
    int k = atoi(argv[1]) % 26;

    // get plaintext
    string plain_text = get_string("plaintext: ");
    printf("ciphertext: ");
    for (size_t i = 0; plain_text[i] != '\0'; i++) {
        unsigned char c = plain_text[i];
        // change letters
        if (islower(c)) {
            putchar('a' + ((c - 'a') + k) % 26);
        } else
        if (isupper(c)) {
            putchar('A' + ((c - 'A') + k) % 26);
        } else {
            putchar(c);
        }
    }
    printf("\n");
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...