维格纳';C中的s密码

维格纳';C中的s密码,c,encryption,vigenere,C,Encryption,Vigenere,我用C写了一个程序,它接受纯文本和密码,并使用vigenere的密码生成密文。虽然代码大部分时间都会产生正确的输出,但我发现了一个示例,其中代码会产生意外的输出,而我自己却找不到问题。输出如下: jess@laptop:~/Desktop/programming/C/current/vigenere$ ./vigenere lemon attackatdawn LXF OPV EFR NHR [0002] 最后的那个框并没有显示它应该显示的样子,它是用来表示bash试图显示ascii字符2的时

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

jess@laptop:~/Desktop/programming/C/current/vigenere$ ./vigenere lemon attackatdawn
LXF OPV EFR NHR [0002]
最后的那个框并没有显示它应该显示的样子,它是用来表示bash试图显示ascii字符2的时间,但是复制和粘贴并没有正确显示它。这是来自维基百科的密码示例文本,也是我发现的唯一一个破坏我的程序的文本(我不知道原因是什么,所以我无法复制它),但我确信会有更多的字符串产生类似的结果。我怀疑我做了一些导致未定义行为的事情,但我不确定。我做错了什么? 我的代码:

//vigenere.c-从argv[1]和argv[2]中获取明文和密码密钥,并根据vigenere的密码生成密码文本
#包括
#包括
#包括
#包括
void string_clean(char*source)//由StackOverflow的用户“Aaron”提供(大部分)
{
char*i=源;
char*j=源;
而(*j!=0){
*i=*j++;
如果(*i!=''&(isupper(*i)| islower(*i)))
i++;
}
*i=0;
}
char*vigenere_enc(字符普通[],字符密码[])
{
字符*密文;
串_清洁(普通);
字符串_clean(密码);
int平原=斯特伦(平原);
int cipher_len=strlen(密码);
if(!(cipher\u text=calloc(plain\u len,sizeof(char)))
返回0;
对于(int i=0;i

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

您需要输入输出字符串:-(这也意味着您对
calloc
(尽管您确实应该使用
malloc
)的调用应该指定
plain\u len+1
,而不仅仅是
plain\u len

OP还在
string\u clean()
中写入输入字符串,而是将参数传递给
main()
可能不可写。非常感谢您的回答,因为它解决了我的问题。不过,有两个问题,为什么要使用malloc而不是calloc,为什么是plain_len+1而不是plain_len?这不是我最好的休息日。:/
calloc将内存归零,但您无论如何都要将内存归零,而不需要它归零。
+1
因为你需要为提到的字符串终止符留出空间。
strlen()
不包括这一点。@psychedelic_alex
malloc
不会首先清除内存。这通常比
calloc
快,而且由于您的程序不依赖已清除的内存,所以工作正常。+1是因为您需要为NUL终止符分配额外的字符。或者,您知道,Weather Vane刚才说了什么谢谢大家,你们帮我节省了很多时间。还有一个问题是@WeatherVane何时以及为什么argv不可写?我听说它总是可以写的,但我很高兴我错了。
// 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;
}