Шифр Вигенера в C

Я написал программу на C, которая принимает обычный текст и пароль и создает зашифрованный текст, используя шифр Vigenere. В то время как код выдает правильный вывод большую часть времени, я нашел пример, где он выдает неожиданный вывод, и я не могу найти проблему самостоятельно. Вывод как таковой:

alex@alex-laptop:~/Desktop/programming/C/current/vigenere$ ./vigenere lemon attackatdawn
LXF OPV EFR NHR [0002]

Это поле в конце не отображается должным образом, оно предназначено для представления, когда bash пытается отобразить символ ascii 2, но при копировании и вставке он отображается неправильно. Это пример текста из Википедии для шифра, и это единственный найденный мной текст, который нарушает мою программу (я не знаю, в чем причина, поэтому я не могу ее воспроизвести), но я уверен, что есть больше строк это даст аналогичные результаты. Я подозреваю, что сделал что-то, что вызывает неопределенное поведение, но я не уверен. Что я здесь не так сделал? Мой код:

// vigenere.c - Takes a plaintext and a cipher key from argv[1] and argv[2] and produces the cipher text according to Vigenere's cipher

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

void string_clean(char *source) //Courtesy (mostly) of user 'Aaron' of Stackru
{
    char *i = source;
    char *j = source;

    while(*j != 0) {
        *i = *j++;
        if( *i != ' ' && (isupper(*i) || islower(*i)) )
            i++;
    }

    *i = 0;
}

char *vigenere_enc(char plain[], char cipher[])
{
    char *cipher_text;

    string_clean(plain);
    string_clean(cipher);

    int plain_len = strlen(plain);
    int cipher_len = strlen(cipher);

    if( !(cipher_text = calloc(plain_len, sizeof(char))) )
        return 0;

    for(int i = 0; i < cipher_len; i++) {
        if(isupper(cipher[i]))
            cipher[i] -= 'A';
        else if(islower(cipher[i]))
            cipher[i] -= 'a';
    }

    int j = 0;

    for(int i = 0; i < plain_len; i++, j++) {
        if(j == cipher_len)
            j = 0;

        if(isupper(plain[i]))
            plain[i] -= 'A';
        else if(islower(plain[i]))
            plain[i] -= 'a';

        cipher_text[i] = ((plain[i] + cipher[j]) % 26) + 'A';
    }
    return cipher_text;
}

int main(int argc, char *argv[])
{
    if(argc != 3)
        return 1;
    char *cipher = vigenere_enc(argv[2], argv[1]);

    for(int i = 0; i < strlen(cipher); i++) {
        if(i % 3 == 0 && i != 0)
            putchar(' ');
        putchar(cipher[i]);
    }

    putchar('\n');

    return 0;
}

Все и любая помощь / предложения с благодарностью!

1 ответ

Решение

Вам нужно NUL-завершить вашу выходную строку.:-(Это также означает, что ваш звонок calloc (вы действительно должны просто использовать mallocправда) следует указать plain_len + 1, не просто plain_len,

Другие вопросы по тегам