密码函数在输出的最后一个字符中产生不需要的结果

时间:2017-10-09 03:25:01

标签: c encryption cs50

我一整天都在努力弄清楚我创建的这个加密函数我做错了什么。

该函数通过接收一个关键字然后将其转换为ASCII值然后获取该值并将其格式化为可以使用字母索引eg: A= 0, B= 1, C= 2, etc...然后转换所有纯文本的方式来工作。同样的方法。之后,它会移动纯文本的字符,然后在循环中添加迭代关键字的关键字中的字符值,直到加密纯文本为止。

它适用于我的所有测试,除了像这样的测试:

Keyword is BaZ

输入

plaintext: BaRFoo

输出:

ciphertext: CaQGoh

但所需的输出是

ciphertext: CaQGon

我使用以下加密函数:

void encipher(char* plainText, char*key)
{
    printf("ciphertext: ");
    char alphabeticalIndex[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
    int currentKeyChar = 0;

    for(int i = 0, n = strlen(plainText); i < n; i++)
    {
            // check if the end of they key has been reached, if so then reset it
            if(currentKeyChar >= strlen(key)) currentKeyChar = 0;


            if(isalpha(plainText[i]) == false) printf("%c", plainText[i]);

            if(isupper(plainText[i]))
            {
                // find the cipher character as an int then add it as the key to captialCharNum
                int capitalCipherCharNum = ((int) key[currentKeyChar] - 65);
                int capitalCharNum = (((int) plainText[i] - 65) + capitalCipherCharNum) % 26;

                printf("%c", toupper(alphabeticalIndex[capitalCharNum]));
            }

            if(islower(plainText[i]))
            {
                // same as it was for capitals but in this case its lowercase
                int lowerCipherCharNum = ((int) key[currentKeyChar] - 97);
                int lowerCharNum = (((int) plainText[i] - 97) + lowerCipherCharNum) % 26;

                printf("%c", tolower(alphabeticalIndex[lowerCharNum]));
            }
        currentKeyChar++;
        }

    printf("\n");
}

1 个答案:

答案 0 :(得分:1)

您的错误在这里:

            int lowerCipherCharNum = ((int) key[currentKeyChar] - 97);

key[currentKeyChar] 大写 时,lowerCipherCharNum为否定,导致您的密码值错误。要解决您需要的问题:

            int lowerCipherCharNum;
            if (islower (key[currentKeyChar]))
                lowerCipherCharNum = key[currentKeyChar] - 'a';
            else
                lowerCipherCharNum = key[currentKeyChar] - 'A';

这将更正您的预期输出。

虽然使用数组索引来解决每个字符串没有任何问题,但使用指针算法可以大大简化代码。 (你还需要删除strlen不必要的重复调用(或至少通过计算key的长度而不是每次检查它来最小化。)

使用指针运算如何简化逻辑(以及缩短变量名称因为我不想键入)的示例,您可以执行类似以下操作:

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

void encipher (const char *plaintext, const char *key)
{
    const char *aidx = "abcdefghijklmnopqrstuvwxyz",
               *p = plaintext,
               *k = key;

    printf ("ciphertext: ");

    while (*p) {
        if (isalpha (*p) == 0) printf ("%c", *p);

        if (isupper (*p)) {
            /* find the cipher character as an int then add it as the key */
            int ccicn = (*k - 'A');
            int ccnum = (*p - 'A' + ccicn) % 26;

            putchar (toupper (aidx[ccnum]));
        }

        if (islower (*p)) {
            /* same as it was for capitals but in this case its lowercase */
            int lcicn = islower (*k) ? *k - 'a' : *k - 'A';
            int lcnum = (*p - 'a' + lcicn) % 26;

            putchar (aidx[lcnum]);
        }
        p++;
        if (*k)  k++;
        if (!*k) k = key;
    }
    putchar ('\n');     /* don't use printf for one-character */
}

int main (int argc, char **argv) {

    const char *s   = argc > 1 ? argv[1] : "BaRFoo", 
               *key = argc > 2 ? argv[2] : "BaZ";

    encipher (s, key);

    return 0;
}

示例使用/输出

$ ./bin/encipher
ciphertext: CaQGon

注意:评论/* don't use printf for one-character */

虽然不是错误,但C的标准编码样式避免使用camelCaseMixedCase变量名来支持所有小写,同时保留用于宏和常量的大写名称。这是一个风格问题 - 所以它完全取决于你,但如果不遵循它可能会在某些圈子中产生错误的第一印象。

以下是&#34;编辑过的&#34;你的encipher函数的版本,在评论中有一些额外的想法,代码间隔更宽一些(当你的眼睛变老时,你可能会更加欣赏)

/* if plainText and key are not modified, pass them as 'const char *' */
void encipher (const char *plainText, const char *key)
{
    /* place variables before executed code if you have the option...
     * (just increases portability to older compilers (like Win7))
     */
    char alphabeticalIndex[26] = "abcdefghijklmnopqrstuvwxyz";
    int currentKeyChar = 0;
    size_t keylen = strlen (key);

    printf ("ciphertext: ");

    for (int i = 0, n = strlen (plainText); i < n; i++)
    {
        // check if the end of they key has been reached, if so then reset it
        if (currentKeyChar >= (int)keylen) currentKeyChar = 0;

        if (isalpha (plainText[i]) == 0) putchar (plainText[i]);

        if (isupper (plainText[i]))
        {
            // find the cipher character as an int then add it as the key
            int capitalCipherCharNum = ((int) key[currentKeyChar] - 65);
            int capitalCharNum = (plainText[i] - 65 + capitalCipherCharNum) % 26;

            putchar (toupper (alphabeticalIndex[capitalCharNum]));
        }

        if (islower (plainText[i]))
        {
            // same as it was for capitals but in this case its lowercase
            // int lowerCipherCharNum = ((int) key[currentKeyChar] - 97);
            int lowerCipherCharNum;
            if (islower (key[currentKeyChar]))
                lowerCipherCharNum = key[currentKeyChar] - 'a';
            else
                lowerCipherCharNum = key[currentKeyChar] - 'A';

            int lowerCharNum = (plainText[i] - 97 + lowerCipherCharNum) % 26;

            putchar (tolower (alphabeticalIndex[lowerCharNum]));
        }
        currentKeyChar++;
    }

    putchar ('\n');     /* don't use printf for one-character */
}

仔细看看,如果您有其他问题,请告诉我。