Help with functions

This is a discussion on Help with functions within the C++ Programming forums, part of the General Programming Boards category; The ciphertext is almost identical to the message: Code: #include <iostream> #include <string> using namespace std; #define DEBUG char* shift(char* ...

  1. #1
    Caution: Wet Floor
    Join Date
    May 2006
    Posts
    55

    Help with functions

    The ciphertext is almost identical to the message:

    Code:
    #include <iostream>
    #include <string>
    using namespace std;
    
    #define DEBUG
    
    
    char* shift(char* k) {
    
      // return an (odd) permutation of `k'
    
      int sz = sizeof(k)/sizeof(char);
    
      for(int i = 0; i < sz; i++) {
        char t = k[i];
        k[i] = k[i+1];
        k[i+1] = t;
      }
    
      return k;
    
    }
    
    char* forward(char* m, char* k) {
    
      // forward cipher (encryption)
    
      int sz_m = sizeof(m)/sizeof(char);
    
      while(*m++ ^= *k) {
        k = shift(k); // algorithm (symmetric difference)
    #ifdef DEBUG
        cout << k << '\n';
    #endif
      }
      return m;
    }
    
    int main(int argc, char* argv[]) {
    
      char** args = argv;
    
      char* mess;
      char* key;
    
      switch(argc) {
      case 3:
        mess = args[1];
        key = args[2];
        break;
      default:
        cout <<"usage: encrypt message key\n";
        return 1;
      }
    
      cout << "Encrypted message is: \n"
           <<"\n\t" << forward(mess, key) << '\n';
    
      return 0;
    }
    The `shift' function is supposed to rotate through each character in the key, so that a (somewhat) different comparison is done for as many characters as the unencrypted message contains. But the output points to a problem:

    Code:
    oops% encrypt bell-labs message
    Encrypted message is:
    
            ll-labs
    Any ideas? Great help on past issues--thanks.

  2. #2
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    Code:
    >  int sz = sizeof(k)/sizeof(char);
    Perhaps you want to use the length of the key here:
    Code:
      int sz = strlen(k);

  3. #3
    Caution: Wet Floor
    Join Date
    May 2006
    Posts
    55
    Thanks, but I still have the same problem : (

  4. #4
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,048
    To expand on swoopy's response, sizeof(array)/sizeof(*array) only works on proper arrays. It doesn't work on pointers to strings or anything like that. And since, when passed to functions, arrays "degrade" (sorry, Prelude) into pointers, you can't use that trick to determine the number of elements in an array inside of a function that was passed that array. That's why you have to pass the size into the function as a separate parameter.

    I'm examining your code in greater detail now.

    [edit] Your shift function can return void. It doesn't have to return the pointer, because you don't modify it in any way.

    You don't need to use args, argv will do just fine.

    What if the encrypted message contains NULLs? . . . .

    Anyway, I experimented a bit, and this is what I came up with. It's not pretty, but hey.
    Code:
    #include <iostream>
    #include <string>
    #include <cctype>
    using namespace std;
    
    #define DEBUG
    
    
    void shift(char* k) {
    
      // return an (odd) permutation of `k'
    
      int sz = strlen(k);
    
      for(int i = 0; i < sz-1; i++) {
        char t = k[i];
        k[i] = k[i+1];
        k[i+1] = t;
      }
    }
    
    char* forward(char* m, char* k) {
    
      // forward cipher (encryption)
    
      int sz_m = strlen(m);
    
      for(;;) {
        *m ^= *k;
        if(!*++m) break;
        cout << "[message: " << m << "]\n";
    
        shift(k); // algorithm (symmetric difference)
    #ifdef DEBUG
        cout << k << '\n';
    #endif
      }
      return m;
    }
    
    int main(int argc, char* argv[]) {
    
      char* mess;
      char* key;
    
      switch(argc) {
      case 3:
        mess = argv[1];
        key = argv[2];
        break;
      default:
        cout <<"usage: encrypt message key\n";
        return 1;
      }
    
      {
        cout << "Encrypted message is: \n"
             <<"\n\t";
        int len = strlen(mess);
        const char *message = forward(mess, key);
        for(int x = 0; x < len; x ++) {
            cout << (int)mess[x] << ' ' << (isprint(mess[x]) ? (char)mess[x] : '-') << endl;
        }
      }
    
      return 0;
    }
    Hopefully that helps. [/edit]
    Last edited by dwks; 12-19-2007 at 04:06 PM.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  5. #5
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    Code:
    >  while(*m++ ^= *k) {
    Either change this to:
    Code:
    size_t len = strlen(m);
    for (int i=0; i<len; i++)
    {
    	*m++ ^= *k;
    Or be sure you don't xor a letter with itself, which results in a null terminatro (\0), and consequently the loop terminates.

    >oops&#37; encrypt bell-labs message
    xor e with e and you get 0.

  6. #6
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Code:
    #include <string>
    Are you aware that you are not using anything from that header?

    C-style array functionality (strlen, strcpy etc) are in <cstring>.

    This might be a large part of your problem, as it seems that you are quite relaxed about array bounds.

    Edit: Using std::string might also take care of the 0-character problem because std::string doesn't use '\0' for anything special.

    Code:
    char* forward(char* m, char* k) {
    
      // forward cipher (encryption)
    
      int sz_m = sizeof(m)/sizeof(char);
    
      while(*m++ ^= *k) {
        k = shift(k); // algorithm (symmetric difference)
    #ifdef DEBUG
        cout << k << '\n';
    #endif
      }
      return m;
    }
    Note that sz_m isn't used. Are you quite sure that the while loop condition respects the different lengths of the two buffers? What if key is shorter than message? Or the other way round?

    The shift function appears simply to chops characters from the beginning of the key, making it even shorter.
    Last edited by anon; 12-19-2007 at 04:06 PM.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  7. #7
    Caution: Wet Floor
    Join Date
    May 2006
    Posts
    55
    Thanks all! It works, and the code is much cleaner.

    Now I have to go backward( ) ; )

  8. #8
    Registered User
    Join Date
    Dec 2007
    Posts
    2
    Great info, thanks for sharing

    Toni Rudolf Vlaic

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Void Functions Help
    By bethanne41 in forum C++ Programming
    Replies: 1
    Last Post: 05-09-2005, 05:30 PM
  2. Functions and Classes - What did I do wrong?
    By redmage in forum C++ Programming
    Replies: 5
    Last Post: 04-11-2005, 11:50 AM
  3. calling functions within functions
    By edd1986 in forum C Programming
    Replies: 3
    Last Post: 03-29-2005, 02:35 AM
  4. Factory Functions HOWTO
    By GuardianDevil in forum Windows Programming
    Replies: 1
    Last Post: 05-01-2004, 01:41 PM
  5. Shell functions on Win XP
    By geek@02 in forum Windows Programming
    Replies: 6
    Last Post: 04-19-2004, 05:39 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21