Thread: Cipher program error : redifinition/previous definition

  1. #1
    Registered User
    Join Date
    Feb 2012
    Posts
    4

    Cipher program error : redifinition/previous definition

    Hello everyone, Im trying to run a program PassWeb by compiling three source files together (PassWeb, Cipher and Menu) but every time I run it the compiler crashes(I use both dev C++ and gcc).
    The error redefinition/previous definition of all the funtions is repeatedly displayed and I dont know what to do with it. Im posting the Cipher.c program. Thanks for the help

    Code:
    /* "cipher.c – containing the Caesar cipher program."
     "Use the simple Caesar cipher algorithm covered in class.  Make the integer
     number a constant, built into the program.  The program must not ask the user
     for an integer number.  Make this Caesar cipher encrypt over the entire ASCII
     character space and not encrypt only letters as in the previous assignment."
     "Neil: Do we encode the entire file, just the lines, or the values.
     Mirza Abdel Baig: It's better to just decrypt the whole file first (including
     newlines) and then convert comma-separated data into a linked-list.
     Neil: Thanks."
     This is a wrapper for IO fn's using 'encryption.' */
    
    #include <stdlib.h> /* malloc free */
    #include <stdio.h>  /* fprintf fputs */
    #include <stdarg.h> /* va_* vsnprintf */
    #include <string.h> /* strlen */
    #include "Cipher.c"
    #include "PassWeb.c"
    
    /* Caesar Cipher is probably the easiest ever to break, but I can choose a
     number that is good (primes < 256: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
     53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157
     163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251;) it
     doesn't matter though, 10 is the last byte in the file, so any attacker could
     decrypt (and know your key) trivially; a better way would be to encrypt the
     values; md5() anyone? */
    
    const int debug   = 0;
    const int key     = 113;  /* default key */
    const int bufsize = 2048; /* sufficient to hold user info? */
    
    /* public */
    struct Cipher {
        FILE      *fp;
        enum Mode {WRITE, READ} mode;
        char      *buf;
    };
    
    static int encrypt(const int c, const int key);
    static int flushin(FILE *fp);
    
    /* public */
    
    void Cipher_(struct Cipher **cipherPtr) {
        struct Cipher *cipher;
    
        if(!cipherPtr || !(cipher = *cipherPtr)) return;
        if(cipher->fp && fclose(cipher->fp)) perror("file");
        if(debug) fprintf(stderr, "~Cipher: erase, #%p.\n", (void *)cipher);
        free(cipher);
        *cipherPtr = cipher = 0;
    }
    
    struct Cipher *Cipher(char *fn, enum Mode m) {
        struct Cipher *cipher;
    
        if(!fn || !*fn) return 0;
        if(!(cipher = malloc(sizeof(struct Cipher) + bufsize))) {
            perror("Cipher constructor");
            Cipher_(&cipher);
            return 0;
        }
        cipher->fp   = 0;
        cipher->mode = m;
        cipher->buf  = (char *)(cipher + 1);
        if(debug) fprintf(stderr, "Cipher: new <%s> for %s, #%p.\n", fn,
                          m == WRITE ? "writing" : "reading", (void *)cipher);
        /* binary files: warning: no automatic \n conversion */
        if(!(cipher->fp = fopen(fn, m == WRITE ? "wb" : "rb"))) {
            perror(fn);
            Cipher_(&cipher);
            return 0;
        }
    
        return cipher;
    }
    
    
    
    /** gets as much of the line as possible (up to bufsize,) discards the rest,
     never returns a \n */
    char *CipherGetLine(struct Cipher *c) {
        int i, ch;
    
        if(!c || c->mode != READ) return 0;
        /* read char by char; slower but needs unencryping to tell where \n's are */
        for(i = 0; i < bufsize; i++) {
            if((ch = fgetc(c->fp)) == EOF) {
                if(ferror(c->fp)) perror("Cipher::getLine");
                break;
            }
            ch = encrypt(ch, -key);
            if(ch == '\n') break;
            c->buf[i] = ch;
        }
        if(i < bufsize) {
            c->buf[i] = '\0';
        } else {
            fprintf(stderr, "Cipher::getLine: truncating input at column %d.\n", bufsize - 1);
            flushin(c->fp);
            c->buf[bufsize - 1] = '\0';
        }
        /* very scetch returning decrypted memory */
        return c->buf;
    }
    
    /** everything is sexy in this fn (except it needs a \n, getLine does not, so
     this fn outputs one less char then getLine) */
    void CipherPrintf(struct Cipher *c, const char *fmt, ...) {
        char    *chPtr;
        va_list ap; /* macro */
    
        /* what happens to the stack if this is true? should be okay */
        if(!c || c->mode != WRITE) return;
        /* transfer to temporary buffer */
        va_start(ap, fmt);
        va_end(ap);
        if(vsnprintf(c->buf, bufsize, fmt, ap) >= bufsize && c->buf[bufsize - 2] != '\n') {
            c->buf[bufsize - 2] = '\n';
            fprintf(stderr, "Cipher::printf: truncating output at column %d.\n", bufsize - 2);
        }
        /* encrypt, shredding the buffer (fput[s->c] because it's binary) */
        for(chPtr = c->buf; *chPtr != '\0'; chPtr++) {
            *chPtr = encrypt(*chPtr, key);
            if(fputc(*chPtr, c->fp) == EOF) {
                perror("Cipher::printf");
                return;
            }
        }
    }
    
    /* private */
    
    /** it doesn't take much code */
    static int encrypt(const int c, const int key) {
        return c + key;
    }
    
    /** fflush isn't defined on input buffers; returns zero if it got an EOF */
    static int flushin(FILE *fp) {
        int c;
        do { c = fgetc(fp); } while(c != EOF && c != '\n');
        return (c == EOF) ? 0 : -1;
    }

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I notice:
    Code:
    #include "Cipher.c"
    #include "PassWeb.c"
    Generally, you should not include source files in another source file. You should include header files instead.

    So, what is likely happening here is that your function definitions from those two source files are being included in this source file, then you compile and link all three source files. Problem is, you now define the same functions in both Cipher.c and this source file, violating the one definition rule.

    One way to solve this is to write a header file for each of these two source files, then include them in this source file. The header files would contain the forward declarations of the functions in the respective source files. Since declaring a function twice is fine, you'll be okay.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    You've got 'Cipher' as a struct and as a function:
    Code:
    struct Cipher *Cipher(char *fn, enum Mode m) {
        struct Cipher *cipher;
        ....

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by nonoob
    You've got 'Cipher' as a struct and as a function:
    Not really. The struct is struct Cipher, not Cipher.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 07-16-2011, 06:08 PM
  2. Multiple definition error, one definition
    By frog in forum C++ Programming
    Replies: 9
    Last Post: 10-21-2010, 03:15 AM
  3. warning: this is the location of the previous definition
    By Boschwakka in forum C Programming
    Replies: 1
    Last Post: 07-21-2010, 07:47 AM
  4. Replies: 1
    Last Post: 04-21-2008, 02:27 AM
  5. Cipher program
    By Mule in forum C++ Programming
    Replies: 3
    Last Post: 04-26-2003, 07:52 PM