Thread: A noob with a question about a transposition cipher

  1. #1
    Registered User
    Join Date
    Sep 2007
    Posts
    4

    Question A noob with a question about a transposition cipher

    So I was talking with a friend online the other day the the subject of transposition ciphers came up and I ended up whipping this together:

    Code:
    
    #ifdef HAVE_CONFIG_H
    #include <config.h>
    #endif
    
    #include <iostream>
    #include <cstdlib>
    
    using namespace std;
    
    int main(int argc, char *argv[])
    {
    
    	char plaintext1[255];
    	char plaintext2[255];
    	char ciphertext[255];
    	int caesarkey = 0;
    	int stringlength = 0;
    	int i = 0;
    	cout<<"Next we are going to try a flip cipher, this is a little more complicated, so bear with 	me."<<endl;
    		cout<<endl<<"First off, enter a new plaintext: ";
    		cin.getline(plaintext2, 255, '\n');
    		while(plaintext2[i] != '\0'){i++;stringlength++;}
    	
    		char flipcipher[stringlength+1];
    		int permuter[stringlength];
    		cout<<"Now we know that our ciphertext is "<<stringlength<<" Characters long. We are now going to move the characters around a little, for that we need to enter a key for them."<<endl;
    
    		cout<<"Please enter the numbers 0 - "<<stringlength-1<<" In a random order! Don't repeat yourself!"<<endl;
    		
    		i = 0;
    		
    		while(i < stringlength){
    			int n = 0;
    			int u = 0;
    			cout<<"Enter number: ";	
    			cin>>n;
    			if(n>stringlength){
    				cout<<"Number too high! Try again!";
    				cin>>n;
    				i--;}
    	
    			permuter[i] = n;
    			i++;}
    		i = 0;
    		cout<<"Ok now we have a permutor, let put it to use!"<<endl;
    		while(plaintext2[i] != '\0'){
    			flipcipher[i] = plaintext2[permuter[i]];
    			i++;}
    		flipcipher[i+1]  = '\0';
    		i = 0;
    	
    		cout<<"Ok now we have flipped the plaintext, let's look at it: "<<endl;
    	
    		while(flipcipher[i] !='\0'){
    			cout<<flipcipher[i];
    			i++;}
    	
    		cout<<endl<<"OK! Now let us see if we can decode the text as well!"<<endl<<endl;
    		
    		i = 0;	
    		while(flipcipher[i] !='\0'){
    		plaintext1[permuter[i]] = flipcipher[i];
    		i++;}
    		
    		cout<<"If what comes next is your real text then we've won!"<<endl;
    		
    		i = 0 ;
    		while(plaintext1[i] !='\0'){
    			cout<<plaintext1[i];
    			i++;}
    	cout<<endl;
    	return 0;
    }
    It's not very pretty, but it works. I still learning the finer points of c++.
    My question is this: As you can see my method for generating a "permuter" (I suppose the correct term is a key) is far from elegant, I tried to incorporate a check for duplicate numbers but it only worked some of the time, and even the length check is sort of dodge, so I am looking for a method to generate a key in a way that is half-way random. I can't just generate a string of random numbers since the cipher requires it to be a permutation of the number string from 0 to stringlength, so I was thinking is there any relatively simple way to generate an arbitrary permutation of said string?

    Also any general comments on the code are welcome, mostly it was written to show the principle of a transposition cipher and for me to learn a bit more C++, so any comments are welcome!

  2. #2
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Code:
    while(plaintext2[i] != '\0'){i++;stringlength++;}
    Bad. Use strlen(), or better yet, use std::string for all string-related stuff.

    Code:
    char flipcipher[stringlength+1];
    That's not even valid C++. It's a GCC extension to allow this C99 code under C++.

    The typical way to generate numbers in a range without duplicates, in random order, is to first generate the numbers in, say, ascending order (makes it easy to avoid dupes) and then shuffle the result. std::shuffle() can shuffle for you.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  3. #3
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Why are you calculating the length of the string by scanning for a zero? It is not guaranteed that a C++ std::string actually has a zero at the end, and even if it does, string::size() would be much faster.

    You may also want to ENFORCE the "don't repeat yourself".

    And at the end, you are again relying on the undefined behaviour of "string" don't always end with a zero.

    Edit: Doh! strings are char arrays, not C++ strings, so ignore that bit.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  4. #4
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    You should learn about the std::string container.

    Code:
    cout<<"Please enter the numbers 0 - "<<stringlength-1<<" In a random order! Don't repeat yourself!"<<endl;
    Ugh, so if I type in a message that's 250 characters in length then I need to individually type in the values from 0 to 249 in a random order and remember which ones I've already typed so I don't repeat them? I don't have that much patience. Yeah, that does need work.

    Code:
    cout<<"Ok now we have a permutor, let put it to use!"<<endl;
    while(plaintext2[i] != '\0'){
        flipcipher[i] = plaintext2[permuter[i]];
        i++;}
    flipcipher[i+1]  = '\0';
    When you reach the end of your loop to fill the flipcipher array, your i value is already correct to place the null. You shouldn't need to add 1 to it.

    Code:
    i = 0;
    
    cout<<"Ok now we have flipped the plaintext, let's look at it: "<<endl;
    	
    while(flipcipher[i] !='\0'){
        cout<<flipcipher[i];
        i++;}
    You do realize you can skip this loop and just say:
    Code:
    cout << flipcipher;
    Quote Originally Posted by DocFerret
    My question is this: As you can see my method for generating a "permuter" (I suppose the correct term is a key) is far from elegant, I tried to incorporate a check for duplicate numbers but it only worked some of the time, and even the length check is sort of dodge, so I am looking for a method to generate a key in a way that is half-way random. I can't just generate a string of random numbers since the cipher requires it to be a permutation of the number string from 0 to stringlength, so I was thinking is there any relatively simple way to generate an arbitrary permutation of said string?
    Yes you can do this easier. You can initialize an array of size stringlength with the values from 0-stringlength (-1). You can then call the STL random_shuffle function which will randomize the values in this array so you will in effect randomly generate the key.
    Last edited by hk_mp5kpdw; 09-25-2007 at 08:34 AM.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  5. #5
    Registered User
    Join Date
    Sep 2007
    Posts
    4
    Quote Originally Posted by CornedBee View Post
    Code:
    while(plaintext2[i] != '\0'){i++;stringlength++;}
    Bad. Use strlen(), or better yet, use std::string for all string-related stuff.

    Code:
    char flipcipher[stringlength+1];
    That's not even valid C++. It's a GCC extension to allow this C99 code under C++.

    The typical way to generate numbers in a range without duplicates, in random order, is to first generate the numbers in, say, ascending order (makes it easy to avoid dupes) and then shuffle the result. std::shuffle() can shuffle for you.


    I have no idea what C99 even is to be honest so I just used it and it worked so it's fine by me. Of course I realize it might not be fine in the long run, but to be honest at my current skill level I don't even know why it's wrong

    I've never used strlen or shuffle, how are they called and what libs are they in? I assume they work on char arrays as well.

    Another thing, I started out by saying my method was FAR from elegant, in fact it outright sucks, I'm well aware of this and that is why I'm posting here so I can learn smarter ways of doing things like that

    I do apprciate the comments though so keep them comming.
    Last edited by DocFerret; 09-25-2007 at 08:33 AM.

  6. #6
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    It's wrong because it's not part of C++. Array bounds must be compile-time constants.

    strlen() is used with legacy C strings. Use std::string, from the <string> header. std::random_shuffle is in <algorithm>.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  7. #7
    Registered User
    Join Date
    Sep 2007
    Posts
    4
    So I'd just do for example:

    Code:
     int stringlength = strlen(plaintext2[]);
    To get the length of the plaintext2[] string?

    And

    Code:
    int key[] = random_shuffle(permuter[]);
    Or at least something to that effect to get the random key?

  8. #8
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    No and no. You should read a proper tutorial on arrays, and more importantly, you should forget all about C strings and learn C++ strings.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  9. #9
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    random_shuffle works like this:
    Code:
    #include <algorithm>
    
    ...
    
    int array[10] = {0,1,2,3,4,5,6,7,8,9};
    
    // Randomly shuffle the contents of "array"
    std::random_shuffle(array,array+10);
    And yes, it works with characters as well:
    Code:
    char alphabet[26] = "abcdefghijklmnopqrstuvwxyz";
    
    std::random_shuffle(alphabet,alphabet+26);
    And other containers like std::string:
    Code:
    std::string alphabet("abcdefghijklmnopqrstuvwxyz");
    
    std::random_shuffle(alphabet.begin(),alphabet.end());
    Depending on implementation you may need a call to srand prior to using it to truly make it random.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  10. #10
    Registered User
    Join Date
    Sep 2007
    Posts
    4
    Cool thanks I'll give that a whirl.

    And CornedBee I do appriciate you trying to teach me propper code ettiquette and I will look into those strings, it's just that the book I started out learning from did it that way and I feel relatively comfortable with doing it that way.

  11. #11
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    You mean you learned from a book that teaches char arrays as string but doesn't even show you how to use strlen()?

    Please, throw it away. Or better, throw it at the head of the author.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. quick noob question
    By thanatos1 in forum C# Programming
    Replies: 2
    Last Post: 06-17-2009, 08:28 PM
  2. another noob question
    By clb2003 in forum C Programming
    Replies: 4
    Last Post: 02-12-2009, 01:28 PM
  3. Noob printf question
    By lolguy in forum C Programming
    Replies: 3
    Last Post: 12-14-2008, 08:08 PM
  4. About aes
    By gumit in forum C Programming
    Replies: 13
    Last Post: 10-24-2006, 03:42 PM
  5. noob question
    By unclebob in forum C++ Programming
    Replies: 9
    Last Post: 09-24-2006, 08:48 AM