我觉得你有太多的循环[levels]。
如果密钥长度在单词结束之前用完,则重新开始加密单词开头的中的单词(即错误)。
主要的重点是循环所有字词。 A 单个循环递增i
工作,提供它也递增l
[模数键长度]。
这里有一个清理版本[请原谅无偿风格清理]:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
// NOTE: I don't have GetString on my system
char *FakeGetString(void);
int
main(int argc, char *argv[])
{
// key
// prompts if no key is entered
if (argc < 2) {
printf("Please enter your word key");
return 1;
}
char *key = (argv[1]);
int klen = strlen(key);
if (argc >= 2) {
printf("plaintext:");
#if 0
char *word = GetString();
#else
char *word = FakeGetString();
#endif
int wlen = strlen(word);
printf("ciphertext:");
// current key index
int l = 0;
// starts loop to repeat following for loop
// iterates through word entered by user as plaintext
// advance to next key char [with wrap to beginning if we're short]
for (int i = 0; i < wlen; ++i, l = (l + 1) % klen) {
int num = key[l];
int cipher;
// if original characters are uppercase
if (isupper(word[i])) {
cipher = (word[i] + num - 65) % 26 + 65;
}
// if original characters are lowercase
else if (islower(word[i])) {
cipher = (word[i] + num - 97) % 26 + 97;
}
// all other types of characters
else {
cipher = word[i];
}
printf("%c", cipher);
}
printf("\n");
}
return 0;
}
// NOTE: I don't have GetString on my system
char *
FakeGetString(void)
{
static char buf[1000];
char *cp;
fgets(buf,sizeof(buf),stdin);
cp = strchr(buf,'\n');
if (cp != NULL)
*cp = 0;
return buf;
}
UPDATE:
上面的代码我写的是很接近,但没有的V @ genere因为你的原始方程已关闭。键值必须是偏移/行号,因此需要从中减去'A'
(即关键字只能是大写)。
所以,这里是修正版本[有一些额外的清理]:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
// NOTE: I don't have GetString on my system
char *FakeGetString(void);
int
baseof(int chr)
{
int base;
// if original character is uppercase
if (isupper(chr)) {
base = 'A';
}
// if original character is lowercase
else if (islower(chr)) {
base = 'a';
}
// anything else
else
base = 0;
return base;
}
int
main(int argc, char *argv[])
{
int kval;
int base;
int i;
// key
// prompts if no key is entered
if (argc < 2) {
printf("Please enter your word key\n");
return 1;
}
char *key = argv[1];
int klen = strlen(key);
// key must be uppercase and we only want row numbers
for (i = 0; i < klen; ++i) {
kval = key[i];
base = baseof(kval);
if (base) {
key[i] = kval - base;
continue;
}
printf("Key value must be only A-Z\n");
return 1;
}
if (argc >= 2) {
printf("plaintext:");
#if 0
char *word = GetString();
#else
char *word = FakeGetString();
#endif
int wlen = strlen(word);
printf("ciphertext:");
// starts loop to repeat following for loop
// iterates through word entered by user as plaintext
// advance to next key char [with wrap to beginning if we're short]
for (i = 0; i < wlen; ++i) {
int wval = word[i];
int cipher;
base = baseof(wval);
// uppercase or lowercase
if (base) {
kval = key[i % klen];
cipher = ((wval - base) + kval) % 26 + base;
}
// all other types of characters
else {
cipher = wval;
}
printf("%c",cipher);
}
printf("\n");
}
return 0;
}
// NOTE: I don't have GetString on my system
char *
FakeGetString(void)
{
static char buf[1000];
char *cp;
fgets(buf,sizeof(buf),stdin);
cp = strchr(buf,'\n');
if (cp != NULL)
*cp = 0;
return buf;
}
更新#2:
您的代码通过了所有check50检查,除了这一个: :(使用“baz”作为关键字\期望的输出,而不是“密文:xoqmd,szz gflkp!\”来加密“世界,打个招呼!”为“xoqmd,rby gflkp!”,它不会加密单词'正确地说',这就是伟RD。
我测试使用来自上的V @ genere维基百科页测试数据/例子,但它只有一个准备试验例[而不空格或标点。
这是包含一个空格(在“say”之前)的唯一检查。空间必须直接复制。也许这就是原因。
的空间为直接复制,所以这是好的。但是...
正确的方法是,当复制非字母字符时,密钥索引必须增加而不是。
我的版本中使用i
索引的语句和i % klen
索引的关键,所以关键指标将总是递增[有效。这是错误。
讽刺的是,我已经不知道这一点,但没有在当时展开的测试数据。
因此,解决方案是[再:-)]分离索引的变量。
这里的修正版本。当我将其固定我改名i
变量为更具说明性的(例如widx
)和(重新)创建的索引变量的密钥(例如kidx
)。
请注意,现在kidx
是只有在实际加密字符时递增。在“通过”的情况下不不
#include <stdio.h>
#include <string.h>
#include <ctype.h>
// NOTE: I don't have GetString on my system
char *FakeGetString(void);
int
baseof(int chr)
{
int base;
// if original character is uppercase
if (isupper(chr)) {
base = 'A';
}
// if original character is lowercase
else if (islower(chr)) {
base = 'a';
}
// anything else
else
base = 0;
return base;
}
int
main(int argc, char *argv[])
{
int kval;
int base;
int widx;
int kidx;
// key
// prompts if no key is entered
if (argc < 2) {
printf("Please enter your word key\n");
return 1;
}
char *key = argv[1];
int klen = strlen(key);
// key must be uppercase and we only want row numbers
for (kidx = 0; kidx < klen; ++kidx) {
kval = key[kidx];
base = baseof(kval);
if (base) {
key[kidx] = kval - base;
continue;
}
printf("Key value must be only A-Z\n");
return 1;
}
if (argc < 2)
return 1;
printf("plaintext:");
#if 0
char *word = GetString();
#else
char *word = FakeGetString();
#endif
int wlen = strlen(word);
printf("ciphertext:");
kidx = 0;
// starts loop to repeat following for loop
// iterates through word entered by user as plaintext
// advance to next key char [with wrap to beginning if we're short]
for (widx = 0; widx < wlen; ++widx) {
int wval = word[widx];
int cipher;
base = baseof(wval);
// uppercase or lowercase
if (base) {
kval = key[kidx];
cipher = ((wval - base) + kval) % 26 + base;
kidx = (kidx + 1) % klen;
}
// all other types of characters
else {
cipher = wval;
}
printf("%c",cipher);
}
printf("\n");
return 0;
}
// NOTE: I don't have GetString on my system
char *
FakeGetString(void)
{
static char buf[1000];
char *cp;
fgets(buf,sizeof(buf),stdin);
cp = strchr(buf,'\n');
if (cp != NULL)
*cp = 0;
return buf;
}
那'i'在'for'循环的初始化表达式声明,所以它只有'for'循环内有效......这就是为什么你不能在'do ... while()'条件下测试它。只需在'do ... while()'之前声明它,而不是在'for'的初始化之前。还要记住'for'后的'i'会比通过'for'循环的最后一次更大。 – Dmitri
变量'i'在作用域'for'循环的范围上受到限制。在该循环之外不可访问。如果你想在'do ... while'循环的'while'条件中访问'i',你需要在'do ... while'循环的范围之外定义它(如果你在里面定义它,它会不能在条件下访问;在条件之前,它会在'}处不存在 –
我明白这就是为什么发生这种情况,但我找不到解决方法。每当我重新声明我在任何地方否则在脚本中我会看到一个过度阴影的错误,你能不能再告诉我如何再次表达word [i],以及在哪里这样做,以避免在脚本中出现阴影错误,因为我尝试了所有我能想到的?还有什么是你在底部脚本的我而行的意见。它是另外合适?有另一种方式,我可以表达这种循环到了关键,只要有剩余的字中的字母反复迭代? – Android