【问题标题】:Vigenere's cipher in CC中的维吉尼亚密码
【发布时间】:2015-12-01 17:30:57
【问题描述】:

我用 C 语言编写了一个程序,它接受纯文本和密码,并使用 vigenere 的密码生成密文。虽然代码大部分时间都会产生正确的输出,但我发现了一个示例,它产生了意外的输出,我自己找不到问题。输出如下:

jess@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 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;
}

非常感谢所有和任何帮助/建议!

【问题讨论】:

    标签: c encryption vigenere


    【解决方案1】:

    你需要NUL-terminate你的输出字符串。 :-( 这也意味着您对calloc 的调用(不过,您真的应该只使用malloc)应该指定plain_len + 1,而不仅仅是plain_len

    【讨论】:

    • OP 也在写入string_clean() 中的输入字符串,但传递给main() 的参数可能不可写。
    • 非常感谢您的回答,因为它解决了我的问题。但是有两个问题,为什么使用 malloc 而不是 calloc,为什么使用 plain_len + 1 而不是 plain_len?不是我最好的一天。 ://
    • calloc 将内存归零,但无论如何你都可以写入它,而不需要它为零。还有+1,因为您需要为提到的字符串终止符留出空间。 strlen() 不包括这个。
    • @psychedelic_alex malloc 不会先清除内存。这通常比calloc 快,并且由于您的程序不依赖于清除的内存,所以它工作得很好。 + 1 是因为您需要为 NUL 终止符分配额外的字符。或者,你知道,风向标刚才说的话。 ;-)
    • 非常感谢,你们在这里为我节省了大量时间 :-)。对于@WeatherVane,还有一个问题,什么时候以及为什么 argv 不可写?我实际上听说它总是可写的,但我很高兴错了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-02
    • 2016-01-18
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    相关资源
    最近更新 更多