Thread: Caesar cipher bug headaches.

  1. #1
    Registered User
    Join Date
    May 2010
    Posts
    4

    Caesar cipher bug headaches.

    Hello everyone,

    I'm following along with a Harvard Course (by myself, I'm not an enrolled student) over at This is CS50 / OpenCourseWare . Again, this is not graded work.

    An assignment in pset2 is to create a program that takes a command like input for a key and then rotates all characters in an input string by that amount of places. The key can be longer than 26, it needs to wrap around (so 30 for instance is the same as 4, in other words key % 26). If the key is not a positive int then it should exit.

    Secondly, it needs to preserve case and ignore any non alphanumerical chars.

    CS50 provide their own lib that allows you to use GetInput functions and a few types such as string instead of char *. These training wheels will be taken off eventually but not now.

    I have managed to create the program and it works fine except for one problem. It converts non caps to caps. I've looked at this code for hours and I even posted the relevant code on the cs50 discussion group but to no avail. Does anyone have a clue on what I might had messed up?

    To reiterate the problem. if I tell it to rotate by 1 with the input of Aa Yy Zz, it gives me BB ZZ AA instead of Bb Zz Aa.

    The code isn't fully cleaned up yet, the commented out parts are used as diagnostics.

    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include <ctype.h>
    #include <cs50.h>
    #include <string.h>
    
    #define KEY 1
    
    int
    main(int argc, char *argv[])
    {
    
    char c;
    int key = atoi(argv[KEY]), i, n;
    string s;
    
    //printf("%d\n", key);
    
    //checks for key as pos int & 
    //that there is one command line arg
    
    if(key > 0 && argc == 2) 
        {
       // printf("key: %d\n", key);
       // printf("count: %d\n", argc);
    
        // gets user input.
        s = GetString();
        printf("%s\n", s);
    
        //checks for valid string
        if(s != NULL)
            {
            for(i = 0, n = strlen(s); i < n; i++) // starts encoding
                { // checks for alphabetical non digit char
                if (s[i] >= 'A' && s[i] <= 'Z')
                    printf("%c", (((s[i] - 'A') + key) % 26) + 'A'); // rotates 
                else if (s[i] >= 'a' && s[i] <= 'z')
                    printf("%c", (((s[i] - 'a') + key) % 26) + 'a');
                else
                    printf("%c", s[i]); // non alphabet char preserved
                }
                printf("\n");
                return 0; // return success
            }
        }
    else
    return 1; // return failure. 
    }
    I hope I'm not breaking any rules here.

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Switch your key math a bit:
    Code:
    foo = 'a' + ((s[i] - 'a') + (key%26));

    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Registered User
    Join Date
    May 2010
    Posts
    4
    Switched the math around, same output.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Strange, it works here...
    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        char s[] = "Hello worldz";
        int key = 1, i, n;
        printf("%s\n", s);
        for (i = 0, n = strlen(s); i < n; i++)  // starts encoding
        {                           // checks for alphabetical non digit char
            if (s[i] >= 'A' && s[i] <= 'Z')
                printf("%c", (((s[i] - 'A') + key) % 26) + 'A');  // rotates
            else if (s[i] >= 'a' && s[i] <= 'z')
                printf("%c", (((s[i] - 'a') + key) % 26) + 'a');
            else
                printf("%c", s[i]); // non alphabet char preserved
        }
        printf("\n");
        return 0;
    }
    
    
    $ gcc foo.c
    $ ./a.out 
    Hello worldz
    Ifmmp xpsmea
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    May 2010
    Posts
    4
    What the hell? I just tried running gcc on caesar.c and it doesn't create an a.out file at all!

    I have a few other programs, those run perfectly fine.

    Compiler doesn't throw any errors, there's just no a.out file.

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Are you using an IDE (which one?) with a makefile?
    Try a "make clean" and "make all" approach.

    Or are you compiling from the command line - if so, post a snippet of terminal session so we can see what the responses are.

    If you're using -o on the compiler command line, your executable isn't called a.out
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    May 2010
    Posts
    4
    Quote Originally Posted by Salem View Post
    Are you using an IDE (which one?) with a makefile?
    Try a "make clean" and "make all" approach.

    Or are you compiling from the command line - if so, post a snippet of terminal session so we can see what the responses are.

    If you're using -o on the compiler command line, your executable isn't called a.out
    I'm using this:

    Appliance - The CS50 Wiki

    So here are two commands that I have used:

    gcc caesar.c -lcs50

    This doesn't give me the a.out output that I would normally expect.

    And make caesar which is:

    gcc -ggdb -std=c99 -Wall -Werror -Wformat=0 caesar.c -lcs50 -lm -o caesar

    This creates a caesar file which runs perfectly fine but still produces the original error.

  8. #8
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Arik View Post
    CS50 provide their own lib that allows you to use GetInput functions and a few types such as string instead of char *. These training wheels will be taken off eventually but not now.
    Take them off, they are apparently a hindrance and don't serve much purpose in this program anyway. Also, you might as well learn the language correctly. I am sure you can still follow along with the course code, etc.

    Getting input is simple, use fgets() on stdin and a sufficiently sized char array. It's no harder than using this "GetString()" function.

    Otherwise you are just asking people how to use a piece of (obscure) software.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    How about the one I posted (with no dependency on command line or other input).
    Is that also weird?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  10. #10
    Registered User jephthah's Avatar
    Join Date
    May 2010
    Location
    seattle
    Posts
    49
    I have managed to create the program and it works fine except for one problem. It converts non caps to caps.
    you need to rotate the alpha characters by the key, but do so in a manner that separately considers whether the original character is upper or lower case

    Code:
        unsigned char text[500] = "The Quick Brown Fox jumped o'er the 42 Lazy Dogs.";
        unsigned char *text_p = text;
        int key = 15;
    
        while (*text_p != '\0')
        {
            if (*text_p >= 'A' && *text_p <= 'Z')
            {
                *text_p += (key % 26);
                if (*text_p > 'Z')
                    *text_p -= 26;
            }
            else if (*text_p >= 'a' && *text_p <= 'z')
            {
                *text_p += (key % 26);
                if (*text_p > 'z')
                    *text_p -= 26;
            }
    
            text_p++;
        }
        printf("CIPHERTEXT: %s\n", text);
    Last edited by jephthah; 05-15-2010 at 10:14 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Caesar Cipher
    By dldsob in forum C++ Programming
    Replies: 7
    Last Post: 07-06-2009, 06:06 PM
  2. About aes
    By gumit in forum C Programming
    Replies: 13
    Last Post: 10-24-2006, 03:42 PM
  3. caesar cipher help.
    By stormfront in forum C Programming
    Replies: 36
    Last Post: 11-22-2005, 08:45 PM
  4. Help with Caesar cipher
    By jcmichman in forum C++ Programming
    Replies: 1
    Last Post: 04-05-2005, 10:50 AM
  5. My little Caesar cipher emulator
    By dead_cell in forum C++ Programming
    Replies: 3
    Last Post: 01-16-2004, 01:05 AM

Tags for this Thread