Skip to main content
Question Protected by Jamal
Reverted answer invalidations; removed noise; added tags
Source Link
Jamal
  • 35.2k
  • 13
  • 134
  • 238

Learning C, Making a Caesar Cipher program in C

So, wanting to learn at least the basics of C before I continue with C++, I'm writing some small programs to understand it better. (And soon, a small Text-Based Adventure Game, for the purpose of learning how to cope without Objects! LOL)

Anyway, I just want code critique, as I have never used the C input functions (I admit, I have used and like printf()printf()! Even I even made my own sprintf()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 nice. (Andand run nicenicely.)

Here it is! Hope I did well :)caesar.c

UPDATE: Fixed a couple minor bugs

#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);
}

UPDATE 2: Improved code syntax - Thanks for the pointer about char pointers! :)caesar.h

UPDATE 3: Total reconstruction of the syntax, minimizing the code size - Thanks!!!!

char *getCipherText(char *src, int key);
char *getPlainText(char *src, int key);

main.cmain.c

#include <stdio.h> /* for printf(), sscanf(), fgetc() and fgets() */
#include <stdio<stdlib.h>
  /* for malloc() and free() */
#include <stdlib<string.h>
  /* for strlen() */
#include <ctype"caesar.h>h"

/* Size of text intbuffer encodeto read into */
#define BUFS 1024

/* Size of buffer for reading misc. items, i.e. for the get_int(int) chfunction */
#define TBUFS 128

/* Get char, no new lines */
int keygetc_nnl() {
    int ch = '\n';
     
    /* While ch is ifa (islowernewline 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 ch*s = (ch-'a'char*)malloc(TBUFS); +s[0] key)= %'\0';
 26 + 'a'; int i = 0;
    /* Read a string, and later parse the int in case there are no ints to chread +=*/
    while (chstrlen(s) <<= 'a'1) ? 
 26 : 0;     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);
     
   else /* Return the int - if (isuppersscanf found nothing, it's already 0 */
    return i;
}

