Vigenere Cipher

2019-09-24 06:53发布

问题:

I am trying to make Vigenere Cipher in C. https://www.youtube.com/watch?v=9zASwVoshiM this is info about Vigenere Cipher. My code works doesnt work for certain cases like encrypts "world, say hello!" as "xoqmd, rby gflkp!" using "baz" as keyword instead it encrypts it as xomd, szz fl. Another example is: encrypts "BaRFoo" as "CaQGon" using "BaZ" as keyword but instead it encrypts it as CakGo. My code is given below please help me out:

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

int main(int argc, string argv[]) {
    //string plaintext;

    string key;
    if (argc != 2) {
        printf("Please run the programme again this time using a command line argument!\n");
        return 1;
    }
    key = argv[1];
    int keys[strlen(key)];

    for (int m = 0; m< strlen(key); m++) {
        if (isalpha(key[m]) == false) {
            printf("Re-Run The programme without any symbols.\n");
            return 1;
        }
    }

    for (int b = 0; b < strlen(key); b++) {
        if (isupper(key[b]) == false) {
            keys[b] = key[b] - 'a';
        }
        else {
            keys[b] = key[b] - 'A';
        }
    }

    //printf("Enter a string which should be encrypted: \n");
    string plaintext = GetString();
    int plength = strlen(plaintext);
    int klength = strlen(key);
    string ciphertext = key;

    for (int u = 0; u<plength; u++) {

        if (isalpha(plaintext[u]) == false) {
            printf("%c", plaintext[u]);
            continue;
        }

        int value = u % klength;
        ciphertext[u] = (keys[value] + plaintext[u]);
        if ((islower(plaintext[u])) && (ciphertext[u])>'z') {
            ciphertext[u] = ciphertext[u] - 'z' + 'a' - 1;
        }

        if ((isupper(plaintext[u])) && (ciphertext[u])>'z') {
            ciphertext[u] = ciphertext[u] - 'Z' + 'A' - 1;
        }

        printf("%c", ciphertext[u]);
    }

    printf("\n");

    return 0;
}

回答1:

string ciphertext = key;

ciphertext should start out as blank, it should not be set to key.

ciphertext[u] = ciphertext[u] - 'z' + 'a' - 1;

This is not correct because ciphertext[u] can go out of range. Character should be between 'a' to 'z'. Use the mod % operator to make sure character is within range. For example:

int j = 0;
for (int u = 0; u<plength; u++) 
{
    int c = plaintext[u];
    if (isalpha(plaintext[u])) 
    {
        int k = keys[j % klength];
        if (islower(c))
        {
            c = 'a' + (c - 'a' + k) % 26;
        }
        else
        {
            c = 'A' + (c - 'A' + k) % 26;
        }
        j++;
    }
    ciphertext[u] = c;
}
printf("%s\n", ciphertext);


回答2:

Lots of little issues (ciphertext needs to be allocated dynamically and start out as a copy of plaintext, not key; need to mod calculations to the length of the alphabet; incorrect calculations; print errors to stderr) and lots of little optimizations that can be made (combine loops; combine if clauses; save key length to a variable earlier). A rework of your code:

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

int main(int argc, string argv[]) {

    if (argc != 2) {
        fprintf(stderr, "Please run the program again with a command line argument!\n");
        return 1;
    }

    string key = argv[1];
    int key_length = strlen(key);
    int keys[key_length];

    for (int i = 0; i < key_length; i++) {
        if (!isalpha(key[i])) {
            fprintf(stderr, "Re-run The program without any symbols.\n");
            return 1;
        }

        keys[i] = toupper(key[i]) - 'A';
    }

//  printf("Enter a string which should be encrypted: \n");

    string plaintext = GetString();
    int text_length = strlen(plaintext);
    string ciphertext = strcpy(malloc(text_length + 1), plaintext);

    for (int i = 0, j = 0; i < text_length; i++) {
        if (!isalpha(plaintext[i])) {
            continue;
        }

        int index = j++ % key_length;

        ciphertext[i] = (toupper(plaintext[i]) - 'A' + keys[index]) % (1 + 'Z' - 'A');

        ciphertext[i] += isupper(plaintext[i]) ? 'A' : 'a';
    }

    printf("%s\n", ciphertext);

    free(ciphertext);

    return 0;
}

Encrypts "world, say hello!" as "xoqmd, rby gflkp!" with key "baz"

Encrypts "BaRFoo" as "CaQGon" with key "BaZ"