comparing arrays?

Hi again

I'm writing a code that decrypts certain text files using arrays.

There is a permutation of 20 integers, and it applies the permutation to a character string and decodes a message (from a given input file).

An example is: 0 1 2 3....(goes to 19)
//permutation: 12 4 7 1....(these integers never go above 19)

So the 12th integer in the array should be 0
the 4th integer in the array should be 1 ....and so on (this is the inverse)

Here's how I did the permutation:

1
2
3
4
5
6
7
8
9
10
 	void permutation (int readInt[], int inverse[],int& idx, int& newIdx) {
	
		for (idx=0; idx < totalInt; idx++) {
					
			newIdx = readInt[idx]; 

			inverse[newIdx] = idx;
		}
				
	} 


where readInt is the permutation array and the inverse array is the array used for decrypting.


Given a character array I have to use the changes from the permutation to decrypt a message. It takes chunks of 20 characters than applies the permutation until the message is deciphered.


I am using all functions, and I am wondering how I could compare the changes in the permutation to apply to the character code.

Thanks
totalInt is undefined, isn't it? Why are idx and newIdx passed in as references?

I don't really understand what you are asking. What is your question?
Well, idx and newIdx, dont really need to be passed your're right.


Ill try to rephrase: The code i wrote above applies a permutation so the values are changed around within the array. (btw disregard the example up there)

example: say there are 5 integers in an array 0,1,2,3,4
the permutation could be something like 3,0,1,2,4

So:
After applying the code, the inverse would be : 1, 2, 3, 0, 4

since 0 is below 1, 1 is below 2, 2 is below 3 .....etc.





My question is: how do I can i use this permutation to apply to character arrays ?

This is whats supposed to happen: Say I have 0, 1, 2 ,3 , 4
Permutation: 4, 3, 2, 1, 0
Message: o l l e h



So 0 -> 4
1 -> 3
2 -> 2
3 -> 1
4 -> 0

Applying this to the message, we get the new message h e l l o

I can't figure out how to apply the permutation to the character arrays. I'm trying to write a function that will change the character arrays just like it changed the integer arrays (by position)

Its supposed to grab 20 characters and reorder them in the same way the permuation reordered the integer array. Thanks



Argh, I knew I would probably analyze your code before too long... ;-)
http://www.cplusplus.com/forum/beginner/12340/

You are trying to be too sneaky with the code -- it doesn't do what you think it ought to be doing. For example, on line 43 the comment is //read first 20 characters of the message -- but it actually only reads one character. Then you go into the permutation loop while trying to read more characters.

Remember, a permutation cipher is a form of block cipher -- meaning that it works on a complete group of values (characters) at a time.

So, if your cipher key is 4 3 2 1 0 (to reverse each group of five characters), then you must read the plaintext five characters at a time. For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ifstream infile;
ofstream outfile;
const unsigned pkey [ 5 ] = { 4, 3, 2, 1, 0 };
char block[ 5 ];

while (infile)
  {
  // Read an entire block to be permuted
  for (unsigned n = 0; n < 5; n++)
    {
    block[ n ] = '\0';         // EOF --> null characters in the block
    infile.get( block[ n ] );  // Get the next character in the block (if not EOF)
    }

  // Permute it
  permute( block, pkey );

  // Write the permuted block
  for (unsigned n = 0; n < 5; n++)
    {
    outfile.put( block[ n ] );
    }
  }
The permutation function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void permute( char block[ 5 ], int pkey[ 5 ] )
  {
  char result[ 5 ];

  // This puts the permuted data in result[]
  for (unsigned n = 0; n < 5; n++)
    {
    result[ pkey[ n ] ] = block[ n ];
    }

  // Now, copy the result[] back to block[] in order to return the permuted data
  for (unsigned n = 0; n < 5; n++)
    block[ n ] = result[ n ];  
  }



Input Format
I am not sure I understand your input data. It appears that you want it to be a file something like:
; this line is ignored
; this line is also ignored
19
4 3 2 1 0
; this line is ignored as well
Caesar was no fool.

As it is, your code fails after reading the 'C' in "Caesar", because it tries to skip two lines before each character read...