int main(ch)int argc, char *argv[]) {
     char *text = NULL;
    int key = 0;
    int ch = (ch-'A'0;

 + key  while(1) %{ 26 +/* 'A';Forever loop, until we break; out */
    
        /* Prompt for an option */
      ch += printf(ch"Encrypt, <Decrypt, 'A')or Quit? 26 :(e/d/q) 0;");
        ch = getc_nnl();  
 }   
        /* Make sure they returngave ch;
us a valid option - }
if not, keep prompting! */
    int decode   while (intch != 'e' && ch, int!= key'E' && ch != 'd' && ch != 'D' && ch != 'q' && ch != 'Q') { 
            returnprintf("Invalid encodeoption. Encrypt, Decrypt, or Quit? (e/d/q) ");
            ch, -key= getc_nnl();
        }

    int main(int argc, char **argv)/* {If the user wants to quit... */
        if (ch == 'q' int|| ch;ch == 'Q') 
            intbreak; key;/* ...then break out of the loop */
        
        /* Allocate buffer for iftext (argcI <set 2text[0] to a null-terminator due to later strlen() {calls) */
        text = (char*)malloc(BUFS); text[0] = '\0';
       printf("USAGE: cipher 
 <integer key> <encode | decode>\n");
   /* Get the text to encrypt - If user entered nothing,
         * or printffgets("Then) is reading only a newline (from the fgetc calls), justkeep typereading.
 your text and it will automatically output the en*/de 
 crypted text!      printf("Please enter your text:)\n" ");
        while (strlen(text) <= 1)
            fgets(text, returnBUFS, 1;stdin);
            }

        /* Get the integer key =to atoiencrypt/decrypt with. If it's invalid, keep prompting! :) */
        printf(argv[1]"Ok, now what key should I use? (1 - 25) ");
        key = get_int();
  if      while (key < 1 || key > 25) {
            printf("Invalid key. Please enter a number between 1 and 25: ");
 printf("Key is invalid, or out of range. Valid keys are integers 1key through= 25.\n"get_int();
        }
         
    return 1;
   /* Ok, we have our data - now, did }

they say encrypt or decrypt? */
       int (*f)if (int,ch int)== ='e' (argv[2][0]|| ch == 'd''E') ? {
            /* Encrypt, and print the result */
  decode : 
         getCipherText(text, key);
           encode;

 printf("Ok. Here's your encrypted text: %s\n", text);
     while (EOF != (ch=getchar} else if ())ch == 'd' || ch == 'D') {
            /* Decrypt, and print the result */
  putchar(f          getPlainText(chtext, key);
            printf("Ok. Here's your decrypted text: %s\n", text);
        }
         
    return 0;   /* Free our malloc, so we don't have a memory overrun */
        free(text);
    }

    return 0;
}

Learning C, Making a Caesar Cipher program

So, wanting to learn at least the basics of C before I continue with C++, I'm writing some small programs to understand it better. (And soon, a small Text-Based Adventure Game, for the purpose of learning how to cope without Objects! LOL)

Anyway, I just want code critique, as I have never used the C input functions (I admit, I have used and like printf()! 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 nice. (And run nice.)

Here it is! Hope I did well :)

UPDATE: Fixed a couple minor bugs

UPDATE 2: Improved code syntax - Thanks for the pointer about char pointers! :)

UPDATE 3: Total reconstruction of the syntax, minimizing the code size - Thanks!!!!

main.c

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

    int encode(int ch, int key) { 
            if (islower(ch)) {
                    ch = (ch-'a' + key) % 26 + 'a';
                    ch += (ch < 'a') ? 26 : 0;
            }
            else if (isupper(ch)) {
                    ch = (ch-'A' + key) % 26 + 'A';
                    ch += (ch < 'A') ? 26 : 0;
            }
            return ch;
    }

    int decode(int ch, int key) { 
            return encode(ch, -key);
    }

    int main(int argc, char **argv) { 
            int ch;
            int key;

            if (argc < 2) {
                    printf("USAGE: cipher <integer key> <encode | decode>\n");
                    printf("Then, just type your text and it will automatically output the en/de crypted text! :)\n");
                    return 1;
            }

            key = atoi(argv[1]);
            if (key < 1 || key > 25) {
                    printf("Key is invalid, or out of range. Valid keys are integers 1 through 25.\n");
                    return 1;
            }

            int (*f)(int, int) = (argv[2][0] == 'd') ? 
                    decode : 
                     encode;

            while (EOF != (ch=getchar()))
                    putchar(f(ch, key));

            return 0;
    }

Caesar Cipher program in C

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;
}
added 240 characters in body
Source Link
FurryHead
  • 201
  • 1
  • 2
  • 5
    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>

    int encode(int ch, int key) { 
            if (islower(ch)) {
                    ch = (ch-'a' + key) % 26 + 'a';
                    ch += (ch < 'a') ? 26 : 0;
        }    }
            else if (isupper(ch)) {
                    ch = (ch-'A' + key) % 26 + 'A';
                    ch += (ch < 'A') ? 26 : 0;
            }
            return ch;
    }

    int decode(int ch, int key) { 
            return encode(ch, -key);
    }

    int main(int argc, char **argv) { 
            int ch;
            int key;

            if (argc < 32) {
                    printf("USAGE: cipher <integer key> <encode | decode>decode>\n");
 <text                   printf("Then, fromjust keyboardtype oryour stdin>\n"text and it will automatically output the en/de crypted text! :)\n");
                    return 1;
            }

            key = atoi(argv[1]);
            if (key < 1 || key > 25) {
                    printf("Key is invalid, or out of range. Valid keys are integers 1 through 25.\n");
                    return 1;
            }

            int (*f)(int, int) = (argv[2][0] == 'd') ? 
                    decode : 
                    encode;

            while (EOF != (ch=getchar()))
                    putchar(f(ch, key));

            return 0;
    }
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int encode(int ch, int key) { 
        if (islower(ch)) {
                ch = (ch-'a' + key) % 26 + 'a';
                ch += (ch < 'a') ? 26 : 0;
        } 
        else if (isupper(ch)) {
                ch = (ch-'A' + key) % 26 + 'A';
                ch += (ch < 'A') ? 26 : 0;
        }
        return ch;
}

int decode(int ch, int key) { 
    return encode(ch, -key);
}

