无法找出为什么我的程序没有按计划执行

时间:2019-09-13 16:55:19

标签: c cs50 vigenere

作为我目前正在参加的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时不会发生。

3 个答案:

答案 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)

以下建议的代码:

  1. 不使用不可移植的库cs50
  2. 正确地将错误信息输出到stderr
  3. 执行所需的功能
  4. 干净地编译

现在,建议的代码:

#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]);