I do not know your teacher's input requirements, but I don't think it a good idea to mix the permutation key with the codes to permute. I think it is a better idea to ask the user for the key, then operate over an entire file. For example (presuming you are using Unix):

% cat Scrambled.txt
aseaCsaw rf on 0.loo
% ./a.out
Please enter the name of the file to permute
> Scrambled.txt
Please enter the name of the file to write
> Unscrambled.txt
Please enter the permutation key.
The key must be between 3 and 20 integers long, in the range [0,N), with no repeats.
For example, "4 3 2 1 0" to reverse blocks of 5 characters.
> 4 3 2 1 0
% cat Unscrambled.txt
Caesar was no fool.
%

(Bold text represents what the user entered. The underlined zero shows where there would be a null character in the output -- based upon the code I gave above. In real life a null character would not likely print anything... but I'll mention more on the significance of this character below.)


Block Size
It also looks to me like you want to be able to handle different-sized blocks (given a permutation for each text to cipher/decipher). This is easy enough to do using the STL containers string and vector. The above code then becomes much easier:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
vector <unsigned> get_and_validate_permutation_key();
string read_block( ifstream& infile, unsigned block_size );
string permute( const string& block, const vector <unsigned> & pkey );

int main()
  {
  ifstream infile;
  ifstream outfile;

  vector <unsigned> pkey;
  string block;

  // Get the input file name
  string infilename;
  cout << "Please enter the name of the file to permute\n>" << flush;
  getline( cin, infilename );
  infile.open( infilename.c_str() );
  if (!infile)
    {
    cerr << "I could not open \"" << infilename << "\"\n";
    return 1;
    }

  // Get the output file name
  string outfilename;
  ...

  // Get the permutation key
  pkey = get_and_validate_permutation_key();
  if (pkey.empty())
    {
    cerr << "Invalid permutation key.\n";
    return 1;
    }

  // OK, now permute the entire input file (compare this with the code above)
  while (infile)
    {
    block = read_block( infile, pkey.size() );
    block = permute( block, pkey );
    outfile << block;
    }

  // All done!
  return 0;
  }

The read_block() routine must be sure to return a string of exactly block_size characters long. If the source file doesn't have enough characters to fill a whole block, the extra characters must be set to something, like null or a space or something. (I really will talk about it below -- honest.)

The permute() function works much like before, except that now you can just return the resulting string instead of overwriting the argument data...

Oh, and get_and_validate_permutation_key() must do what it says... read a bunch of integers from the user and make sure they all have the required characteristics. If invalid in any way, the returned value should be an empty vector so that the program will complain and quit. I suggest using getline() to read a string from the user, then use an istringstream to get the integers out of the line (with a loop) and push_back() each integer in the result vector. Don't forget to validate!


Padding
Now, for the significance of that null character -- this is only useful if you know that the null character is not part of the plaintext. That is typically the case for text files, so it is safe to do that.

However, if that is not true, then you must know exactly how long the plaintext is, and truncate the last block before writing it out. Your code over on the other post seems to suggest that you know how long the plaintext is. Where and how you store that information is up to you. You might just store an extra byte (character) at the beginning of the cipher file that gives the size of the last block (== plaintext_size % block_size), and read/write it first when deciphering/ciphering the file. Etc.


Whew. That ought to help get you started. Good luck!
Hey Duos, I appreciate the long reply, but unfortunately it doesn't help me that much. I'm taking a beginners c++ course and we haven't covered many of the things you have mentioned (so i'm not allowed to use them).

I'm almost there. I just need to APPLY THE ARRAY........just a few lines of code I'm missing that I can't figure out. Here it is again (and btw, I changed it so it does read 20 characters at a time).....Notice the function definition for the decryption function. I've tried so many things, ah programming is so tedious!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
 #include <iostream> // for cout, if needed for debugging
#include <fstream> // for file stream support
#include <iomanip> // for formatting support
#include <cmath> // for standard math functions, if needed
#include <string> // for character string type
#include <climits>
using namespace std; // put all of that in scope

