I've just come back into programming after a year since my first year university courses and I've run into a pair of problems with the program I've been working on.
What the program is supposed to do is take a given sentence and mix up the letters, then output the mixed up sentence. It's basically a program to create a Cryptocypher. The challenge is to make sure that the program used a unique letter for each letter of the alphabet of the given sentence.
The problems I've been coming up against is that, first, the letters aren't completely randomized, sometimes the letter matches the one it changes.
Second, in the function that's designed to replace the letters in the sentence, the numbers are replaced but the program seperates the sentence into words instead of the full sentence.
ie -
this
is
a
test
except with the the scrambled letters of course.
The first problem is in Main, the second is in the applyCypher function.
Any help would be greatly appreciated.
***code start***
//Christopher Anderson
//June 14th 2011
//includes for program
#include <iostream>
#include <string>
#include <time.h>
using namespace std;
void applyCypher(string phrase, int length, string base, string cypher)
{
int i;
if (length < 0) //terminating condition
{
cout << "Your cryptocypher phrase is - "<< endl << endl;
cout << phrase;
return;
}
else
{
for (i = 0 ; i < 26; i++) // checks to see if the current character matches the cypher and then replaces it.
{
if (phrase[length] == base[i])
{
phrase[length] = cypher[i];
}
}
}
applyCypher(phrase, length-1, base, cypher); //calls the next instance of the function
return;
}
int main()
{
string base ("abcdefghijklmnopqrstuvwxyz");
string phrase;
string cypher;
int check [26];
int Randomize;
int length;
srand ( time(NULL) );
// Intro
cout << "Welcome to Cryptocypher 1.0." << endl;
cout << "This program created by Christopher Anderson for free use." << endl;
cout << endl;
// Load the first string
cout << "Please enter the word or phrase, lower case only, for conversion." << endl;
cout << "Enter '0' to quit" << endl;
cout << endl;
cin >> phrase;
while ( phrase != "0" ) //Exit condition
{
length = phrase.length(); //gets the string length for later.
// building the randomization.
for (int i = 0; i < 27; i++)
{
Randomize = rand() % 27;
for (int a = i; a >= 0; a--) //checks to see if the random letter has been used before
{
if (Randomize == check[a])
{
Randomize = rand() % 27;
a = i;
}
}
cout << Randomize << endl;
check[i] = Randomize;
cypher.append(base,Randomize,1); // Adds the randomized letter onto the cypher and repeats.
}
for (int b = 0; b < 26; b++) //Clearing check array for next loop
{
check[b] = 30;
}
cout << base << endl;
cout << cypher << endl;
cout << endl;
applyCypher(phrase, length, base, cypher); //Calling ittertion function to switch the new letters
cout << endl;
phrase = ""; //clearing phrase and cypher strings for next loop
cypher = "";
cout << endl;
// next loop prompt
cout << "Please enter the word or phrase, lower case only, for conversion." << endl;
cout << "Enter '0' to quit" << endl;
cout << endl;
cin >> phrase;
}
for (int i = 0; i < 27; i++)
{
Randomize = rand() % 27;
for (int a = i; a >= 0; a--) //checks to see if the random letter has been used before
{
if (Randomize == check[a])
{
Randomize = rand() % 27;
a = i;
}
}
...
}
In the above, you should replace all instances of 27 with 26. As it is, you have indeces [0..26] which is one more than the number of letters in the alphabet.
cin >> phrase;
Use getline(cin,phrase); instead. This will get any inputted spaces correctly.
1 2 3 4 5 6 7
for (i = 0 ; i < 26; i++) /*checks to see if the current character matches the cypher and then replaces it.*/
{
if (phrase[length] == base[i])
{
phrase[length] = cypher[i];
}
}
You should break; from this loop after you've reassigned the letter. Otherwise, the (new) letter may be replaced again. Also, shouldn't you initially pass in length-1 to applyCypher? Checking phrase[length] where length is the actual length of the string would mean you're looking at the string termination character '\0'. I would also suggest renaming the parameter, "length" in applyCypher to "currentIndex" or something similar because after you decrement it, it is no longer the length of the string.
the letters aren't completely randomized, sometimes the letter matches the one it changes
Well there is a 1/26 probability that the chosen letter in the cipher will be the same as the base. After you call Randomize = rand() % 26;, you should check that Randomize is not the same as i.
Hey thanks shacktar, that really helped, the break and getline suggestions worked and it's running fine now.
I had to tweek the check loop too, it's now checking against the cypher itself rather than the check array which seems to have solved the problem with the repeating letters.
One last question though. I tried to give this program to a friend of mine, but she's getting an error message when she tries to open it.
"This program can't start because cygwin1.dll is missing from your computer. Try reinstalling the program to fix the problem."
Now I get from that that she can't run the program because somehow it's still dependent on the compiler or at least to my computer. My question is, is there a way to code or compile the program so that it can be run on any computer?
Barring that, you may have to find cygwin1.dll on your computer and package it with your program's exe (i.e. put it in the same directory). In this case, hopefully cygwin1.dll doesn't depend on too many other dlls. If it depends on other dlls, then you would have to package those as well...
There's an app you can use called Dependency Walker (depends.exe) which shows you what dlls your program depends on. It's very useful for deploying programs. http://www.dependencywalker.com/