int main(int argc, char **argv) { 
        int ch;
        int key;

        if (argc < 3) {
                printf("USAGE: cipher <integer key> <encode | decode> <text, from keyboard or stdin>\n");
                return 1;
        }

        key = atoi(argv[1]);
        if (key < 1 || key > 25) {
                printf("Key is invalid, or out of range. Valid keys are integers 1 through 25.\n");
                return 1;
        }

        int (*f)(int, int) = (argv[2][0] == 'd') ? 
                decode : 
                encode;

        while (EOF != (ch=getchar()))
                putchar(f(ch, key));

        return 0;
}
    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>

    int encode(int ch, int key) { 
            if (islower(ch)) {
                    ch = (ch-'a' + key) % 26 + 'a';
                    ch += (ch < 'a') ? 26 : 0;
            }
            else if (isupper(ch)) {
                    ch = (ch-'A' + key) % 26 + 'A';
                    ch += (ch < 'A') ? 26 : 0;
            }
            return ch;
    }

    int decode(int ch, int key) { 
            return encode(ch, -key);
    }

    int main(int argc, char **argv) { 
            int ch;
            int key;

            if (argc < 2) {
                    printf("USAGE: cipher <integer key> <encode | decode>\n");
                    printf("Then, just type your text and it will automatically output the en/de crypted text! :)\n");
                    return 1;
            }

            key = atoi(argv[1]);
            if (key < 1 || key > 25) {
                    printf("Key is invalid, or out of range. Valid keys are integers 1 through 25.\n");
                    return 1;
            }

            int (*f)(int, int) = (argv[2][0] == 'd') ? 
                    decode : 
                    encode;

            while (EOF != (ch=getchar()))
                    putchar(f(ch, key));

            return 0;
    }
deleted 4021 characters in body
Source Link
FurryHead
  • 201
  • 1
  • 2
  • 5

caesarUPDATE 3: Total reconstruction of the syntax, minimizing the code size - Thanks!!!!

main.c

#include <string<stdio.h> /* for strlen() */
#include <ctype<stdlib.h> /* for isupper() and islower() */
#include "caesar<ctype.h"h>

