gpt4 book ai didi

c - 为什么我的 vigenere.c 不工作?

转载 作者:行者123 更新时间:2023-11-30 15:27:37 24 4
gpt4 key购买 nike

我不断更改此代码的循环部分,但我的 check50 总是失败。我不知道发生了什么事。下面是我的代码:

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

int main(int argc, string argv[])
{
// declare variables
int cipherText;

if (argc != 2)
{
printf("Usage: ./vigenere keyword");
printf("\n");
return 1;
}
// keyword is the second command line argument
string key = argv[1];
int keylen = strlen(argv[1]);

// iterate through keyword to check if alphabetical
for (int i = 0, n = strlen(argv[1]); i < n; i++)
{
if ((key[i] >= '0') && (key[i] <= '9'))
{
printf("Keyword must consist only of letters.");
return 1;
}
}

// get the plaintext
string plainText = GetString();

// encypher - iterate over the characters in string, print each one encrypted
for (int i = 0, j = 0, n = strlen(plainText); i < n; i++, j++)
{
// start the key again if key shorter than plainText
if (j >= strlen(key))
{
j = 0;
}

// skip key[j] if plainText[i] is not an alpha character
if (!isalpha(plainText[i]))
{
j = (j-1);
}

// makes Aa = 0, Zz = 25 for the uppercase letters
if (isupper(key[j]))
{
key[j] = (key[j] - 'A');
}

// makes Aa = 0, Zz = 25 for lowercase letters
else if (islower(key[j]))
{
key[j] = (key[j] - 'a');
}


if (isupper(plainText[i]))
{
cipherText = (plainText[i] - 'A');
cipherText = ((cipherText + key[j%keylen])%26) + 'A';
printf("%c", cipherText);
}

else if (islower(plainText[i]))
{
cipherText = (plainText[i] - 'a');
cipherText = ((cipherText + key[j%keylen])%26 + 'a');
printf("%c", cipherText);
}

else
{
printf("%c", plainText[i]);
}
}
printf("\n");
return 0;

}

有些人回答说:“第一个 for 循环有问题。条件是在应该检查 i > keylen 时检查 i < keylen ”。

此外,在计算下一个输出值时,步骤应该是

  • (p[i]-65) 得出 0 到 25 之间的数字
  • 相加 (key[i % keylen]) 会得到 0 到 50 之间的数字
  • 应用模 26,使数字介于 0 到 25 之间(这是缺少的步骤)
  • 然后加上 65 即可得到输出”

这就是我尝试做的。

最佳答案

鉴于此代码:

int keylen = strlen(argv[1]);

// iterate through keyword to check if alphabetical
for (int i = 0, n = strlen(argv[1]); i < n; i++)
{
if ((key[i] >= '0') && (key[i] <= '9'))
{
printf("Keyword must consist only of letters.");
return 1;
}
}

循环内的测试将数字识别为“不是字母”(这是有效的),但忽略标点符号、空格等。您可能应该使用 if (!isalpha(key[i])) 进行测试(并且有礼貌地打印错误消息中的错误字符,该字符应该打印在标准错误上,而不是标准输出,并应以换行符结尾:

        fprintf(stderr, "Keyword must consist only of letters (%c found at %d)\n",
key[i], i+1);

您可以对其进行改进,使其不会尝试使用 %c 打印不可打印的字符,但这是朝着正确方向迈出的一大步。

你真的不需要在循环中设置n;您只需在循环之前设置 keylen 即可,因此您可以编写:

for (int i = 0; i < keylen; i++)

但是,这主要是装饰性的。你真正的问题在于:

    // start the key again if key shorter than plainText
if (j >= strlen(key))
{
j = 0;
}

// makes Aa = 0, Zz = 25 for the uppercase letters
if (isupper(key[j]))
{
key[j] = (key[j] - 'A');
}

// makes Aa = 0, Zz = 25 for lowercase letters
else if (islower(key[j]))
{
key[j] = (key[j] - 'a');
}

您可以通过键在每次迭代中修改键字符串。但不幸的是,如果 key 中的任何字母是 aA,您已将其转换为 '\0',这意味着 strlen(key) 返回与之前不同的答案。因此,您应该使用 keylen 代替 strlen()。 AFAICS,如果没有 aA,则该部分代码没问题。

之后,您将拥有:

    if (isupper(plainText[i]))
{
cipherText = (plainText[i] - 'A');
cipherText = ((cipherText + key[j%keylen])%26) + 'A';
printf("%c", cipherText);
}

j % keylen 是多余的; j 已限制为 0 .. keylen-1。与小写文本的代码类似。

将这些更改放在一起,并使用 fgets() 虚拟一个 GetString() 函数,我得到:

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

typedef char *string;

static char *GetString(void)
{
static char buffer[4096];
if (fgets(buffer, sizeof(buffer), stdin) == 0)
{
fprintf(stderr, "EOF detected in GetString()\n");
exit(EXIT_SUCCESS);
}
buffer[strlen(buffer) - 1] = '\0';
return buffer;
}

int main(int argc, string argv[])
{
// declare variables
int cipherText;

if (argc != 2)
{
printf("Usage: ./vigenere keyword");
printf("\n");
return 1;
}
// keyword is the second command line argument
string key = argv[1];
int keylen = strlen(argv[1]);

// iterate through keyword to check if alphabetical
for (int i = 0; i < keylen; i++)
{
if (!isalpha(key[i]))
{
printf("Keyword must consist only of letters (%c at %d)\n",
key[i], i+1);
return 1;
}
}

// get the plaintext
string plainText = GetString();

// encypher - iterate over the characters in string, print each one encrypted
for (int i = 0, j = 0, n = strlen(plainText); i < n; i++, j++)
{
// start the key again if key shorter than plainText
if (j >= keylen)
{
j = 0;
}

// skip key[j] if plainText[i] is not an alpha character
if (!isalpha(plainText[i]))
{
j = (j - 1);
}

// makes Aa = 0, Zz = 25 for the uppercase letters
if (isupper(key[j]))
{
key[j] = (key[j] - 'A');
}
// makes Aa = 0, Zz = 25 for lowercase letters
else if (islower(key[j]))
{
key[j] = (key[j] - 'a');
}

if (isupper(plainText[i]))
{
cipherText = (plainText[i] - 'A');
cipherText = ((cipherText + key[j]) % 26) + 'A';
printf("%c", cipherText);
}
else if (islower(plainText[i]))
{
cipherText = (plainText[i] - 'a');
cipherText = ((cipherText + key[j]) % 26 + 'a');
printf("%c", cipherText);
}
else
{
printf("%c", plainText[i]);
}
}
printf("\n");
return 0;
}

示例运行:

$ ./vigenere bakedalaska
What a wonderful world! The news is good, and the Vigenere cipher is solved.
Xhkx d wznvorguv arrwd! Lre oegw ls rogn, aod dlh Vtgwxese mmshpr ac splfig.
$

关于c - 为什么我的 vigenere.c 不工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26921484/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com