2016-08-16 2 views
1

J'ai le code suivant dans C qui va générer des clés basées sur le numéro de série d'entrée.complément de bits d'un caractère dans C# vs C overflowexception

unsigned int32 passkey(unsigned int32 snumber) 
{ 
    char snstring[11]; 
    unsigned int32 pwd; 
    int i = 0; 
    itoa(snumber,10,snstring); 
    do{ 
     snstring[i+1] -= '0'; 
     snstring[i] = ~snstring[i+1]; 
     snstring[i] &= 0x07; 
     i++; 
    }while(i < 9); 
    snstring[9] <<= 1; 
    snstring[9] &= 0x07; 
    pwd = atoi32(snstring); 
    return (pwd); 
} 

J'ai besoin de convertir en code C#, j'ai essayé suivante:

private uint ComputeKey(uint snumber) 
     { 
      char[] snstring = new char[11]; 
      UInt32 pwd; 
      int i = 0; 
      snstring = snumber.ToString().ToCharArray(); 

      do 
      { 
       snstring[i + 1] = Convert.ToChar(snstring[i + 1] - '0'); 
       snstring[i] = Convert.ToChar(~Convert.ToInt32(snstring[i + 1])); 
       snstring[i] &= Convert.ToChar(Convert.ToInt32(0x07)); 
       i++; 
      } while (i < 9); 
      snstring[9] <<= 1; 
      snstring[9] &= Convert.ToChar(0x07); 
      pwd = Convert.ToUInt32(snstring); 
      return (pwd); 
     } 

programmes génère une exception sur snstring[i] = Convert.ToChar(~Convert.ToInt32(snstring[i + 1])); cette ligne.

Un autre comportement notable est que, par exemple, j'ai entrée comme

Ensuite, cette valeur de ligne snstring[i] = Convert.ToChar(~Convert.ToInt32(snstring[i + 1])); de snstring[i+1] est '\u0005' Et il jette OverflowException était Unhandled.

Je ne suis pas sûr de ce que je devrais faire, toute aide est appréciée.

+0

Le résultat de '~ Convert.ToInt32 (snstring [i + 1])' ne peut pas être converti en char comme il est hors de la plage. Faites avec. –

+0

Arrête la conversion entre 'int' et' char'. Convertir en 'int' une fois, appliquer tous les bits twiddling, puis reconvertir. – Phylogenesis

+0

Pourquoi ne pas utiliser la bonne vieille fonction c workign? Voir: http://stackoverflow.com/a/11593657/3989673 – bigahega

Répondre

1

J'ai effectué une tâche similaire, c'est-à-dire prendre un nombre comme entrée et faire exactement ce que votre code fait en C#. Je prends la chaîne comme entrée et la chaîne de retour cependant. Voici le code:

private string ComputeKey(string serialnumber) 
     { 
      if (string.IsNullOrEmpty(serialnumber)) 
      { 
       throw new Exception("Cannot generate a key from a null or empty string"); 
      } 

      serialnumber += '\0'; 
      var length = serialnumber.Length; 
      byte[] snbytes = Encoding.UTF8.GetBytes(serialnumber); 
      for (int i = 0; i < length - 1; i++) 
      { 
       snbytes[i + 1] -= 0x30; 
       snbytes[i] = (byte)~snbytes[i + 1]; 
       snbytes[i] &= 0x07; 
      } 
      snbytes[length - 1] <<= 1; 
      snbytes[length - 1] &= 0x07; 

      var sb = new StringBuilder(); 
      for (int j = 0; j < length - 1; j++) 
      { 
       sb.Append(snbytes[j].ToString()); 
      } 

      return sb.ToString(); 
     } 
1

Lorsque vous inversez les bits d'un int 32 bits représentant un char, qui a toujours un octet dans C, vous vous retrouvez avec les trois octets supérieurs définis sur 0xFF. Cependant, C supprime heureusement les octets supérieurs en assignation à char, tandis que le convertisseur C# lève une exception.

Vous pouvez résoudre ce problème en utilisant une distribution en place de conversion pour correspondre à ce que C fait:

snstring[i+1] -= '0'; 
snstring[i] = (char)(~snstring[i+1] & 0x07); 

Essentiellement, la distribution indique C# explicitement faire la même chose que C fait par défaut.

+1

Vous vous retrouvez avec les octets supérieurs mis à 0xFF en C aussi, en raison de la promotion d'entier. Mais C est laxiste et permet à l'affectation de revenir directement au type lvalue, sans produire de diagnostic. Autrement dit, le code C robuste devrait également faire un cast implicite au type prévu directement après '~', par exemple '(unsigned char) ~ snstring [i + 1]'. (Vous ne voulez pas utiliser 'char' pour cela en C, car il a une signature mal définie.) – Lundin

+0

Correction, merci! – dasblinkenlight