-
How to change letters of string?
Hi, I'm working my way through a book called "Information Security: Principles and Practice". At the end of each chapter there are problems that the author deals out to make sure you comprehend what you just read. Well, a lot of the problems are encrypted strings using the ceasar cipher, and I'm trying to shift the letters in a string to decrypt the string. How can I do this in C++?
Thanks for the help,
Nathan
-
Re: How to change letters of string?
What kind of string are you using?
char *, std::string or CString?
In case it is a char *, you can do the following:
Code:
char *pCursor = pszString;
while('\0' != *pCursor)
{
*pCursor = *pCursor + whatever; // Here you can modify every single char
pCursor++; // advance to next char
}
In case of std::string or CString, there are functions for replacing strings.
Or, you could get a ptr to the bytes and then use what I wrote above.
Hope that helps,
Andy
-
Re: How to change letters of string?
I haven't written the program yet, cause I wasn't sure how :) In your code you posted does it actually change a letter? I don't understand it very well, sorry. I'm kind of new to C++ so thanks for the help :)
-
Re: How to change letters of string?
No, but in the loop you can add/subtract the number you want (I understand that is what Caesarian cipher is, adding 3 to 'A', so it becomes 'D'.
E.g.
'A' + 3 = 'D' and
'D' - 3 = 'A'
If you don't understand why, look at an ASCII table.
-Andy
-
Re: How to change letters of string?
Ok, but what does pszString mean?
-
Re: How to change letters of string?
How about;
Code:
int main()
{
std::string s = "Hello";
std::cout << s << std::endl;
for(int index=0; index < s.length(); index++)
{
s[ index ] = s[ index ] + 1;
}
std::cout << s << std::endl;
system("PAUSE");
return 0;
}
Output
-
Re: How to change letters of string?
So adding a number to a letter will shift the letter by the numbers amount?
-
Re: How to change letters of string?
Quote:
Originally Posted by Nathand
So adding a number to a letter will shift the letter by the numbers amount?
as suggested earlier look at the asciitable.
search asciitable on google...
-
Re: How to change letters of string?
@namezero111111: Warning, your encoded string may contain nul character.
Or, assuming that the source character set contains only A-Za-z and space, the destination character set doesn't match the source character set.
-
Re: How to change letters of string?
When I try to compile that C++ program I get: http://rafb.net/paste/results/fHSKTq95.html.
-
Re: How to change letters of string?
@Nathand: Check that you include the <string> and <iostream> headers (both of them must be included).
-
Re: How to change letters of string?
A proper cipher (assuming only capital letters in the source)
Code:
char *in = source;
char *out = *dest; // assuming dest is pre-allocated
while (*in)
{
*out = ((*in -'A') + offset) %26;
in++; // not optimal, but possibly easier to read for a beginner...
out++;
}
*out = 0; // terminate the output.
-
Re: How to change letters of string?
You were right :) I forgot to add "#include <string>.
Thanks,
Nathan
-
Re: How to change letters of string?
TheCPUWizard: Wouldn't it be:
Code:
*out = 'A' + ((*in -'A') + offset) %26;
:p
And if space characters have to be handled:
Code:
if (*in == ' ') *out=*in;
else *out = 'A' + ((*in -'A') + offset) %26;
Yes, I know, space characters are not encrypted, it's very weak, but AFAIK, the original caesar encryption algorithm does that.
-
Re: How to change letters of string?
Ok, last question :)
When I use this code:
Code:
#include <iostream>
#include <string>
int key = 1;
int main()
{
std::string s = "CSYEVIXIVQMREXIH";
std::cout << s << std::endl;
for(int i = 0; i < 26; i++)
{
for(int index=0; index < s.length(); index++)
{
s[ index ] = s[ index ] + key;
}
std::cout << s << std::endl;
key += 1;
}
system("PAUSE");
return 0;
}
The caesar's cipher is "youareterminated", but the program returns "_ouareterminated". Why would this be? This also happens with some other ciphers I tried.
And if someone feels so inclined to compile and run this on their system, let me know if you get a very strange "beeping" noise coming from your computer?
Thanks,
Nathan
-
Re: How to change letters of string?
Quote:
Originally Posted by Nathand
The caesar's cipher is "youareterminated", but the program returns "_ouareterminated". Why would this be?
My new tagline --
Have you debugged your code?
You've written the program and it runs. Debugging is part of the programming process.
Regards,
Paul McKenzie
-
Re: How to change letters of string?
What exactly do you mean by "debugged" your code?
-
Re: How to change letters of string?
Quote:
Originally Posted by Nathand
Ok, last question :)
When I use this code:
Code:
#include <iostream>
#include <string>
int key = 1;
int main()
{
std::string s = "CSYEVIXIVQMREXIH";
std::cout << s << std::endl;
for(int i = 0; i < 26; i++)
{
for(int index=0; index < s.length(); index++)
{
s[ index ] = s[ index ] + key;
}
std::cout << s << std::endl;
key += 1;
}
system("PAUSE");
return 0;
}
The caesar's cipher is "youareterminated", but the program returns "_ouareterminated". Why would this be? This also happens with some other ciphers I tried.
And if someone feels so inclined to compile and run this on their system, let me know if you get a very strange "beeping" noise coming from your computer?
Thanks,
Nathan
It's due to the fact that ('Y' + the_original_encoding_key) / 26 was equal to 1+(any_other_letter_of_the_string + the_original_encoding_key)/26
In other words, 'Y' wrapped around once while other characters don't.
Actually, it's easy to see that the_original_encoding_key==4.
But, your current algorithm is incorrect... It doesn't compute things modulo 26.
Since the_decoding_key is -4 or 26-4==22 modulo 26, your program shouldn't work at all... In fact, you should never screen any value that re-creates anything looking a bit with the original text.
But an amazing thing happened! The lower case a-z characters are above the upper-case A-Z characters in the ASCII table, and, 'a'='A'+32, 'b'='B'+32
So, for decoding_key==28, your program will output something that really looks like the original text, except that you've lower case letters, and 'Y' will be translated to 'y'-26=='a'-2=='_'
But, you'll say that you don't test for decoding_key==28...
But, you do!
You iteratively modify the original string, and consequently, you're testing for decoding_key==0, decoding_key==1, decoding_key==3, decoding_key==6, decoding_key=10 and so on...
0+1+2+3+4+5+6+7 happens to be equal to 28
So, your 8th 'deciphered string' is equal to _ourareterminated
Amazing, isn't it?
Code:
#include <iostream>
#include <string>
int main()
{
std::string s = "CSYEVIXIVQMREXIH";
std::cout << s << std::endl;
for(int i = 0; i < 26; i++)
{
for(int index=0; index < s.length(); index++)
{
s[ index ] = 'A'+(s[ index ]-'A' + 1)%26;
}
std::cout << s << std::endl;
}
system("PAUSE");
return 0;
}
Should work better (warning, it has not been tested, currently I've no compiler under the hand).
PS: the 'beeping' is probably character #7 that you get because you end up adding large numbers to your characters that wrap around 256.
-
Re: How to change letters of string?
Quote:
Originally Posted by Nathand
What exactly do you mean by "debugged" your code?
Programming isn't just writing code, running the code, and then hoping everything works. Part of programming is called "debugging", which means finding the errors in the logic in your code. Every programmer must know how to debug their own code.
This is done by using printf() or cout() statements, or using the debugging facilities provided to you by the compiler you're using, or just using pencil and paper to step through the logic in the code. These are skills that should be learned on the first, if not second day of programming.
What if the program was much more complex? How will you find the error? How do programmers such as SupeKoko and others able to find the problem?
The bottom line is that you have a running program, and it doesn't produce the output or results you wanted, then take it on yourself to figure it out by debugging the code. Sure, you got an instant answer, but IMO this takes away from you actually learning the skills needed for programming, especially if you come across another problem. However, sometimes the reasons for the error are not obvious, even during debugging -- then and only then should you call for help in figuring out a problem.
Regards,
Paul McKenzie
-
Re: How to change letters of string?
-
Re: How to change letters of string?
SuperKoko - Thank you for your very informative post. I'm still trying to figure out what you said :)
I really appreciate all the help,
Nathan
-
Re: How to change letters of string?
SuperKoko - In your post you said:
"It's due to the fact that ('Y' + the_original_encoding_key) / 26 was equal to 1+(any_other_letter_of_the_string + the_original_encoding_key)/26."
In C++ would that be
Code:
#include <iostream>
#include <string>
int main()
{
std::string s = "Y";
s[0] = (s[0] - 4) / 26;
std::cout << s;
s[0] = 1 + (86 - 4)/26;
std::cout << s;
system("PAUSE");
}
Because I tried that and got two different values?
Sorry for not being good at programming :(
-Nathan
-
Re: How to change letters of string?
Quote:
Originally Posted by Nathand
SuperKoko - In your post you said:
"It's due to the fact that ('Y' + the_original_encoding_key) / 26 was equal to 1+(any_other_letter_of_the_string + the_original_encoding_key)/26."
I was refering to the non-C++ values of characters in the alphabetical table.
In C++, it would be:
Code:
#include <iostream>
int main()
{
std::cout << (('Y'-'A')+4)/26 << " equal " << 1+(('O'-'A')+4)/26 << '\n'; // untested, but it should display: 1 equal 1
}
In other words:
'Y'-'A' == 24 (Y is the character #24 in the alphabetical table, starting from zero).
'Y'-'A'+4 == 28 and consequently, it should wrap around with a correctly written caesar encoding algorithm.
i.e. (('Y'-'A')+4)/26==1
For other characters, the base alphabetical value is smaller than 26-4, and consequently, after being added 4, they're still below 26 and ((the_character-'A')+4)/26==0 and ((the_character-'A')+4)%26==
((the_character-'A')+4).
Assuming the key is any number < 26 or >=26 having a remainder equal to 4 modulo 26, the general C++ formula is:
(('Y'-'A')+key)/26 == 1+(('O'-'A')+key)/26
And, given in non-C++ terms (a formula applying on usual alphabetic codes: 'A'=0, 'B'=1, etc.):
('Y'+key)/26 = 1+('O'+key)/26
That is just a mean to say that 'Y' is not added the same absolute value than other characters in the original text sample.
That explains why you can have a resulting "decoded" string that looks a bit like the original except for the 'Y' character.
-
Re: How to change letters of string?
Ok, thanks for the help.
I'm having a little trouble understanding this code:
Code:
std::cout << (('Y'-'A')+4)/26 << " equal " << 1+(('O'-'A')+4)/26 << '\n';
Because the code above (which you posted), prints "1 equal 1" just like you said it would.
But this code:
Code:
std::cout << (('Y'-'A')+4) << " equal " << 1+(('O'-'A')+4) << '\n';
Prints "28 equal 19". Which doesn't make sense to me, considering the only things I removed were the
So what I'm having trouble understanding is why 28 dived by 26 (1.07) equals 19 divided by 26 (0.73)?
Thank you for the help.
-
Re: How to change letters of string?
Quote:
Originally Posted by Nathand
Code:
std::cout << (('Y'-'A')+4) << " equal " << 1+(('O'-'A')+4) << '\n';
Prints "28 equal 19". Which doesn't make sense to me, considering the only things I removed were the
So what I'm having trouble understanding is why 28 dived by 26 (1.07) equals 19 divided by 26 (0.73)?
Thank you for the help.
/ is the integer division.
In other words, it returns the quotient of the euclidian division.
28 divided by 26 has a quotient equal to 1
18 divided by 26 has a quotient equal to 0, and, adding 1 gives 1.
Note that division has a higher precedence than addition.
Consequently:
1+(('O'-'A')+4)/26
Is NOT 19/26
It is interpreted as:
1+((('O'-'A')+4)/26)
And is equal to 1+(18/26), NOT (1+18)/26
Consequently, it is equal to 1+0
And, 1+0=1 :)
-
Re: How to change letters of string?
Right! *smacks himself*
Because when using integers you don't use decimal points right? Just whole numbers?