【问题标题】:Convert C++ function to C#将 C++ 函数转换为 C#
【发布时间】:2011-12-24 07:29:08
【问题描述】:

我正在尝试将以下 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#?

【问题讨论】:

  • 已用可能有用的信息更新了我的答案
  • 我假设 QString 是一个 QT 类?我添加了标签。

标签: c# c++ qt porting


【解决方案1】:

编辑我怀疑您的代码实际上对输入数据进行了 MD5 摘要。 有关基于该假设的 sn-p,请参见下文。

翻译步骤

一些应该很好用的提示1

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

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

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

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

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

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

问: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 明确未优化,旨在作为快速提示;根据需要进行优化

【讨论】:

  • 我使用 System.Security 添加了一个 md5 实现,因为我怀疑(在谷歌搜索原始代码之后)它可能是 MD5。注意:这只不过是一种怀疑(我不太容易识别哈希函数的代码))
  • 确定它不是 MD5,因为我在此函数之前计算 MD5,并且此函数的输入是 MD5 哈希,但感谢一些提示。
  • 我们可以去掉小文本吗?
【解决方案2】:

更多提示:

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); - 从输入中取一个数字并将其十六进制值添加到您从表格中查找的 a 中。 (我假设 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,那么 toLocal8Bit 应该与 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 写成一个合乎逻辑的 &amp; 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");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-17
    • 2016-02-27
    相关资源
    最近更新 更多