char *getCipherText(char *src, int key) {
    if encode(src == NULL) return src;
    char *p = src; /* Save the pointer to the beginning ofint srcch, to return later */
    int ch;
    
    /* Loop over each char in src */
    while (*srckey) {
        /* I convert *src to an int, and add/subtract from that instead as arithmetic on *src has adverse effects */
        ch = (int)*src;
        if (isupperislower(ch)) { /* If the char is uppercase */
            ch += key; /* add the key */
            if (ch > 'Z')= (ch -= 26; /* if the'a' char+ iskey) higher% than26 the+ highest'a';
 uppercase char, sub 26 */
           ch if+= (ch < 'A''a') ch += 26; /* if? the26 char: is0;
 lower than the lowest uppercase char, add 26} */
        } else if (islowerisupper(ch)) { /* else if it's lowercase */
            ch += key; /* add the key */
            if (ch > 'z')= (ch -= 26; /* if the'A' char+ iskey) higher% than26 the+ highest'A';
 lowercase char, sub 26 */
           ch if+= (ch < 'a''A') ch += 26; /* if the char is lower than the lowest lowercase char, add? 26 */
        } 
        /* an else case is not needed, since we are modifying the original. */
        
        /* set the current char to the new value, and move on to the next char in src */
        *src =: (char)ch;0;
        src++;
    }
    /* Return a pointer to the beginning of the char array passed to us */
    return p;ch;
}

charint *getPlainTextdecode(charint *srcch, 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 getCipherTextencode(srcch, -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 exit(), 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_nnlmain() {
    int ch = fgetc(stdin);
    
    /* While ch is a newline or carriage returnargc, 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(**argv) {
    char s[TBUFS]; 
    int i = 0;
    
    /* Read a string, and later parse the int in case there are no ints to read */
    fgets(s, TBUFS, stdin);
    while (!s[0] || !s[1]) 
        fgets(s, TBUFS, stdin);ch;
    
     /* Parse the int. Using sscanf because scanf on stdin leaves the file caret at a unknown position. */
    sscanf(s, "%d", &i);key;
    
    /* Return the int - if sscanf found nothing, it's already 0 */
    return i;
}

int main(int argc, char *argv[]) {
    char text[BUFS];
    int key = 0;
    int ch = 0;

   < while(13) {  /* Forever loop, until we break; out */
    
        /* Prompt for an option */
        printf("Encrypt, Decrypt, or Quit? (e/d/q)"USAGE: ");
cipher <integer key> <encode | decode> <text, from chkeyboard =or getc_nnl(stdin>\n"); 
    
         /* Make sure they gave us a valid option - if not, keep prompting!return */1;
        while (ch != 'e' && ch != 'E' && ch != 'd' && ch != 'D' && ch != 'q' && ch != 'Q') {}
            printf("Invalid option. Encrypt, Decrypt, or Quit? (e/d/q) ");
            chkey = getc_nnlatoi(argv[1]);
        }

        /* If the user wants to quit... */
        if (chkey ==< 'q'1 || chkey ==> 'Q'25) 
            break; /* ...then break out of the loop */
        {
        /* Get the text to encrypt - If user entered nothing,
         * or fgetsprintf()"Key is reading only a newline (from the fgetc calls)invalid, keep reading.
         */
  or out of range. Valid keys printf("Pleaseare enterintegers your1 text:through "25.\n");
        fgets(text, BUFS, stdin);
        while (!text[0] ||return !text[1])1;
            fgets(text, BUFS, stdin);}
            
        /* Get the integer key to encrypt/decrypt with. If it's invalid, keep prompting!int :(*f) */
        printf("Okint, now what key should I use? (1 - 25) "int);
        key = get_int();
        while (key < 1 || keyargv[2][0] >== 25'd') {? 
            printf("Invalid key. Please enter a number between 1 anddecode 25: ");
            key = get_int();
        }encode;
        
        /* Ok, we have our data - now, did they say encrypt or decrypt? */
        ifwhile (ch == 'e' || ch == 'E') {
            /* Encrypt, and print the result */
          EOF != getCipherText(text, key);
            printfch=getchar("Ok. Here's your encrypted text: %s\n", text);
        } else if (ch == 'd' || ch == 'D') {)
            /* Decrypt, and print the result */
            getPlainTextputchar(textf(ch, key);
            printf("Ok. Here's your decrypted text: %s\n", text);
        }
    }

    return 0;
}

caesar.c

#include <string.h> /* for strlen() */
#include <ctype.h> /* for isupper() and islower() */
#include "caesar.h"

char *getCipherText(char *src, int key) {
    if (src == NULL) return src;
    char *p = src; /* Save the pointer to the beginning of src, to return later */
    int ch;
    
    /* Loop over each char in src */
    while (*src) {
        /* I convert *src to an int, and add/subtract from that instead as arithmetic on *src has adverse effects */
        ch = (int)*src;
        if (isupper(ch)) { /* If the char is uppercase */
            ch += key; /* add the key */
            if (ch > 'Z') ch -= 26; /* if the char is higher than the highest uppercase char, sub 26 */
            if (ch < 'A') ch += 26; /* if the char is lower than the lowest uppercase char, add 26 */
        } else if (islower(ch)) { /* else if it's lowercase */
            ch += key; /* add the key */
            if (ch > 'z') ch -= 26; /* if the char is higher than the highest lowercase char, sub 26 */
            if (ch < 'a') ch += 26; /* if the char is lower than the lowest lowercase char, add 26 */
        } 
        /* an else case is not needed, since we are modifying the original. */
        
        /* set the current char to the new value, and move on to the next char in src */
        *src = (char)ch;
        src++;
    }
    /* Return a pointer to the beginning of the char array passed to us */
    return p;
}

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 exit(), 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 = fgetc(stdin);
    
    /* 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[TBUFS]; 
    int i = 0;
    
    /* Read a string, and later parse the int in case there are no ints to read */
    fgets(s, TBUFS, stdin);
    while (!s[0] || !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[BUFS];
    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 */
        
        /* 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: ");
        fgets(text, BUFS, stdin);
        while (!text[0] || !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);
        }
    }

    return 0;
}

UPDATE 3: Total reconstruction of the syntax, minimizing the code size - Thanks!!!!

main.c

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

int encode(int ch, int key) { 
        if (islower(ch)) {
                ch = (ch-'a' + key) % 26 + 'a';
                ch += (ch < 'a') ? 26 : 0;
        } 
        else if (isupper(ch)) {
                ch = (ch-'A' + key) % 26 + 'A';
                ch += (ch < 'A') ? 26 : 0;
        }
        return ch;
}

int decode(int ch, int key) { 
    return encode(ch, -key);
}

int main(int argc, char **argv) { 
        int ch;
        int key;

        if (argc < 3) {
                printf("USAGE: cipher <integer key> <encode | decode> <text, from keyboard or stdin>\n");
                return 1;
        }

        key = atoi(argv[1]);
        if (key < 1 || key > 25) {
                printf("Key is invalid, or out of range. Valid keys are integers 1 through 25.\n");
                return 1;
        }

        int (*f)(int, int) = (argv[2][0] == 'd') ? 
                decode : 
                encode;

        while (EOF != (ch=getchar()))
                putchar(f(ch, key));

        return 0;
}
Improved syntax, began using stack instead of heap, etc...
Source Link
FurryHead
  • 201
  • 1
  • 2
  • 5
Loading
Tweeted twitter.com/#!/StackCodeReview/status/67378429007376384
Bug fixes from feedback
Source Link
FurryHead
  • 201
  • 1
  • 2
  • 5
Loading
Source Link
FurryHead
  • 201
  • 1
  • 2
  • 5
Loading