作为我目前正在参加的CS50哈佛编程课程的一部分,我正在做一个名为“ Vigenere”的练习。
除了收到以b
开头的输入内容之外,我的程序一切正常(逐行进行,并且符合预期的行为)。
一旦到达输入字符串的末尾,它就不会循环回到数组中的第一个字符,但是,如果输入不是以b开头,它将像应该的那样工作。
一直在进行谷歌搜索,调试,但无法弄清楚。也尝试过以其他许多不同方式进行操作,但我无法使其正常工作。
#include <stdio.h>
#include <cs50.h>
#include <stdlib.h>
#include <ctype.h>
int main(int argc, char *argv[])
{
if (argc != 2)
{
printf("Error.\n");
return (1);
}
string input = argv[1];
for (int i = 0; input[i] != '\0'; i++)
{
if (!isalpha(input[i]))
{
printf("Error.\n");
return (1);
}
}
string plaintext = get_string("plaintext: ");
string cipher = argv[1];
printf("ciphertext: ");
int i = 0;
int j = 0;
int code = 0;
while (plaintext[i] != '\0')
{
if (cipher[j] >= 97)
{
cipher[j] = cipher[j] - 97;
}
if (isupper(cipher[j]))
{
cipher[j] = cipher[j] - 65;
}
if (islower(plaintext[i]))
{
printf("%c", 'a' + (plaintext[i] - 'a' + cipher[j]) % 26);
j++;
}
if (isupper(plaintext[i]))
{
printf("%c", 'A' + (plaintext[i] - 'A' + cipher[j]) % 26);
j++;
}
if (plaintext[i] == ' ')
{
printf("%c", plaintext[i]);
}
if (!isalpha(plaintext[i]) && !isspace(plaintext[i]))
{
printf("%c", plaintext[i]);
}
if (cipher[j] == '\0' && plaintext[i] != ' ')
{
j = 0;
}
i++;
}
printf("\n");
return (0);
}
如上所述,每当我的命令行输入以b开头时,程序均无法按预期运行。当输入不是b时不会发生。
答案 0 :(得分:0)
您在代码中执行的 cipher 操作可能导致 j 始终为零,并导致重复打印第一个字符。
这是由于 ascii->非ascii-> ascii 的行为引起的,这是加密过程中所需的行为
为了解决此问题,您只需要使用 cipher 的值,而无需使用条件中的值。 我所做的是将值复制到另一个 pointer ,并通过保持条件以使用<>引用原始 cipher 的原始 char strong> malloc 和 memset 。
代码:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *input = argv[1];
for (int i = 0; input[i] != '\0'; i++)
{
if (!isalpha(input[i]))
{
printf("Error.\n");
return (1);
}
}
char *plaintext = "aaaaaaa";
char *cipher = argv[1];
//<============================
char *moving_cipher;
moving_cipher = (char *) malloc(3);
memcpy(moving_cipher, cipher, 3);
//<============================
printf("ciphertext: ");
int i = 0;
int j = 0;
int code = 0;
while (plaintext[i] != '\0')
{
if (cipher[j] >= 97)
{
moving_cipher[j] = cipher[j] - 97;
}
if (isupper(cipher[j]))
{
moving_cipher[j] = cipher[j] - 65;
}
if (islower(plaintext[i]))
{
printf("%c", 'a' + (plaintext[i] - 'a' + moving_cipher[j]) % 26);
j++;
}
if (isupper(plaintext[i]))
{
printf("%c", 'A' + (plaintext[i] - 'A' + moving_cipher[j]) % 26);
j++;
}
if (plaintext[i] == ' ')
{
printf("%c", plaintext[i]);
}
if (!isalpha(plaintext[i]) && !isspace(plaintext[i]))
{
printf("%c", plaintext[i]);
}
if (cipher[j] == '\0' && plaintext[i] != ' ')
{
j = 0;
}
i++;
}
printf("\n");
return (0);
}
注意: 我检查了您在评论中写的有问题的输入,这就是为什么您需要以明智的原因而不是硬编码来找到所需的大小。
输入:“巴兹”
修复前的输出:“ bazbbbb”
修复后的输出:“ bazbazb”
答案 1 :(得分:0)
以下建议的代码:
cs50
stderr
现在,建议的代码:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf( stderr, "USAGE: %s cypherKey\n", argv[0] );
exit( EXIT_FAILURE );
}
// implied else, user entered correct number of parameters
char * cipher = argv[1];
for (int i = 0; cipher[i] != '\0'; i++)
{
if (!isalpha( cipher[i]))
{
fprintf( stderr, "key must be all alphabetic characters\n");
exit( EXIT_FAILURE );
}
}
// implied else, key all alphabetic characters
char plaintext[1024];
puts( "Please enter the plain text" );
if( !fgets( plaintext, sizeof(plaintext), stdin ) )
{
perror( "fgets to input plain text failed" );
exit( EXIT_FAILURE );
}
//implied else, fgets successful
// remove possible trailing newline
plaintext[ strcspn( plaintext, "\n" ) ] = '\0';
printf("ciphertext: ");
for( int j = 0, i = 0; plaintext[i]; i++ )
{
if (cipher[j] >= 97)
{
cipher[j] = (char)(cipher[j] - 97);
}
if (isupper(cipher[j]))
{
cipher[j] = (char)(cipher[j] - 65);
}
if (islower(plaintext[i]))
{
printf("%c", 'a' + (plaintext[i] - 'a' + cipher[j]) % 26);
j++;
}
if (isupper(plaintext[i]))
{
printf("%c", 'A' + (plaintext[i] - 'A' + cipher[j]) % 26);
j++;
}
if (plaintext[i] == ' ')
{
printf("%c", plaintext[i]);
}
if (!isalpha(plaintext[i]) && !isspace(plaintext[i]))
{
printf("%c", plaintext[i]);
}
if (cipher[j] == '\0' && plaintext[i] != ' ')
{
j = 0;
}
}
printf("\n");
return (0);
}
以下是该程序的一些典型运行
./无标题的可执行文件
./untitled
USAGE: ./untitled cypherKey
./untitled abcd
Please enter the plain text
This is a plain text message
ciphertext: Tikv it c slbkq tfzw mfuvahg
./untitled bcda
Please enter the plain text
This is a plain text message
ciphertext: Ujls ju d qndjp wfzw ngvtcjf
答案 2 :(得分:-1)
由于您将cipher[j]
中的字符从ASCII码更改为索引到“ ABC ... XYZ”,因此以下比较无法检测到键码的结尾:
if (cipher[j] == '\0' ...
“ A”或“ a”将变为值0,与“ \ 0”相同。因此,引起此问题的不是前导“ b”而是后继“ a”。
将其放在循环中的重要位置,您将立即看到它:
printf("%d %d %02X %02X\n", i, j, cipher[j], plaintext[i]);