Another string problem

Started by
8 comments, last by Julian90 17 years, 5 months ago
In this program, I am trying to have the user input a sentence or a phrase. From there I want to loop through the whatever the user entered and "encrypt" there input. For instance a would become b, b would become c and so on. Could somebody please help me or give me some hints as what to correct.

int main()
{
	string sentence;
	string alphabet = "abcdefghijklmnopqrstuvwyxz";
	
	cout << "Please enter a sentence: ";
	cin.ignore();
	getline(cin, sentence);
	cout << endl;

	for (int i = 0; i < sentence.length(); i++)
	{
		for (int j = 0; j < alphabet.length(); j++)
		{
			if (alphabet[j] == sentence)
			{
				sentence = alphabet[j+1];
			}
		}
	}
        return 0;
}

Advertisement
The key to this program is that the letters in ASCII are stored in order. That means that the character codes naturally come one after the other, so you don't have to do the mapping yourself:
getline(cin, sentence);for (int i = 0; i < sentence.length(); i++){    if( sentence == 'z' )        sentence = 'a';    else        sentence++;}cout << sentence << endl;

The only thing to worry about is the mapping from 'z' back to 'a'.
HTH
That pretty much sums up that problem. Saves alot of work not having to map it all yourself. Thanks.
Problems in the original (extra complexity notwithstanding):

- What do you want to happen with a 'z'?

- Modifying something that you're looping over while looping over it (here, "sentence") can be tricky. Here, the problem is that the modification will shift the letter to the next one in the alphabet - and then the inner loop continues, checking the next letter in the alphabet. Since the "sentence"'s letter was just shifted as well, it will match *again*. This proceeds all the way through the loop.

You could fix that by breaking out of the (inner) loop, but as noted, a simple rotation cipher is more easily implemented by some arithmetic on the character values.

For more complex, general substitution ciphers, you can build a lookup table - this relies on the idea that chars are a numeric type, so you can use them as array indices.

int main() {  char lookup[256] = {0};  // the array size is the number of possible character values  // and lookup[{some character}] stores the character with which the indexing  // character is replaced.  lookup['a'] = 'b'; // for example.  // Once the array has been set up (nicer if you can do it in the array  // initialization, or better yet by reading it from a file ;) ), you can  // read in the sentence as before:  cout << "Please enter a sentence: ";  string sentence;  // You shouldn't need to 'ignore' at the beginning of the program run.  getline(cin, sentence);  cout << endl;  // And the translation work just becomes:  for (int i = 0; i < sentence.length(); ++i) {    sentence = lookup[sentence];  }}
Quote:
getline(cin, sentence);for (int i = 0; i < sentence.length(); i++){    if( sentence == 'z' )        sentence = 'a';    else        sentence++;}cout << sentence << endl;


Sorry i just cant stand it when i see people do that (although it does help the explenation here so i do understand) but this is exactly what modula arithmatic is for.

getline(cin, sentence);for (int i = 0; i < sentence.length(); i++){        sentence = ((sentance - 'a' + 1) % 26) + 'a';}cout << sentence << endl;
I disagree; I think the code I posted is easier to read and write. What would happen if you made a silly mistake like forgot to add the 1, or forgot to override the operator precedence with parenthesis? A child could understand my version, wheras most programmers would at least have to slow down to read yours.

5 simple lines of code are preferable to 1 complex one.
Quote:5 simple lines of code are preferable to 1 complex one.

I agree here, i guess i just didnt think mine was that much more complex because i like maths (particulary discrete maths and number theory ) :-).
Quote:Original post by Julian90
Sorry i just cant stand it when i see people do that (although it does help the explenation here so i do understand) but this is exactly what modula arithmatic is for.

getline(cin, sentence);for (int i = 0; i < sentence.length(); i++){        sentence = ((sentance - 'a' + 1) % 26) + 'a';}cout << sentence << endl;


Keep in mind the C++ '%' operator does not implement the mod function of mathematics. Oh, sure, it looks like it when applied to positive integers, but for any other numbers all bets are off.

Also, the above code will not work in a localized environemnt. Most of the world is not the United States, so if you're aiming at either professional-quality software (ie,. stuff the marketing suits will be able to hawk to pay your salary) or the respect and admiration of your peers (ie. geeks browsing the internet in their sweats from the basement of their parent's yurt) you might want to stay away from assumptions about alphabets and codesets.

Stephen M. Webb
Professional Free Software Developer

AFAIK, "all bets are off" with 'mod' in mathematics, too. There are at least two reasonable interpretations, one of which will normally be taken by the compiler, and each of which can be useful (and the other very annoying) in different contexts.

But the table lookup takes care of that, is more flexible and handles internationalization much better, too. It's just more work to set up the table is all (again, reading it in from a file is a good idea; but with Unicode that may be unwieldy without some kind of pseudo-compression).
Quote:AFAIK, "all bets are off" with 'mod' in mathematics, too. There are at least two reasonable interpretations, one of which will normally be taken by the compiler, and each of which can be useful (and the other very annoying) in different contexts.


Actualy mod in mathematics is very strictly defined the problem is that definition does not require everything to be redused down to the rand [0,n) were n is the modulas and hence from a theoretical perspective the compiler doing this
53 % 10 = 1753 is perfectly valid.

The actual definition is this...
a = b (mod n) iff a - b = k * n for k an element of ZOR equivelentlya = b (mod n) iff a = k * n + b for k an element of Z

but most people then tack onto the end of that a
"for 0 0 <= b < n"
statment which the compiler doesnt have to and hence i believe your "all bets are off" statement.

Anyhow heres an over the top patch up (only valid for positive numbers valid for all a)
int operator%(int a, int n){    return a - (a / n) * n;}int main(){    getline(cin, sentence);    for (int i = 0; i < sentence.length(); i++)    {        sentence = ((sentance - 'a' + 1) % 26) + 'a';    }    cout << sentence << endl;|


Quote:But the table lookup takes care of that, is more flexible and handles internationalization much better, too. It's just more work to set up the table is all (again, reading it in from a file is a good idea; but with Unicode that may be unwieldy without some kind of pseudo-compression).


In most cases yes ill agree it is more flexible however i can find cases (relativly easier) where it is less flexible or requires a whole lot more work then mod to do the same thing (in the context of SIMPLE ciphers).

Quote:
Keep in mind the C++ '%' operator does not implement the mod function of mathematics. Oh, sure, it looks like it when applied to positive integers, but for any other numbers all bets are off.

Also, the above code will not work in a localized environemnt. Most of the world is not the United States, so if you're aiming at either professional-quality software (ie,. stuff the marketing suits will be able to hawk to pay your salary) or the respect and admiration of your peers (ie. geeks browsing the internet in their sweats from the basement of their parent's yurt) you might want to stay away from assumptions about alphabets and codesets.


actually it does but as mentioned above people tend to conceptually add a tiny bit to the end of that definition. Also using the if for wrap around which is what i was adressing also suffers from the problem of only working with some character sets, In fact the only solution that doesnt (actualy i can think of one other but its more complex :-)) is Zahlman's.

[Edited by - Julian90 on November 20, 2006 11:08:23 PM]

This topic is closed to new replies.

Advertisement