Дополнительные персонажи в конце Vigenere cs50 Pset2

Я новичок в программировании и занимаюсь им уже пару недель. Сейчас я прохожу курс cs50, и я написал код для pset2 vigenere. Когда я использовал check50, я понял, что мне нужно учитывать пробелы и небуквенные символы, не пропуская вперед ключ.

Я добавил "j--;" и, хотя код правильный, теперь он создает дополнительные случайные символы в конце зашифрованного текста.

Кроме того, при проверке argv [1] только букв в моем коде у меня есть оператор if, который имеет "int key = argv [1] [i];" в теле. Он ничего не делает, но я не знаю, как заставить его просто продолжать проверку следующего символа без пустого тела, что недопустимо.

Любая помощь будет оценена по достоинству! Большое спасибо!

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


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

{
    //making sure it is not more than one command line
    if (argc != 2)
    {
        printf("Usage: ./vigenere key \n");
        return 1;
    }

    //if it is one command line, making sure the input is just letters      
    if (argc == 2)
    {
        for (int i = 0, n = strlen(argv[1]); i < n; i++)
        {
            if (isalpha(argv[1][i]))
            {    
                int key = argv[1][i];
            }
            else
            {
                printf("Usage: ./vigenere key \n");
                return 1;
            }
        }   

    }
    //asking user for input text
    string plaintext = get_string("plaintext: ");
    printf("ciphertext:");

    //going through a loop to turn plain text into ciphertext 
    int i = 0; 
    int n = strlen(plaintext); 
    string key = argv[1];


    //looping through the key    
    while (i < n)

    {

        for (int j = 0, m= strlen(key); j < m; j++, i++)

        {   
            //using the asci of each char as an int
            int asc = (plaintext[i]);
            int k = key[j];
            //if lowercase
            if (k >= 97 && k <= 122)
            {
                k -= 97;
            }
            else
            {
                k -= 65;
            }

            //if lowercase
            if (asc >= 97 && asc <= 122)
            {
                printf("%c", ((((asc - 97) + k) % 26) + 97));
            }
            //if uppercase
            else
            {
                if (asc >= 65 && asc <= 90)
                {
                    printf("%c", ((((asc - 65) + k) % 26) + 65));
                }
                //if non-letter
                else
                {  
                    printf("%c", asc);
                    j--;

                }
            }

        }  


    }


    printf("\n");

}      

Это ожидаемые и фактические результаты:

key: baz
plaintext: hello, world!
expected ciphertext: iekmo, vprke!

actual ciphertext:   iekmo, vprke!!pu

person Alejandro89    schedule 13.05.2019    source источник
comment
Вы смотрели на другие вопросы с тегами cs50 и vigenere, чтобы узнать, как эти программы (возможно, те, что указаны в ответах, а не в вопросах), делают это? Если вы наберете [c] [cs50] [vigenere] в области поиска, вы получите 71 вопрос, включая этот. Где-то среди них есть то понимание, которое вам нужно.   -  person Jonathan Leffler    schedule 14.05.2019
comment
Наиболее частая причина появления «лишних символов» заключается в том, что вы неправильно завершили строку нулем - вы проверили, завершаете ли строку нулем.   -  person Jonathan Leffler    schedule 14.05.2019
comment
У вас есть int main(int argc, string argv[0]) - 0 является необычным, и его лучше не указывать. Лучше всего сообщать об ошибках на stderr (используйте fprintf(stderr, …) вместо printf(…)). Вы сообщаете об ошибке использования, когда нет ключа, а также когда в ключе есть не алфавитный символ. Было бы лучше использовать другое сообщение об ошибке, если ключ предоставлен, но содержит неалфавитные символы.   -  person Jonathan Leffler    schedule 14.05.2019
comment
Спасибо за совет!   -  person Alejandro89    schedule 14.05.2019
comment
ОТ: относительно: printf("Usage: ./vigenere key \n"); 1) Сообщения об ошибках должны выводиться на stderr, а не на stdout. 2) тот же исполняемый файл не заботится о том, какое имя исполняемого файла, поэтому следует использовать фактическое имя, на что указывает: argv[0] Полезным примером может быть: fprintf( stderr, "Usage: %s <key>\n", argv[0] );   -  person user3629249    schedule 17.05.2019


Ответы (1)


Поскольку программа увеличивает i здесь for (int j = 0, m= strlen(key); j < m; j++, i++), она позволяет читать после конца открытого текста. Цикл while не будет оценивать i до тех пор, пока цикл for не будет выполнен. И это может привести к бесконечному циклу, в зависимости от того, какое содержимое памяти находится после конца открытого текста. Если он никогда не встретит что-то в диапазоне от a до z или от A до Z, он будет j-- навсегда.

Вам нужно выйти из цикла for, если и когда i == strlen(plaintext).

person DinoCoderSaurus    schedule 14.05.2019
comment
Вау, теперь это так очевидно! Оно работает!! Огромное спасибо!! - person Alejandro89; 14.05.2019