简体   繁体   中英

What's wrong with my cs50 vigenere code? I am close on the output

I have spent hours on this and I am still stuck. I am getting the following output when I do my check. Do the errors have something to do with the way I am printing it out?

  • :) vigenere.c exists
  • :) vigenere.c compiles
  • :( encrypts "a" as "a" using "a" as keyword \\ expected output, but not "ciphertext: a\ù\ÿ\\n"
  • :) encrypts "barfoo" as "caqgon" using "baz" as keyword
  • :) encrypts "BaRFoo" as "CaQGon" using "BaZ" as keyword
  • :) encrypts "BARFOO" as "CAQGON" using "BAZ" as keyword
  • :( encrypts "world!$?" as "xoqmd!$?" using "baz" as keyword \\ expected output, but not "ciphertext: xoqmd!$?í\\b@\\n"
  • :( encrypts "world, say hello!" as "xoqmd, rby gflkp!" using "baz" as keyword \\ expected output, but not "ciphertext: xoqmd, rby gflkp!^¿µÿ\\n"
  • :) handles lack of argv[1]
  • :) handles argc > 2
  • :) rejects "Hax0r2" as keyword

Here is the code:

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

#define alpha_length 26

char secret(char character, int key);

int main(int argc, string argv[]) {
    //check that there are only two strings
    if (argc != 2) {
        printf("Usage: ./vignere k\n");
        return 1;
    }
    //check that argv1 is alphabetical
    string code = argv[1];
    for (int t = 0; t < strlen(code); t++) {    
        if (!isalpha(code[t])) {
            printf("Alphabetical only!\n");
            return 1;
        }
    }
    //get string from user to encrypt
    printf("plaintext: ");
    string plaintext = get_string();

    //array created out of user inputted plain text
    char cypher[strlen(plaintext)];

    //j counts the number of alphabetical characters so that it resets based on argv length
    int j = 0; 
    //iterate over characters in array.  If they are alpha then apply the function secret
    for (int i = 0; i < strlen(plaintext); i++) {
        if (isalpha(plaintext[i])) {
            int index = j % strlen(code);
            int code_index = toupper(code[index]) - 'A' ;
            cypher[i] = secret(plaintext[i], code_index);
            j = j + 1;
        } else {
            cypher[i] = plaintext[i];
        }
    }
    printf("ciphertext: %s\n", cypher);

    return 0;
}  

char secret (char character, int key) {
    char shift;

    // if the character is upper case then start with uppercase A and shift based on the appropriate character from argv1
    if (isupper(character)) {
        shift = (int)character -'A';
        shift = shift + key;
        shift = (shift % alpha_length) + 'A';
    } else {
        // else start wit lower case a
        shift = (int)character - 'a'; 
        shift = shift + key;
        shift = (shift % alpha_length) + 'a';
    }
    return (char)shift;
}

There are multiple problems in your code:

  • do not use the string typedef from <cs50.h> : it hides the nature of the object you are manipulating, a simple char * pointer which you should learn to master without fear.

  • because type char can be signed by default and have a negative value for which isalpha() is undefined, you should cast the char arguments to these functions as unsigned char : isalpha((unsigned char)code[t])

  • you intend for cypher to be a C string, so you must allocate an extra byte for the null terminator and store it there:

     char cypher[strlen(plaintext) + 1]; 
  • cipher is spelled with an i .

Here is a modified version:

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

#define alpha_length 26

char secret(char character, int key);

int main(int argc, char *argv[]) {
    //check that there are only two strings
    if (argc != 2) {
        printf("Usage: ./vignere k\n");
        return 1;
    }
    //check that argv1 is alphabetical
    char *code = argv[1];
    int code_len = strlen(code);
    for (int t = 0; t < code_len; t++) {    
        if (!isalpha((unsigned char)code[t])) {
            printf("Alphabetical only!\n");
            return 1;
        }
    }
    //get string from user to encrypt
    printf("plaintext: ");
    char *plaintext = get_string();
    int text_len = strlen(plaintext);

    //array created out of user inputted plain text
    char cipher[text_len + 1];

    //j counts the number of alphabetical characters so that it resets based on argv length
    int j = 0; 
    //iterate over characters in array.  If they are alpha then apply the function secret
    for (int i = 0; i < text_len; i++) {
        if (isalpha((unsigned char)plaintext[i])) {
            int index = j % code_len;
            int code_index = toupper((unsigned char)code[index]) - 'A';
            cipher[i] = secret(plaintext[i], code_index);
            j = j + 1;
        } else {
            cipher[i] = plaintext[i];
        }
    }
    cipher[text_len] = '\0';
    printf("ciphertext: %s\n", cipher);

    return 0;
}  

char secret (char character, int key) {
    int shift;

    // if the character is upper case then start with uppercase A and shift based on the appropriate character from argv1
    if (isupper((unsigned char)character)) {
        shift = (int)character - 'A';
        shift = shift + key;
        return 'A' + (shift % alpha_length);
    } else {
        // else start with lower case a
        shift = (int)character - 'a'; 
        shift = shift + key;
        return 'a' + (shift % alpha_length);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM