我正在尝试将此 Pascal 代码转换为 C#。没有编译错误,并且该方法适用于短字符串(4 或 5 个字符)。所有的方法和函数都是等价的,但我的代码抛出这个异常:
System.OverflowException: Value was either too large or too small for a character .
这是 StackTrace
:
in System.Convert.ToChar(Int32 value) in ConsoleApplication3.Program.Encrypt(Boolean encrypt, String word, Int32 startKey, Int32 multKey, Int32 addKey) on c:\Users\TRS\Documents\Visual Studio 2013\Projects\ConsoleApplication3\ConsoleApplication3\Program.cs:line 29 .
这是 Pascal 代码:
function TGenericsF.Encrypter(Encrypt: WordBool; Source: AnsiString;
StartKey, MultKey, AddKey: Integer): AnsiString;
{$R-} {$Q-}
var Counter: LongInt;
S: AnsiString;
Ret: AnsiString;
begin
S := Source;
Ret := '';
for Counter := 1 to Length(S) do
begin
if Encrypt then
begin
Ret := Ret + AnsiChar(Ord(S[Counter]) xor (StartKey shr 8));
StartKey := (Ord(Ret[Counter]) + StartKey) * MultKey + AddKey;
end
else
begin
Ret := Ret + AnsiChar(Ord(S[Counter]) xor (StartKey shr 8));
StartKey := (Ord(S[Counter]) + StartKey) * MultKey + AddKey;
end;
end;
Result := Ret;
end;
这是我等效的 C# 代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
string username = Encrypt(true, "Administrator", 8, 12, 16);
Console.WriteLine(username);
Console.ReadKey();
}
public static string Encrypt(bool encrypt, string word, int startKey, int multKey, int addKey)
{
string encryptedWord = string.Empty;
for (int i = 0; i < word.Length; i++)
{
if(encrypt)
{
encryptedWord += Convert.ToChar(word[i] ^ (startKey >> 8));
startKey = (((int)encryptedWord[i]) + startKey) * multKey + addKey;
}
else
{
encryptedWord += Convert.ToChar(word[i] ^ (startKey >> 8));
startKey = (((int)word[i]) + startKey) * multKey + addKey;
}
}
return encryptedWord;
}
}
}
非常感谢。
最佳答案
解决此问题的第一步是认识到加密对字节数组进行操作,并返回字节数组。这里没有字符串的位置。文本编码只是模糊了加密算法。如果您需要加密一个字符串,您必须首先使用一些明确定义的文本编码将其转换为字节数组。
那么,让我们用该策略重写 Delphi 代码。它看起来像这样:
{$R-} {$Q-}
function EncryptDecrypt(Encrypt: Boolean; const Source: TBytes;
StartKey, MultKey, AddKey: Integer): TBytes;
var
i: Integer;
begin
SetLength(Result, Length(Source));
for i := low(Source) to high(Source) do
begin
if Encrypt then
begin
Result[i] := Source[i] xor (StartKey shr 8);
StartKey := (Result[i] + StartKey) * MultKey + AddKey;
end
else
begin
Result[i] := Source[i] xor (StartKey shr 8);
StartKey := (Source[i] + StartKey) * MultKey + AddKey;
end;
end;
end;
在 C# 中复制它很容易。我们只需要确保以与 Delphi 代码相同的方式允许溢出。这涉及使用 unchecked
。代码运行如下:
public static byte[] EncryptDecrypt(bool Encrypt, byte[] Source,
int StartKey, int MultKey, int AddKey)
{
byte[] Dest = new byte[Source.Length];
for (int i = 0; i < Source.Length; i++)
{
if (Encrypt)
{
unchecked
{
Dest[i] = (byte) (Source[i] ^ (StartKey >> 8));
StartKey = (Dest[i] + StartKey) * MultKey + AddKey;
}
}
else
{
unchecked
{
Dest[i] = (byte) (Source[i] ^ (StartKey >> 8));
StartKey = (Source[i] + StartKey) * MultKey + AddKey;
}
}
}
return Dest;
}
我粗略的测试表明:
- 字节数组 Delphi 代码的行为与问题中的 Delphi 代码相同。
- C# 代码的行为与 Delphi 代码相同。
- 两个版本的代码code都可以忠实地解密加密数组。
您的代码导致错误,因为已检查算术是否有溢出。您的算术溢出了 int
数据类型,因为它是在检查的上下文中执行的,所以溢出会导致错误。文档有详细信息:http://msdn.microsoft.com/en-us/library/khy08726.aspx
unchecked
关键字抑制该错误并允许发生溢出。 Delphi 代码使用 {$Q-}
来达到同样的效果。
关于c# - 用 Pascal 编写与 C# 代码等效的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23809545/