I'm a beginner-intermediate C++ programmer, and I never used or understood C input & validation. I just always used C++ streams.
Anyway, I just want code critique, as I have never used the C input functions (I admit, I have used and like printf()
! I even made my own sprintf()
, compatible with the C++ string class.)
I hope my code is good. I tend to get code to work properly, completely ignoring formatting and performance, then later once it works I make it look and run nicely.
caesar.c
#include <string.h> /* for strlen() */
#include "caesar.h"
char *getCipherText(char *src, int key) {
int len = strlen(src);
int i = 0;
int ch = 0;
/* Loop over each char in src */
for (i = 0; i < len; i++) {
ch = (int)src[i]; /* Convert the char to int to prevent many uneccecary casts */
if (ch >= 65 && ch <= 90) { /* If the char is uppercase */
ch += key; /* add the key */
if (ch > 90) ch -= 26; /* if the char is higher than the highest uppercase char, sub 26 */
if (ch < 65) ch += 26; /* if the char is lower than the lowest uppercase char, add 26 */
src[i] = (char)ch; /* set the current char in src to the char value of ch */
} else if (ch >= 97 && ch <= 122) { /* else if it's lowercase */
ch += key; /* add the key */
if (ch > 122) ch -= 26; /* if the char is higher than the highest lowercase char, sub 26 */
if (ch < 97) ch += 26; /* if the char is lower than the lowest lowercase char, add 26 */
src[i] = (char)ch; /* set the current char in src to the char value of ch */
}
/* an else case is not needed, since we are modifying the original. */
}
/* Return a pointer to the char array passed to us */
return src;
}
char *getPlainText(char *src, int key) {
/* Since getCipherText adds the key to each char, adding a negative key
* is equivalent to subtracting a positive key. Easier than re-implementing.
*/
return getCipherText(src, -key);
}
caesar.h
char *getCipherText(char *src, int key);
char *getPlainText(char *src, int key);
main.c
#include <stdio.h> /* for printf(), sscanf(), fgetc() and fgets() */
#include <stdlib.h> /* for malloc() and free() */
#include <string.h> /* for strlen() */
#include "caesar.h"
/* Size of text buffer to read into */
#define BUFS 1024
/* Size of buffer for reading misc. items, i.e. for the get_int() function */
#define TBUFS 128
/* Get char, no new lines */
int getc_nnl() {
int ch = '\n';
/* While ch is a newline or carriage return, read another char */
while (ch == '\n' || ch == '\r')
ch = fgetc(stdin);
/* Return the char, promoted to an integer */
return ch;
}
/* Get an integer */
int get_int() {
char *s = (char*)malloc(TBUFS); s[0] = '\0';
int i = 0;
/* Read a string, and later parse the int in case there are no ints to read */
while (strlen(s) <= 1)
fgets(s, TBUFS, stdin);
/* Parse the int. Using sscanf because scanf on stdin leaves the file caret at a unknown position. */
sscanf(s, "%d", &i);
/* Return the int - if sscanf found nothing, it's already 0 */
return i;
}
int main(int argc, char *argv[]) {
char *text = NULL;
int key = 0;
int ch = 0;
while(1) { /* Forever loop, until we break; out */
/* Prompt for an option */
printf("Encrypt, Decrypt, or Quit? (e/d/q) ");
ch = getc_nnl();
/* Make sure they gave us a valid option - if not, keep prompting! */
while (ch != 'e' && ch != 'E' && ch != 'd' && ch != 'D' && ch != 'q' && ch != 'Q') {
printf("Invalid option. Encrypt, Decrypt, or Quit? (e/d/q) ");
ch = getc_nnl();
}
/* If the user wants to quit... */
if (ch == 'q' || ch == 'Q')
break; /* ...then break out of the loop */
/* Allocate buffer for text (I set text[0] to a null-terminator due to later strlen() calls) */
text = (char*)malloc(BUFS); text[0] = '\0';
/* Get the text to encrypt - If user entered nothing,
* or fgets() is reading only a newline (from the fgetc calls), keep reading.
*/
printf("Please enter your text: ");
while (strlen(text) <= 1)
fgets(text, BUFS, stdin);
/* Get the integer key to encrypt/decrypt with. If it's invalid, keep prompting! :) */
printf("Ok, now what key should I use? (1 - 25) ");
key = get_int();
while (key < 1 || key > 25) {
printf("Invalid key. Please enter a number between 1 and 25: ");
key = get_int();
}
/* Ok, we have our data - now, did they say encrypt or decrypt? */
if (ch == 'e' || ch == 'E') {
/* Encrypt, and print the result */
getCipherText(text, key);
printf("Ok. Here's your encrypted text: %s\n", text);
} else if (ch == 'd' || ch == 'D') {
/* Decrypt, and print the result */
getPlainText(text, key);
printf("Ok. Here's your decrypted text: %s\n", text);
}
/* Free our malloc, so we don't have a memory overrun */
free(text);
}
return 0;
}