const int totalInt = 20;
void readpermutation (ifstream& Data, int readInt[],  int idx);
void permutation (int readInt[], int inverse[], int idx, int newIdx);
void readNumChar (ifstream& Data, int numChar);
void readMessage (ifstream& Data, char readChar[], int idx);
void decryption (char readChar[], int finished[], int idx);
void firstoutput (ofstream& Log, int numChar);
void secondoutput (ofstream& Log, int readInt[], int idx);
void lastoutput (ofstream& Log, char finished[], int idx, int newIdx);
void footer (ofstream& Log);


int main () {
	int readInt[totalInt]; //reads and creates first array
	int inverse [totalInt]; //creates new array for decryption
	int numChar = 0; //number of integers given in the input
	char readChar[totalInt]; //array of the code needing decryption
	char finished[totalInt]; //final outputted array
	int sumChar = 0; //sum of characters
	int idx = 0; //index number
	int newIdx = 0; //new index number



	ifstream Data("Scrambled.txt"); // opens the input file
	ofstream Log("Unscrambled.txt"); // opens the output file


		readpermutation (Data, readInt,  idx); //reat the permutation array

		readNumChar (Data, numChar); //read number of characters in the input

		firstoutput (Log, numChar); //first output

		secondoutput (Log, readInt, idx); //second output

		readMessage (Data, readChar, idx); //read first 20 characters of the message

		permutation (readInt, inverse, idx, newIdx); //Apply the permutation

	
			while ( Data && sumChar < numChar) {


				decryption (finished, idx, readChar); //Decryption

				lastoutput (Log, finished,  idx, newIdx);

				sumChar = sumChar + 20;

				readMessage (Data, readChar, idx); //Read next 20 characters of the message
			
				}
			
			footer (Log);
		
			return 0;
				
		}



	


//Function definitions:

	void readpermutation (ifstream& Data, int readInt[],  int idx) { //read first line of digits

		Data.ignore(INT_MAX, '\n');	// skip first line of input

		for (idx=0; idx < totalInt; idx++) {

				Data >> readInt[idx]; // reads list of integers 
		}
		
	}


	void readNumChar (ifstream& Data, int numChar) {
	
		Data.ignore(INT_MAX, '\n'); // skip next 2 lines
		Data.ignore(INT_MAX, '\n');
		
		Data >> numChar;	//read how many characters in the message

		Data.ignore(INT_MAX, '\n'); // skip next 2 lines
		Data.ignore(INT_MAX, '\n');

	}


	void readMessage (ifstream& Data, char readChar[], int idx) {
		
		for (idx = 0; idx < totalInt; idx++) {

				Data >> readChar;
			}
	}



	void permutation (int readInt[], int inverse[],int idx, int newIdx) {
	
		for (idx=0; idx < totalInt; idx++) {
					
			newIdx = readInt[idx]; 

			inverse[newIdx] = idx;
		} 
				
	}




	void decryption (char finished[], int idx, char readChar) {
		
			
			finished[ = readChar[idx];        //help me here PPLLLEEEEAAASSEEE!!!!

		}
	}



	


	void firstoutput (ofstream& Log, int numChar) {
		Log << "***************************************************************************" << endl
			<< "Decrypting " << numChar << " characters" << endl;
	}



	void secondoutput (ofstream& Log, int readInt[], int idx){
		
		Log << "Using:  0  1  2  3  4  5  6 7  8  9  10 11 12 13 14 15 16 17 18 19";
		Log << endl;
		Log << "      ";
			for (idx=0; idx < 20; idx++){
				Log <<  setw(3) << readInt[idx]; 
			}
				Log << endl << endl;
			 
	}

	
	void lastoutput (ofstream&Log, char finished[], int idx ) {

		for (idx = 0; idx < totalInt; idx++) {
		Log << finished[idx] ;
		}	
		Log << endl;
	http://www.cplusplus.com/forum/beginner/12349/	idx=0;
	}
		
		    
Last edited on
anyone else? I have tried many different things and I still can't get it to work. It's due by 12am tonight so any information would be greatly appreciated!(the function definition at line 125 is where my trouble is coming from) Thanks.

Oh, and ignore line 164, not sure where that came from

Well, it's 9:15 here in NJ, so...

You are aware that decryption and encryption both use the same permutation function? The only difference is the key

01234
world

encrypt decrypt

43210 43210
dlrow world

32401 34102
lrdwo world

etc
Hope you got it.
Topic archived. No new replies allowed.