2015-09-05 4 views
1

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

[email protected]:~/Desktop/programming/C/current/vigenere$ ./vigenere lemon attackatdawn 
LXF OPV EFR NHR [0002] 

Это поле в конце не появляется, как она должна, она предназначена для представления, когда Баш пытается отобразить 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 StackOverflow 
{ 
    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; 
} 

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

ответ

3

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

+1

OP также пишет для входных строк в 'string_clean()', но аргументы, передаваемые в ' main() 'может не записываться. –

+0

Большое спасибо за этот ответ, поскольку он решил мою проблему. Два вопроса, однако, зачем использовать malloc для calloc и почему plain_len + 1, а не plain_len? Не лучший день для офф- by-one.:/ –

+1

'calloc' занумерует память, но вы все равно все равно не нуждаетесь в ней, но не нужно, чтобы она была равна нулю. И' + 1', потому что вам нужно место для упомянутого ограничителя строк. 'strlen()' does not включите это. –

Смежные вопросы