Прописные символы в строке не могут быть преобразованы в строчные, и вычитание их значения ASCII не делает их в алфавитном указателе - PullRequest
0 голосов
/ 25 августа 2018

Я новичок, пытающийся научиться кодировать. В настоящее время я делаю курс CS50. Я столкнулся с проблемой с проблемой шифра Vigenere; пожалуйста, смотрите мой код по ссылке на github ниже.

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

#define ASCII_VALUE_LOWER 97
#define ASCII_VALUE_UPPER 65
#define NR_OF_LETTERS 26

int main(int argc, string argv[])
{
    char key[strlen(argv[1]) + 1];
    strcpy(key, argv[1]);
    int keyLen = strlen(key);

    for (int k = 0; k < keyLen; k++)
    {
        if (!isalpha(key[k]))
        {
            printf("ERROR: Secret key has to be alphabetical string, program will be terminated now!\n");
            return 1; // main should return 1 (signify an error)
        }
        //converting key letters to respective values
        if (isupper(key[k]))
            {
                key[k] -= ASCII_VALUE_UPPER;
            }
            key[k] -= ASCII_VALUE_LOWER;
    }
    //if program is executed without an argument, or with more than one arguments
    if (argc != 2)
    {
        printf("ERROR: You need to give a secret key as an argument, program will be terminated now!\n");
        return 1; // main should return 1 (signify an error)
    }
    else
    {
        string plaintext = get_string("plaintext: "); //get a plaintext from a user using cs50 custom function from their library
        int stringLen = strlen(plaintext);
        int keyIndex = 0;

        for (int j = 0; j < keyLen; j++)
        {

        }

        //for each character in the plaintext string
        for (int i = 0; i < stringLen; i++)
        {
            //check if is alphabetic (tolower, toupper)
            if (isalpha(plaintext[i]))
            {
                //cypher_character = (plain_character + key_character)% 26
                if (islower(plaintext[i]))
                {
                    keyIndex %= keyLen;
                    plaintext[i] = ((plaintext[i] - ASCII_VALUE_LOWER + key[keyIndex]) % NR_OF_LETTERS) + ASCII_VALUE_LOWER;
                }
                else
                {
                    plaintext[i] = ((plaintext[i] - ASCII_VALUE_UPPER + key[keyIndex]) % NR_OF_LETTERS) + ASCII_VALUE_UPPER;
                }
                keyIndex++;
            }
            //else leave as is
        }

        //print ciphertext in a format "ciphertext: " + ciper
        printf("ciphertext: %s\n", plaintext);
        return 0;
    }
}

Проблемы заключаются в следующем:

  1. если вы передаете аргумент прописными буквами в ключе, значения будут странными и преобразование не будет работать. Идея состоит в том, чтобы взять каждый символ в строковом ключе и вычесть 65, если они прописные, или 97, если строчные, чтобы их значение ASCII было равно 0 - 25. Затем я могу использовать их в формуле шифра Vigenere: cipher[i_index] = (plaintext[i_index] + key[j_index]) % 26

  2. не справляется с отсутствием argv[1], хотя есть условие IF (!argc == 2), поэтому оно не должно проходить, если вы ничего не передаете.

    "failed to execute program due to segmentation fault".
    

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

Ответы [ 2 ]

0 голосов
/ 25 августа 2018

Как и предполагали другие, все было исправлено, если кому-то было бы любопытно, где именно была ошибка:

1.] Ошибка, обнаруженная @Rob Napier

for (int i = 0; i < stringLen; i++)
    {
        //check if is alphabetic (tolower, toupper)
        if (isalpha(plaintext[i]))
        {
            keyIndex %= keyLen; // makes sure that keyIndex doesnt exceeds actual string length
            //cypher_character = (plain_character + key_character)% 26
            if (islower(plaintext[i]))
            {
                plaintext[i] = ((plaintext[i] - ASCII_VALUE_LOWER + key[keyIndex]) % NR_OF_LETTERS) + ASCII_VALUE_LOWER;
            }
            else
            {
                plaintext[i] = ((plaintext[i] - ASCII_VALUE_UPPER + key[keyIndex]) % NR_OF_LETTERS) + ASCII_VALUE_UPPER;
            }
            keyIndex++;
        }
        //else leave as is
    }

keyIndex% = keyLen;был помещен в условие if, расположенное под ним, поэтому он не выполнялся на каждой итерации цикла FOR.

2.] ответил @Joe Farrel: потому что к тому времени, когда я проверил, является ли argc! = 2, яуже получили доступ к argv [1] и, таким образом, предположили, что argc> = 2. Если вызывающая сторона не предоставила аргумент, тогда argv [1] находится за концом массива и вычисление этого выражения приводит к неопределенному поведению.- Итак, я переместил условие if в первую очередь на главную.

0 голосов
/ 25 августа 2018
    if (isupper(key[k]))
        {
            key[k] -= ASCII_VALUE_UPPER;
        }
        key[k] -= ASCII_VALUE_LOWER;

Если символ в верхнем регистре, это вычитает ASCII_VALUE_UPPER.И потом, несмотря ни на что, вычитает ASCII_VALUE_LOWER.Из окружающего кода, я полагаю, вы имели в виду:

    if (isupper(key[k])) {
        key[k] -= ASCII_VALUE_UPPER;
    } else {
        key[k] -= ASCII_VALUE_LOWER;
    }
...