Reputation:
I'm having a problem with CS50's substitution cipher problem. I'm stuck on how to validate the key. Whenever I pass a 26 character key as a command-line argument, the program outputs "you must not repeat any characters" even when the key doesn't have any. My program correctly checks for the length of the key and the presence of a command-line argument. It just doesn't acknowledge a valid nonrepeating key.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
bool validateKey(char key[]);
string substitute(char key[], string plaintext);
int main(int argc, string argv[]) {
if(strlen(argv[1]) == 26) { //key typed after prgm name will be used to encrypt data
if(validateKey(argv[1])) {
string plaintext = get_string("Plaintext: ");
string ciphertext = substitute(argv[1], plaintext);
printf("Ciphertext: %s", ciphertext);
}
}
else if(argv[1] == NULL) {
printf("Usage: ./substitution key\n");
}
else {
printf("Key must contain 26 characters.\n");
}
}
bool validateKey(char key[]) {
for(int i = 0; i < 26; i++) {
if(!isalpha(key[i])) {
printf("Key must only contain alphabetic characters.\n");
return false;
}
}
/*
an array of counters to keep track of how many times a letter occurs in the cipher
each counter should be set to 1 if key doesn't have repeating letters
*/
int cntr[26] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
for (int i = 0; i < 26; i++) {
key[i] = islower(key[i]); //make all the letters in the key lowercase to make it easier to work with
switch(key[i]) {
case 'a':
cntr[0] += 1;
case 'b':
cntr[1] += 1;
case 'c':
cntr[2] += 1;
case 'd':
cntr[3] += 1;
case 'e':
cntr[4] += 1;
case 'f':
cntr[5] += 1;
case 'g':
cntr[6] += 1;
case 'h':
cntr[7] += 1;
case 'i':
cntr[8] += 1;
case 'j':
cntr[9] += 1;
case 'k':
cntr[10] += 1;
case 'l':
cntr[11] += 1;
case 'm':
cntr[12] += 1;
case 'n':
cntr[13] += 1;
case 'o':
cntr[14] += 1;
case 'p':
cntr[15] += 1;
case 'q':
cntr[16] += 1;
case 'r':
cntr[17] += 1;
case 's':
cntr[18] += 1;
case 't':
cntr[19] += 1;
case 'u':
cntr[20] += 1;
case 'v':
cntr[21] += 1;
case 'w':
cntr[22] += 1;
case 'x':
cntr[23] += 1;
case 'y':
cntr[24] += 1;
case 'z':
cntr[25] += 1;
}
}
for(int i = 0; i < 26; i++) {
if(cntr[i] != 1) {
printf("Key must not contain repeated characters.\n");
return false;
}
}
return true;
}
string substitute(char key[]) {
return "";
}
Upvotes: 1
Views: 75
Reputation: 155604
The "minimal" fix is to add a break
after each increment, so your case 'a'
doesn't execute the code for case 'b'
and onwards. You'd also need to change the islower
call to tolower
(otherwise all your key values just become 0
and 1
).
That said, the switch
statement itself is already ridiculously overlong, and should really just be simplified to the one-liner:
cntr[tolower(key[i]) - 'a'] += 1;
which is safe, since you've already checked all the input characters pass isalpha
.
Upvotes: 2