【问题标题】:Python: XOR each character in a stringPython:对字符串中的每个字符进行异或
【发布时间】:2015-11-09 04:47:45
【问题描述】:

我正在尝试验证一个字符串的校验和,在这种情况下,它是通过对每个单独的字符执行 XOR 来计算的。

给定我的测试字符串:

check_against = "GPGLL,5300.97914,N,00259.98174,E,125926,A"

我想它会很简单:

result = 0
for char in check_against:
    result = result ^ ord(char)

我知道结果应该是28,但是我的代码给出了40

我不确定文本应该采用什么编码,尽管我已经尝试在 utf-8ascii 中进行编码/解码,但结果相同。

我在 C 中通过简单地对 char 数组进行 XOR 实现了相同的算法,得到了完美的结果,那么我错过了什么?

编辑

所以不久前,我在 C 中实现(我认为的)相同的东西。我知道它是在一个 Objective-C 项目中,但我认为我只是这样做了。完全错误,首先有一个步骤,我将末尾的校验和字符串值转换为十六进制,如下所示(我在这里填写了一些东西,所以我只粘贴相关的内容):

 unsigned int checksum = 0;
 NSScanner *scanner = [NSScanner scannerWithString:@"26"];
 [scanner scanHexInt:&checksum];

然后我做了以下计算校验和:

 NSString sumString = @"GPGLL,5300.97914,N,00259.98174,E,125926,A";
 unsigned int sum = 0;
 for (int i=0;i<sumString.length;i++) {
     sum = sum ^ [sumString characterAtIndex:i];
 }

那我就这样比较:

 return sum == checksum;

【问题讨论】:

  • 另一种检查原始值的方法map(ord, check_against),然后使用operator.xor 减少它,就像reduce(xor, map(ord, check_against))。在 python 3 中,它将是 functools.reduce
  • 我相信对于您给定的示例字符串 utf-8ascii 是死路一条,因为 ASCII 字符在 Unicode 中具有相同的值。 bytearray(check_against, encoding='utf-8') == bytearray(check_against) 在 Python 2 中返回 True
  • 另外,最后,你的 C 代码是什么?我确信答案是base10 中的40 和base16 中的0x28。您是如何使用 C 生成输出 28 的?
  • 我刚刚将您的 Python 代码直接移植到 C 并验证结果是正确的 40。链接:ideone.com/YK8FOp
  • 最后一点,似乎没有人承认这一点:printf("%x\n", 40); 导致28 被打印出来。

标签: python checksum


【解决方案1】:

因此,正如 @metatoaster、@XD573 和 cmets 中的其他一些人帮助弄清楚的那样,问题在于结果(以 10 为底)与我想要的解决方案(以 16 为底)之间的差异。

代码的结果,40 是正确的 - 以 10 为底,但是我试图达到的正确值,28 以 16 为底给出。只需将解决方案从 16 底转换为 10 底,即可像这样的例子:

int('28', 16)

我得到40,计算结果。

【讨论】:

    【解决方案2】:
    #python3
    str = "GPGLL,5300.97914,N,00259.98174,E,125926,A"
    cks = 0
    i = 0
    
    while(i<len(str)):
        cks^=ord(str[i])
        i+=1
    
    print("hex:",hex(cks))
    print("dec:",cks)
    

    【讨论】:

      【解决方案3】:

      我创建了如下所示的 C 版本:

      #include <stdio.h>
      #include <string.h>
      
      int main()
      {
          char* str1="GPGLL,5300.97914,N,00259.98174,E,125926,A";
          int sum = 0;
          int i = 0;
      
          for (i; i < strlen(str1); i++) {
              sum ^= str1[i];
          }
      
          printf("checksum: %d\n", sum);
      
          return 0;
      }
      

      当我编译并运行它时:

      $ gcc -o mytest mytest.c
      $ ./mytest
      checksum: 40
      

      这让我相信您从等效 C 代码中得出的假设是不正确的。

      【讨论】:

      • 你是对的,我只是用我的(Objective C,忘了它不仅仅是在 C 中)代码添加了一个编辑。我当前的代码缺少将校验和转换为十六进制作为我认为的字符串。另外,我认为通常数字的十六进制值和字符串值之间存在一些混淆,包括我自己。
      猜你喜欢
      • 2016-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-18
      • 2022-01-13
      • 2015-09-11
      • 2017-05-21
      • 1970-01-01
      相关资源
      最近更新 更多