将C++函数转换为C#

Convert C++ function to C#

本文关键字:转换 函数 C++      更新时间:2023-10-16

我正在尝试将以下C++函数移植到C#:

QString Engine::FDigest(const QString & input)
{
    if(input.size() != 32) return "";
    int idx[] = {0xe, 0x3, 0x6, 0x8, 0x2},
        mul[] = {2, 2, 5, 4, 3},
        add[] = {0x0, 0xd, 0x10, 0xb, 0x5},
        a, m, i, t, v;
    QString b;
    char tmp[2] = { 0, 0 };
    for(int j = 0; j <= 4; j++)
    {
        a = add[j];
        m = mul[j];
        i = idx[j];
        tmp[0] = input[i].toAscii();
        t = a + (int)(strtol(tmp, NULL, 16));
        v = (int)(strtol(input.mid(t, 2).toLocal8Bit(), NULL, 16));
        snprintf(tmp, 2, "%x", (v * m) % 0x10);
        b += tmp;
    }
    return b;
}

其中一些代码很容易移植,但我在这部分遇到了问题:

tmp[0] = input[i].toAscii();
t = a + (int)(strtol(tmp, NULL, 16));
v = (int)(strtol(input.mid(t, 2).toLocal8Bit(), NULL, 16));
snprintf(tmp, 2, "%x", (v * m) % 0x10);

我发现(int)strtol(tmp, NULL, 16)等于C#中的int.Parse(tmp, "x")snprintfString.Format,但我不确定其余部分

如何将这个片段移植到C#?

编辑我怀疑您的代码实际上对输入数据进行了MD5摘要。请参阅以下基于该假设的片段。

翻译步骤

一些提示应该工作良好1

Q:tmp[0] = input[i].toAscii();

bytes[] ascii = ASCIIEncoding.GetBytes(input);
tmp[0] = ascii[i];

Q:t = a + (int)(strtol(tmp, NULL, 16));

t = a + int.Parse(string.Format("{0}{1}", tmp[0], tmp[1]),
               System.Globalization.NumberStyles.HexNumber);

Q:v = (int)(strtol(input.mid(t, 2).toLocal8Bit(), NULL, 16));

没有关于toLocal8bit的线索,需要阅读Qt文档。。。

Q:snprintf(tmp, 2, "%x", (v * m) % 0x10);

{
    string tmptext = ((v*m % 16)).ToString("X2");
    tmp[0] = tmptext[0];
    tmp[1] = tmptext[1];
}

如果。。。它只是MD5

你可以直接尝试一下,看看它是否达到了你需要的效果:

using System;
public string FDigest(string input)
{
   MD5 md5 = System.Security.Cryptography.MD5.Create();
   byte[] ascii = System.Text.Encoding.ASCII.GetBytes (input);
   byte[] hash  = md5.ComputeHash (ascii);
   // Convert the byte array to hexadecimal string
   StringBuilder sb = new StringBuilder();
   for (int i = 0; i < hash.Length; i++)
       sb.Append (hash[i].ToString ("X2")); // "x2" for lowercase
   return sb.ToString();
}

1明确未优化,旨在作为快速提示;根据需要优化

更多提示:

t是一个两字节的缓冲区,并且只写入第一个字节,留下一个尾随的nul。因此,t总是一个恰好由一个字符组成的字符串,并且一次处理一个十六进制数字的字符。所以我认为

tmp[0] = input[i].toAscii();
t = a + (int)(strtol(tmp, NULL, 16));

这大致是int t = a + Convert.ToInt32(input.substring(i, 1), 16);——从输入中取一位数字,并将其十六进制值添加到您从表中查找的值中。(我假设toAscii只是将已经是十六进制数字的QString字符映射到strtol的ASCII中,所以如果你已经有一个十六进制数字字符串,这是可以的。(

下一个

v = (int)(strtol(input.mid(t, 2).toLocal8Bit(), NULL, 16));

这意味着从偏移量t的输入中查找两个字符,即input.substring(t, 2),然后再次将它们转换为十六进制整数。v = Convert.ToInt32(input.substring(t, 2), 16);现在,碰巧的是,我认为你实际上只会在这里使用第二个数字,因为计算是(v * a) % 0x10,但是嘿。如果我们再次使用十六进制数字的QString,那么toLocal8应该与toAscii是相同的转换——我不清楚为什么您的代码在这里有两个不同的函数。

最后将这些值转换为tmp中的一个数字,然后将其附加到b

snprintf(tmp, 2, "%x", (v * m) % 0x10);
b += tmp;

(2是缓冲区的长度,由于我们需要一个尾随的nul,所以只写了1(即

int digit = (v * m) % 0x10;
b += digit.ToString("x");

应该这样做。我个人会把mod 16写成一个逻辑和& 0xf,因为它的目的是把值降到一个数字。

还要注意,在您的代码中,i从未被设置过——我想这是一个循环还是您为了简洁而省略的东西?

总之,

int t = a + Convert.ToInt32(input.substring(i, 1), 16);
int v = Convert.ToInt32(input.substring(t, 2), 16);
int nextDigit = (v * m) & 0xf;
b += nextDigit.ToString("x");