为什么循环有问题(pset2 替换)
Why the loops has a problem (pset2 Substitution)
我一直在进行 CS50X pset2 替换。我认为它几乎已经完成了。当我输入单个字符时,例如 A
或 B
D
等等......密文将得到正确的结果。 (例如 A
将得到 J
,"B" 将得到 T
,D
将得到 E
等等...
但是,如果我输入ABC
,密文只会显示J
,其他的不能显示。我做错了什么?
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int ciphertext = 0;
//Key
//JTREKYAVOGDXPSNCUIZLFBMWHQ
int main(int argc, string argv[])
{
//Check that program was run with one command-line argument
if (argc == 2)
{
string key = argv[1];
//check the key does it validate
for (int i = 0, n = strlen(key); i < n; i++)
{
string plaintext = get_string("plaintext: ");
printf("ciphertext: \n");
int u = 64;
for (int k = 0, p = strlen(plaintext); k < p; k++)
{
if (isupper(plaintext[k]) != 0)
{
for (int j = 0; j < 26; j++)
{
u = u + 1;
//printf("u is %c\n", u);
if (u == plaintext[k])
{
ciphertext = key[j];
printf("Key is %c\n", key[j]);
printf("Plaintext is %c\n", plaintext[k]);
printf("ciphertext is %c\n", ciphertext);
//break;
}
}
}
else
{
printf("%c", plaintext[k]);
}
}
return 0;
}
}
}
您的问题是逻辑错误,似乎是由于您试图对失控的代码进行更改而导致的。您的代码中有不必要的循环和未使用的变量。您需要更改 u
声明的范围,以便在每次迭代时重新初始化它。您只需要完全删除 for (int i = 0, n = strlen(key); i < n; i++)
循环,既不使用 i
也不使用 n
。 ciphertext
和 l
(ell) 相同。
您需要在 if (isupper(plaintext[k]))
之后立即移动 int u = 64;
,以便在每次迭代时重置它。
我怀疑所有 printf
语句都是为了调试,你真的只想要 key
输出。总而言之,您可以将代码重新排列为:
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int main (int argc, string argv[]) {
if (argc == 2) { /* validate key given */
string key = argv[1];
string plaintext = get_string("plaintext: ");
printf("ciphertext: ");
for (int k = 0, p = strlen(plaintext); k < p; k++)
{
if (isupper(plaintext[k]))
{
int u = 64;
for (int j = 0; j < 26; j++)
{
u = u + 1;
if (u == plaintext[k]) {
printf("%c", key[j]);
break;
}
}
}
else
printf("%c", plaintext[k]);
}
putchar ('\n');
}
}
例子Use/Output
$ ./bin/cs50_cypher2 JTREKYAVOGDXPSNCUIZLFBMWHQ
plaintext: ABD
ciphertext: JTE
简化你的逻辑
如果你仔细想想上面的代码实际上在做什么,它可以简化为:
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main (int argc, string argv[]) {
if (argc < 2) { /* validate key given */
fputs ("usage: ./program key\n", stderr);
return 1;
}
string key = argv[1];
string plaintext = get_string("plaintext: ");
printf("ciphertext: ");
for (int k = 0, p = strlen(plaintext); k < p; k++)
{
if (isupper(plaintext[k]))
putchar (key[plaintext[k] - 'A']);
else
putchar (plaintext[k]);
}
putchar ('\n');
}
或者,如果您使用 三元 运算符,您的 for
循环将简化为:
for (int k = 0, p = strlen(plaintext); k < p; k++)
putchar (isupper(plaintext[k]) ? key[plaintext[k] - 'A'] : plaintext[k]);
并且由于不需要调用 strlen(plaintext)
,您可以完全消除 string.h
并只循环 for (int k = 0; plaintext[k]; k++)
因为 plaintext
是一个以 nul 结尾的字符串,您的整个程序可以减少到:
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
int main (int argc, string argv[]) {
if (argc < 2) { /* validate key given */
fputs ("usage: ./program key\n", stderr);
return 1;
}
string key = argv[1];
string plaintext = get_string("plaintext : ");
printf("ciphertext: ");
for (int k = 0; plaintext[k]; k++)
putchar (isupper(plaintext[k]) ? key[plaintext[k] - 'A'] : plaintext[k]);
putchar ('\n');
}
处理小写字母[=78=]
您知道您输入的 key
作为第一个参数全部大写。因此,如果要输出小写 key
,则必须在应用偏移量后对键调用 tolower()
。由于对于大写字母,您只想知道要使用的 26 个字符键内的偏移量,您只需找出当前字母来自 'A'
的多少个字母,然后在 key[]
中获取该偏移量,例如
key[plaintext[k] - 'A']
对于小写输入,需要在key
中找出小写字母差异的偏移量,然后将tolower()
应用于key,例如
tolower(key[plaintext[k] - 'a'])
总而言之,您的 for
循环可以写成:
for (int k = 0; plaintext[k]; k++) {
if (isupper(plaintext[k]))
putchar (key[plaintext[k] - 'A']);
else if (islower(plaintext[k]))
putchar (tolower(key[plaintext[k] - 'a']));
else
putchar (plaintext[k]);
}
例子Use/Output
$ ./bin/cs50_cypher4 JTREKYAVOGDXPSNCUIZLFBMWHQ
plaintext : AbZ 50
ciphertext: JtQ 50
检查一下,如果您还有其他问题,请告诉我。
我也尝试检测低调,但结果不是我想要的。我输入"AbZ 50"。假设答案是"JtQ 50"。然而,它是"JTQ 50"
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int main (int argc, string argv[]) {
if (argc == 2) { /* validate key given */
string key = argv[1];
string plaintext = get_string("plaintext: ");
printf("ciphertext: ");
for (int k = 0, p = strlen(plaintext); k < p; k++)
{
if (isupper(plaintext[k]))
{
int u = 64;
for (int j = 0; j < 26; j++)
{
u = u + 1;
if (u == plaintext[k]) {
printf("%c", key[j]);
break;
}
}
}
else if (islower(plaintext[k]))
{
int l = 96;
for (int j = 0; j < 26; j++)
{
l = l + 1;
if (l == plaintext[k]) {
printf("%c", key[j]);
break;
}
}
}
else
printf("%c", plaintext[k]);
}
putchar ('\n');
}
}
我一直在进行 CS50X pset2 替换。我认为它几乎已经完成了。当我输入单个字符时,例如 A
或 B
D
等等......密文将得到正确的结果。 (例如 A
将得到 J
,"B" 将得到 T
,D
将得到 E
等等...
但是,如果我输入ABC
,密文只会显示J
,其他的不能显示。我做错了什么?
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int ciphertext = 0;
//Key
//JTREKYAVOGDXPSNCUIZLFBMWHQ
int main(int argc, string argv[])
{
//Check that program was run with one command-line argument
if (argc == 2)
{
string key = argv[1];
//check the key does it validate
for (int i = 0, n = strlen(key); i < n; i++)
{
string plaintext = get_string("plaintext: ");
printf("ciphertext: \n");
int u = 64;
for (int k = 0, p = strlen(plaintext); k < p; k++)
{
if (isupper(plaintext[k]) != 0)
{
for (int j = 0; j < 26; j++)
{
u = u + 1;
//printf("u is %c\n", u);
if (u == plaintext[k])
{
ciphertext = key[j];
printf("Key is %c\n", key[j]);
printf("Plaintext is %c\n", plaintext[k]);
printf("ciphertext is %c\n", ciphertext);
//break;
}
}
}
else
{
printf("%c", plaintext[k]);
}
}
return 0;
}
}
}
您的问题是逻辑错误,似乎是由于您试图对失控的代码进行更改而导致的。您的代码中有不必要的循环和未使用的变量。您需要更改 u
声明的范围,以便在每次迭代时重新初始化它。您只需要完全删除 for (int i = 0, n = strlen(key); i < n; i++)
循环,既不使用 i
也不使用 n
。 ciphertext
和 l
(ell) 相同。
您需要在 if (isupper(plaintext[k]))
之后立即移动 int u = 64;
,以便在每次迭代时重置它。
我怀疑所有 printf
语句都是为了调试,你真的只想要 key
输出。总而言之,您可以将代码重新排列为:
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int main (int argc, string argv[]) {
if (argc == 2) { /* validate key given */
string key = argv[1];
string plaintext = get_string("plaintext: ");
printf("ciphertext: ");
for (int k = 0, p = strlen(plaintext); k < p; k++)
{
if (isupper(plaintext[k]))
{
int u = 64;
for (int j = 0; j < 26; j++)
{
u = u + 1;
if (u == plaintext[k]) {
printf("%c", key[j]);
break;
}
}
}
else
printf("%c", plaintext[k]);
}
putchar ('\n');
}
}
例子Use/Output
$ ./bin/cs50_cypher2 JTREKYAVOGDXPSNCUIZLFBMWHQ
plaintext: ABD
ciphertext: JTE
简化你的逻辑
如果你仔细想想上面的代码实际上在做什么,它可以简化为:
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main (int argc, string argv[]) {
if (argc < 2) { /* validate key given */
fputs ("usage: ./program key\n", stderr);
return 1;
}
string key = argv[1];
string plaintext = get_string("plaintext: ");
printf("ciphertext: ");
for (int k = 0, p = strlen(plaintext); k < p; k++)
{
if (isupper(plaintext[k]))
putchar (key[plaintext[k] - 'A']);
else
putchar (plaintext[k]);
}
putchar ('\n');
}
或者,如果您使用 三元 运算符,您的 for
循环将简化为:
for (int k = 0, p = strlen(plaintext); k < p; k++)
putchar (isupper(plaintext[k]) ? key[plaintext[k] - 'A'] : plaintext[k]);
并且由于不需要调用 strlen(plaintext)
,您可以完全消除 string.h
并只循环 for (int k = 0; plaintext[k]; k++)
因为 plaintext
是一个以 nul 结尾的字符串,您的整个程序可以减少到:
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
int main (int argc, string argv[]) {
if (argc < 2) { /* validate key given */
fputs ("usage: ./program key\n", stderr);
return 1;
}
string key = argv[1];
string plaintext = get_string("plaintext : ");
printf("ciphertext: ");
for (int k = 0; plaintext[k]; k++)
putchar (isupper(plaintext[k]) ? key[plaintext[k] - 'A'] : plaintext[k]);
putchar ('\n');
}
处理小写字母[=78=]
您知道您输入的 key
作为第一个参数全部大写。因此,如果要输出小写 key
,则必须在应用偏移量后对键调用 tolower()
。由于对于大写字母,您只想知道要使用的 26 个字符键内的偏移量,您只需找出当前字母来自 'A'
的多少个字母,然后在 key[]
中获取该偏移量,例如
key[plaintext[k] - 'A']
对于小写输入,需要在key
中找出小写字母差异的偏移量,然后将tolower()
应用于key,例如
tolower(key[plaintext[k] - 'a'])
总而言之,您的 for
循环可以写成:
for (int k = 0; plaintext[k]; k++) {
if (isupper(plaintext[k]))
putchar (key[plaintext[k] - 'A']);
else if (islower(plaintext[k]))
putchar (tolower(key[plaintext[k] - 'a']));
else
putchar (plaintext[k]);
}
例子Use/Output
$ ./bin/cs50_cypher4 JTREKYAVOGDXPSNCUIZLFBMWHQ
plaintext : AbZ 50
ciphertext: JtQ 50
检查一下,如果您还有其他问题,请告诉我。
我也尝试检测低调,但结果不是我想要的。我输入"AbZ 50"。假设答案是"JtQ 50"。然而,它是"JTQ 50"
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int main (int argc, string argv[]) {
if (argc == 2) { /* validate key given */
string key = argv[1];
string plaintext = get_string("plaintext: ");
printf("ciphertext: ");
for (int k = 0, p = strlen(plaintext); k < p; k++)
{
if (isupper(plaintext[k]))
{
int u = 64;
for (int j = 0; j < 26; j++)
{
u = u + 1;
if (u == plaintext[k]) {
printf("%c", key[j]);
break;
}
}
}
else if (islower(plaintext[k]))
{
int l = 96;
for (int j = 0; j < 26; j++)
{
l = l + 1;
if (l == plaintext[k]) {
printf("%c", key[j]);
break;
}
}
}
else
printf("%c", plaintext[k]);
}
putchar ('\n');
}
}