This code is tested and working properly, I'm looking for some feedback on the following functions. Pretty straight forward and simple, but if additional information is desired, ask and I will gladly oblige. Comments, suggestions, etc are welcomed.
The following methods are the functional portion of a program that serves as a Vigenere encryption application.
The removeDuplicates
function serves to remove duplicates from the user-entered key phrase, e.g. if infinitestring
was passed in inftesrg
would be returned.
targetFound
serves as a helper for identifying duplicates present as removeDuplicates
builds the final key. I realize it is not completely necessary, but the prototypes were supplied in the project description, and while I did change the return-types and parameters passed, I still decided to use all of the functions specified.
initializeEncryptArray
builds the encryption substitution table, initializeDecryptArray
builds the decryption substitution table, however it dependent on initializeEncryptArray
as the parameters describe. The idea is shown in the following:
key: feather
cipher:
A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z
⇵ ⇵ ⇵ ⇵ ⇵ ⇵ ⇵ ⇵ ⇵ ⇵ ⇵ ⇵ ⇵ ⇵ ⇵ ⇵ ⇵ ⇵ ⇵ ⇵ ⇵ ⇵ ⇵ ⇵ ⇵
F|E|A|T|H|R|Z|Y|X|W|V|U|S|Q|P|O|N|M|L|K|J|I|G|D|C|B
processInput
processes the input file specified by the user, and writes to the output file.
Essentially in main
I parse arguments given at command line, for encrypt/decrypt (e
or d
) options, an input file, and an output file, in the following fashion ./a.out e <key-word> <input-file-name> <output-file-name>
or ./a.out d <key-word> <input-file-name> <output-file-name>
. For the encrypt option, the key is passed to removeDuplicates
to remove duplicate characters. The key (less the duplicate characters) is then passed to initializeEncryptArray
and the rest of the alphabet is appended in reverse order to create the substitution table. The substitution table is then passed to processInput
along with references to the input and output files.
The same sequence happens for the decrypt option, except for after initializeEncryptArray
the result is passed to initializeDecryptArray
instead of processInput
and the resulting table from initializeDecryptArray
is then passed to processInput
along with the references to the input/output files.
p1.c:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include "functions.h"
int main(int argc, char * argv[]){
int MAXNUM = 27;
char * encrypt, * decrypt, * key;
char choice;
FILE * fin, * fout;
//check argument count
if (argc != 5)
errorHandler(0);
choice = toupper(*argv[1]);
key = removeDuplicates(argv[2]);
fin = fopen(argv[3], "r");
fout = fopen(argv[4],"w");
if(fin == NULL || fout == NULL)
errorHandler(3);
encrypt = (char *) malloc (MAXNUM * sizeof(char));
//allocation check
if (encrypt == NULL)
errorHandler(2);
//encrypt option
if (choice == 'E'){
initializeEncryptArray(key, encrypt);
processInput(encrypt, fin, fout);
}
//decrypt option
else if (choice == 'D'){
decrypt = (char *) malloc (MAXNUM * sizeof(char));
if(decrypt == NULL)
errorHandler(2);
initializeEncryptArray(key, encrypt);
initializeDecryptArray(encrypt, decrypt);
processInput(decrypt, fin, fout);
free(decrypt);
}
//invalid choice
else
errorHandler(1);
free(encrypt);
fclose(fin);
fclose(fout);
}
functions.c:
#include "functions.h"
// remove duplicate characters in array word and return the resulting string
char * removeDuplicates(char * word){
char * result;
int len = strlen(word) + 1;
result = malloc (len);
if (result == NULL){
errorHandler(2);
}
char ch;
for(int i = 0, j = 0; i < len; i++){
ch = word[i];
if(!targetFound(result, ch)){
result[j] = ch;
j++;
}
result[j] = '\0';
}
return result;
}
// search the first num characters in array charArray for character target
// return a non-zero integer if found, otherwise, return 0
int targetFound(char * charArray, char target){
int found = 0;
if(strchr(charArray,target))
found = 1;
return found;
}
// initialize the encrypt array with appropriate cipher letters according to the given key
void initializeEncryptArray(char * key, char * encrypt){
char ch;
for (int i = 0, j = 0, flag = 0; j < 27;){
ch = key[i];
if (ch == '\0' || flag == 1){
if(flag == 0)
flag = 1;
ch = 'Z' - j;
j++;
}
if (strchr(encrypt,ch) == NULL){
encrypt[i] = toupper(ch);
i++;
}
}
encrypt[26] = '\0';
printf("Encrypt: %s\n\n", encrypt);
}
// initialize the decrypt array with appropriate cipher letters according to the given key
void initializeDecryptArray(char * encrypt, char * decrypt){
int i;
for ( i = 0; i < 27; i++){
decrypt[encrypt[i] - 'A'] = i + 65;
}
decrypt[26] = '\0';
printf("Decrypt: %s\n\n", decrypt);
}
// process data from the input file and write the result to the output file
// pass the encrypt array to parameter substitute if encryption is intended
// pass the decrypt array to parameter substitute if decryption is intended
void processInput(char * substitute, FILE * fin, FILE * fout){
char ch;
while ( fscanf(fin, "%c", &ch) != EOF ){
if(isupper(ch)){
fprintf(fout, "%c", substitute[ch - 'A']);
}
else if(islower(ch)){
fprintf(fout, "%c", tolower(substitute[ch - 'a']));
}
else
fprintf(fout, "%c", ch);
}
}
// prints errors based on the error code passed in
void errorHandler(int argIndex){
switch(argIndex){
case 0:
printf("Error: Incorrect number of arguments received.\n\tPlease try again using the correct number of args.\n");
case 1:
printf("Error: Invalid program option.\n\tPlease try again using either 'd'/'D' or 'e'/'E'.\n");
case 2:
printf("Error: Memory could not be allocated.\n");
case 3:
printf("Error: Invalid input filename given for input.\n\tPlease use a valid filename for input.\n");
}
exit(1);
}
functions.h
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <string.h>
// remove duplicate characters in array word and return the resulting string
char * removeDuplicates(char * word);
// search the first num characters in array charArray for character target
// return a non-zero integer if found, otherwise, return 0
int targetFound(char * charArray, char target);
// initialize the encrypt array with appropriate cipher letters according to the given key
void initializeEncryptArray(char * key, char * encrypt);
// initialize decrypt array with appropriate substitute letters based on the encrypt array
void initializeDecryptArray(char * encrypt, char * decrypt);
// process data from the input file and write the result to the output file
// pass the encrypt array to parameter substitute if encryption is intended
// pass the decrypt array to parameter substitute if decryption is intended
void processInput(char * substitute, FILE * inf, FILE * outf);
//prints out user-friendly error message
void errorHandler(int errIndex);
#endif //FUNCTIONS_H