Reputation: 14518
I'm working on this decryption program for a hobby of mine: geocaching.
I have a base list of chars :
[a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,0,1,2,3,4,5,6,7,8,9]
And in a windows form you can specify with which character each character should be replaced.
[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,9,8,7,6,5,4,3,2,1,0]
So this would result in my string to decrypt being converted into uppercase.
example: the quick brown fox jumps over the lazy dog
would result in THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG
public static string DecodeWithKey(string source, string keyBase, string keyValue)
{
StringBuilder sb = new StringBuilder(source);
for (int i = 0; i < keyBase.Length; i++)
{
sb = sb.Replace(keyBase[i], keyValue[i]);
}
return sb.ToString();
}
Now this works fine for the above sample. But it completely fails when you start moving characters around.
So let's say this is my base again:
[a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,0,1,2,3,4,5,6,7,8,9]
And now I'm using a bit more realistic values to be replaced:
[a,b,c,d,t,f,g,h,i,j,k,l,m,n,o,p,q,r,s,p,u,v,w,x,y,z,0,1,2,3,4,5,6,7,8,9]
Notice, I changed e with t and t with p.
The result: the quick brown fox jumps over the lazy dog
becomes php quick brown fox jumps ovpr php lazy dog
As you can see in the
it replaced it to tht
and then to php
. Which is obvious from my logic.
How can I prevent this? so that is shows pht
and doesn't replace a character twice.
I hope I have explained it clearly.
Upvotes: 0
Views: 1150
Reputation: 21888
Why don't you simply build the decoded string character by character rather than modifying a copy of the source in-place?
First, build a dictionary that matches each coded char to its decoded value
public static string DecodeWithKey(string source, Dictionary<char,char> decoder)
{
StringBuilder sb = new StringBuilder(source.Length);
for (int i = 0; i < source.Length; i++)
{
sb.Append( decoder[source[i]] ); // error management left out as an exercice
}
return sb.ToString();
}
In response to Piotr comment, let's try to throw some LINQ into the game:
public static string DecodeWithKey(string source, Dictionary<char,char> decoder)
{
return String.Concat(from ch in source select decoder[ch]);
}
Upvotes: 3
Reputation: 46595
You can use regex replace to do what you want. Have a look at this question.
Convert your replacements to a dictionary, and then:
var regex = new Regex(String.Join("|",map.Keys));
var newStr = regex.Replace(str, m => map[m.Value]);
Upvotes: 1