CS50 Caesar Cipher che fornisce un output errato (pset2)

Aug 24 2020

Sto cercando di implementare un programma che crittografa i messaggi utilizzando la cifratura di Cesare. Ho una sorta di errore logico nel mio codice e mi sto tirando i capelli cercando di trovarlo. La logica ha senso per me, ma continuo a ricevere un output sbagliato. Per favore, qualcuno può guidarmi con questo problema!

#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;
    }

}

Risposte

2 Barmar Aug 24 2020 at 20:46

Il codice che esegue la crittografia non dovrebbe essere all'interno del ciclo che controlla che tutti i caratteri in argv[1]sono cifre. Per prima cosa esegui il ciclo che convalida la chiave. Se ha successo, chiedi il testo in chiaro ed esegui la crittografia.

Il principale errore logico è che hai plaintext[i]in un certo numero di posti. Dovrebbe essere 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;
    }
}

Non è inoltre necessario annidare i controlli isupper()e islower()all'interno isalpha(). Basta usare else ifper testare le 3 condizioni che si escludono a vicenda: lettera maiuscola, lettera minuscola, tutto il resto.

Ed evita i codici ASCII hard-coding, usa i caratteri letterali.