C语言 字符串中的大写字符不能转换为小写,减去它们的 ASCII 值不会使它们成为按字母顺序排列的索引



我是一个尝试学习编码的初学者。 目前我正在做CS50课程。我遇到了维杰尼雷密码问题;请在下面的GitHub链接上查看我的代码。

#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ASCII_VALUE_LOWER 97
#define ASCII_VALUE_UPPER 65
#define NR_OF_LETTERS 26
int main(int argc, string argv[])
{
char key[strlen(argv[1]) + 1];
strcpy(key, argv[1]);
int keyLen = strlen(key);
for (int k = 0; k < keyLen; k++)
{
if (!isalpha(key[k]))
{
printf("ERROR: Secret key has to be alphabetical string, program will be terminated now!n");
return 1; // main should return 1 (signify an error)
}
//converting key letters to respective values
if (isupper(key[k]))
{
key[k] -= ASCII_VALUE_UPPER;
}
key[k] -= ASCII_VALUE_LOWER;
}
//if program is executed without an argument, or with more than one arguments
if (argc != 2)
{
printf("ERROR: You need to give a secret key as an argument, program will be terminated now!n");
return 1; // main should return 1 (signify an error)
}
else
{
string plaintext = get_string("plaintext: "); //get a plaintext from a user using cs50 custom function from their library
int stringLen = strlen(plaintext);
int keyIndex = 0;
for (int j = 0; j < keyLen; j++)
{
}
//for each character in the plaintext string
for (int i = 0; i < stringLen; i++)
{
//check if is alphabetic (tolower, toupper)
if (isalpha(plaintext[i]))
{
//cypher_character = (plain_character + key_character)% 26
if (islower(plaintext[i]))
{
keyIndex %= keyLen;
plaintext[i] = ((plaintext[i] - ASCII_VALUE_LOWER + key[keyIndex]) % NR_OF_LETTERS) + ASCII_VALUE_LOWER;
}
else
{
plaintext[i] = ((plaintext[i] - ASCII_VALUE_UPPER + key[keyIndex]) % NR_OF_LETTERS) + ASCII_VALUE_UPPER;
}
keyIndex++;
}
//else leave as is
}
//print ciphertext in a format "ciphertext: " + ciper
printf("ciphertext: %sn", plaintext);
return 0;
}
}

这些问题如下:

  1. 如果在键中以大写字母传递参数,则值很奇怪,转换不起作用。这个想法是将字符串键中的每个字符都取为大写,如果大写则减去 65,如果小写则减去 97,因此它们的 ASCII 值将变为 0 - 25。然后,我可以在Vigenere密码公式中使用它们:cipher[i_index] = (plaintext[i_index] + key[j_index]) % 26

  2. 不处理缺乏argv[1],即使有一个IF条件(!argc == 2),所以如果你不通过任何东西,它不应该通过。

    "failed to execute program due to segmentation fault".
    

我已经尽我所能尝试了一切,我很累,也许明天解决方案会立即弹出。 我请你给我一些提示,可能没有透露一切,但可能会指导我,这样我就可以从中学习。

if (isupper(key[k]))
{
key[k] -= ASCII_VALUE_UPPER;
}
key[k] -= ASCII_VALUE_LOWER;

如果字符为大写,则减去ASCII_VALUE_UPPER。然后,无论如何,它都会减去ASCII_VALUE_LOWER.从周围的代码中,我假设你的意思是:

if (isupper(key[k])) {
key[k] -= ASCII_VALUE_UPPER;
} else {
key[k] -= ASCII_VALUE_LOWER;
}

正如其他人所建议的那样,一切都已修复,如果有人好奇错误到底在哪里:

1.] 纳皮尔@Rob指出的错误

for (int i = 0; i < stringLen; i++)
{
//check if is alphabetic (tolower, toupper)
if (isalpha(plaintext[i]))
{
keyIndex %= keyLen; // makes sure that keyIndex doesnt exceeds actual string length
//cypher_character = (plain_character + key_character)% 26
if (islower(plaintext[i]))
{
plaintext[i] = ((plaintext[i] - ASCII_VALUE_LOWER + key[keyIndex]) % NR_OF_LETTERS) + ASCII_VALUE_LOWER;
}
else
{
plaintext[i] = ((plaintext[i] - ASCII_VALUE_UPPER + key[keyIndex]) % NR_OF_LETTERS) + ASCII_VALUE_UPPER;
}
keyIndex++;
}
//else leave as is
}

keyIndex %= keyLen; 被放置在它下面的 if 条件内,因此它不会在 FOR 循环的每次迭代中执行。

2.]@Joe法雷尔回答: 因为当我检查 argc 是否 != 2 时,我已经访问了 argv[1],从而假设 argc>= 2。如果调用方没有提供参数,则 argv[1] 已经过了数组的末尾,计算该表达式会导致未定义的行为。- 所以我将 if 条件作为主要的第一件事。

最新更新