为什么我的Luhn校验和在Windows上正确计算但在Android上没有计算?

Ple*_*rds 0 delphi android

Luhn在Internet上获得此功能,当我为Windows32 VCL编译它时它是正确的.但是当我编译它以在Android应用程序中使用时,我得到了一个False而不是True我怀疑它是因为它正在转换为utf8期望ascii被转换的字节.

那么我该怎么做才能在Android上正常工作呢?

function Luhn(Code: string): Boolean;
var
    i, sum: integer;
    temp: byte;
begin
{ calcula o algorítimo luhn, usado no iccid }
    sum := 0;
    for i:= length(Code) downto 1 do
    begin  // Run the characters backwards
      temp := byte(Code[i])-48;             // Convert from ASCII to byte
      if (length(Code)-i) mod 2 = 0
        then sum := sum + temp             // Odd characters just add
        else if temp < 5
           then sum := sum + 2*temp        // Even characters add double
           else sum := sum + (2*temp)-9;   // or sum the digits of the doubling
    end;
    Result := sum mod 10 = 0;              // Return true if sum ends in a 0
    if Result then
      Toast(Code+#13+'True')
    else
      Toast(Code+#13+'False');

end;
Run Code Online (Sandbox Code Playgroud)

Rem*_*eau 6

像David所说,这个问题与桌面和移动编译器默认情况下不同地索引字符串有关.字符串在桌面编译器中仍然是1索引的,但在移动编译器中默认为0索引.这在文档中描述:

从桌面迁移Delphi代码到移动设备| 使用0-Based Strings

要使代码以您不必处理ZBS差异的方式工作,您可以:

  1. 用于{$ZEROBASEDSTRINGS OFF}在移动设备上返回基于1的索引

    {$IFDEF NEXTGEN}
      {$ZEROBASEDSTRINGS OFF}
    {$ENDIF}
    
    function Luhn(Code: string): Boolean;
    var
      i, sum: integer;
      temp: byte;
    begin
      { calcula o algorítimo luhn, usado no iccid }
      sum := 0;
      for i := Length(Code) downto 1 do begin  // Run the characters backwards
        temp := byte(Ord(Code[i]))-48;  // Convert from ASCII to byte
        if (Length(Code)-i) mod 2 = 0 then
          sum := sum + temp             // Odd characters just add
        else if temp < 5 then
          sum := sum + (2*temp)         // Even characters add double
        else
          sum := sum + (2*temp) - 9;    // or sum the digits of the doubling
      end;
      Result := sum mod 10 = 0;         // Return true if sum ends in a 0
      if Result then
        Toast(Code+#13+'True')
      else
        Toast(Code+#13+'False');
    end;
    
    {$IFDEF NEXTGEN}
      {$ZEROBASEDSTRINGS ON}
    {$ENDIF}
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用Low(String)High(String)系统功能:

    function Luhn(Code: string): Boolean;
    var
      i, sum: integer;
      temp: byte;
    begin
      { calcula o algorítimo luhn, usado no iccid }
      sum := 0;
      for i := High(Code) downto Low(Code) do begin  // Run the characters backwards
        temp := byte(Ord(Code[i]))-48;  // Convert from ASCII to byte
        if (High(Code)-i) mod 2 = 0 then
          sum := sum + temp             // Odd characters just add
        else if temp < 5 then
          sum := sum + (2*temp)         // Even characters add double
        else
          sum := sum + (2*temp) - 9;    // or sum the digits of the doubling
      end;
      Result := sum mod 10 = 0;         // Return true if sum ends in a 0
      if Result then
        Toast(Code+#13+'True')
      else
        Toast(Code+#13+'False');
    end;
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用TStringHelper助手类:

    uses
      ..., SysUtils;
    
    function Luhn(Code: string): Boolean;
    var
      i, sum: integer;
      temp: byte;
    begin
      { calcula o algorítimo luhn, usado no iccid }
      sum := 0;
      for i := Code.Length-1 downto 0 do begin  // Run the characters backwards
        temp := byte(Ord(Code.Chars[i]))-48;  // Convert from ASCII to byte
        if (Code.Length-1-i) mod 2 = 0 then
          sum := sum + temp             // Odd characters just add
        else if temp < 5 then
          sum := sum + (2*temp)         // Even characters add double
        else
          sum := sum + (2*temp) - 9;    // or sum the digits of the doubling
      end;
      Result := sum mod 10 = 0;         // Return true if sum ends in a 0
      if Result then
        Toast(Code+#13+'True')
      else
        Toast(Code+#13+'False');
    end;
    
    Run Code Online (Sandbox Code Playgroud)


Dav*_*nan 5

问题是,默认情况下,字符串为零,基于移动编译器,但默认情况下基于桌面编译器.您需要调整代码以解决此问题.更改

Code[i]
Run Code Online (Sandbox Code Playgroud)

Code[i-1]
Run Code Online (Sandbox Code Playgroud)

我推荐使用

{$ZEROBASEDSTRINGS ON}
Run Code Online (Sandbox Code Playgroud)

如果您希望在移动和桌面目标之间共享代码.详情请访问:http://docwiki.embarcadero.com/RADStudio/en/Zero-based_strings_(Delphi)


一些旁白:

  • 这里根本没有UTF-8.
  • 代码非常脆弱,并且在ASCII范围之外的代码点可能会失败.一些健全检查是谨慎的.
  • 我建议使用ord()从字符中获取序数值.
  • 您可能会考虑使用内在odd()函数而不是显式mod测试.

所以,我个人会写这样的代码:

function LuhnChecksumValid(const Value: string): Boolean;
var
  C: Char;
  Digit: Integer;
  Sum: Integer;
  OddChar: Boolean;
begin
  if Value.Length=0 then
    Exit(False);

  Sum := 0;
  OddChar := odd(Value.Length);
  for C in Value do
  begin
    Digit := ord(C) - ord('0');
    if not InRange(Digit, 0, 9) then
      Exit(False);
    if OddChar then
      inc(Sum, Digit)
    else if Digit < 5 then
      inc(Sum, 2*Digit)
    else
      inc(Sum, 2*Digit - 9);
    OddChar := not OddChar;
  end;
  Exit((9*Sum) mod 10 = 0);
end;
Run Code Online (Sandbox Code Playgroud)

请注意,我故意避免使用索引.这样做可以让我们完全支持零基或一基指数的问题.