誤った出力を与えるCS50シーザー暗号(pset2)

Aug 24 2020

シーザー暗号を使用してメッセージを暗号化するプログラムを実装しようとしています。コードにある種の論理エラーがあり、それを見つけようとして髪を引っ張っています。ロジックは私には理にかなっていますが、間違った出力を取得し続けます。誰かがこの問題について私を案内してくれませんか?

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

int main(int argc, string argv[])
{
    //Check that program was run with one command-line argument
    if (argc == 2)
    {
       int n = strlen(argv[1]);

       //Iterate over the provided argument to make sure all characters are digits

       for (int i = 0; i < n; i++) {

           if (isdigit(argv[1][i])) {
               //Convert that command-line argument from a string to an int
             //  int key = atoi(argv[1]);
                   int key = atoi(argv[1]);
                //Prompt user for plaintext
                string plaintext = get_string("Enter plain text: ");
                printf("ciphertext: ");

                //int l = strlen(plaintext);
                //Iterate over each character of the plaintext:
                for (int j = 0, l=strlen(plaintext); j < l; j++) {

                if (isalpha(plaintext[j])) {

                    if (isupper(plaintext[j])) {

                         printf("%c", (((plaintext[i] - 65) + key) % 26) + 65);
                    }
                    if (islower(plaintext[j])) {
                         printf("%c", (((plaintext[i] - 97) + key) % 26) + 97);
                    }

                  }
                  else
                    {
                         printf("%c", plaintext[i] );
                    }
                }
                printf("\n");
                return 0;
           }
           else {
                printf("Usage: ./caesar key\n");
                return 1;
           }
       }
    }
    else
    {
         printf("Usage: ./caesar key\n");
         return 1;
    }

}

回答

2 Barmar Aug 24 2020 at 20:46

暗号化を実行するコードは、のすべての文字argv[1]が数字であることを確認するループ内にあるべきではありません。まず、キーを検証するループを実行します。それが成功した場合は、平文を尋ねて暗号化を実行します。

主な論理的エラーは、あなたがplaintext[i]多くの場所にいるということです。それはあるはずですplaintext[j]

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

int main(int argc, string argv[])
{
    //Check that program was run with one command-line argument
    if (argc == 2)
    {
        int n = strlen(argv[1]);

        //Iterate over the provided argument to make sure all characters are digits
        for (int i = 0; i < n; i++) {
            if (!isdigit(argv[1][i])) {
                printf("Error: Key must be numeric");
                return 1;
            }
        }

        //Convert that command-line argument from a string to an int
        int key = atoi(argv[1]);

        //Prompt user for plaintext
        string plaintext = get_string("Enter plain text: ");
        printf("ciphertext: ");

        //Iterate over each character of the plaintext:
        for (int j = 0, l=strlen(plaintext); j < l; j++) {
            if (isupper(plaintext[j])) {
                printf("%c", (((plaintext[j] - 'A') + key) % 26) + 'A');
            } else if (islower(plaintext[j])) {
                printf("%c", (((plaintext[j] - 'a') + key) % 26) + 'a');
            } else {
                printf("%c", plaintext[j] );
            }
        }
        printf("\n");
        return 0;
    } else {
        printf("Usage: ./caesar key\n");
        return 1;
    }
}

をネストして内部isupper()islower()チェックする必要もありませんisalpha()else if大文字、小文字、その他すべての3つの相互に排他的な条件をテストするために使用するだけです。

また、ASCIIコードのハードコーディングは避け、文字リテラルを使用してください。