Le forum (ô combien francophone) des utilisateurs de Powerbuilder.
Salut les experts,
bon, je dois calculer un code (un checksum de contrôle, pour être exact) en fonction d'une chaine de caractère, et dans les spec, pour expliquer, il y a un bout de code en C :
s := ‘XX-YYYY-YYYY’;
r := 0;
for i:=1 to 12 do
r := r xor byte(s[i]);
ZZ := intToHex(r,2);
Sauf qu'en PB, xor, j'ai l'impression que ça n'existe pas.
quelqu'un aurait une idée ?
merci !
Dernière modification par ben147 (20-06-2018 08:02:23)
Hors ligne
Hello, bonne question !
Tu peux aller faire un tour sur le site de Seki, rubrique "PbniCW - Cool Wrappers" :
Fonctions logiques pour unsigned longs BitwiseOr(), BitwiseXor(), BitwiseAnd(), BitwiseNot(), BitwiseLeftShift(), BitwiseRightShift()
Sinon le refaire à l'os en pure PB, sachant que le OR et AND et NOT binaire ne sont pas non plus dispo en pb. (pour info
XOR = (NOT (A AND B)) AND (A OR B)
si je me souviens bien
Mais cela nécessitera de transformer le décimal en binaire avant de faire tes opérations. Sinon peut-être coder une petite DLL qui fait le boulot (non PBNI), je ne crois pas me souvenir qu'il existe une API windows pour ces opérateurs binaires (Bitwise) ni les datawindow expression d'ailleurs.
Une autre solution c'est via le SQL (ici SQL Server supporte nativement AND &, OR |, NOT ~ et XOR ^ :
select a, b, (~ (a & b) & (a | b)) c, a ^ b XOR from ( select 0 a, 0 b union select 0, 1 union select 1, 0 union select 1, 1 ) as ab
a b c XOR ------------ 0 0 0 0 0 1 1 1 1 0 1 1 1 1 0 0
Hors ligne
il te faut surtout le fichier PBX, ensuite tu l'importes dans ton projets ou tu ajoutes la PBD si compatible avec ta version de PB.
Hors ligne
Bonjour,
Sinon en powerbuilder natif, j'avais eu besoin de cette opération pour piloter les TPE. J'avais extrait les 2 méthodes nécessaires de la PowerBuilder Foundation Class :
long uof_bitwisexor(long al_value1, long al_value2) ////////////////////////////////////////////////////////////////////////////// // // Function: of_BitwiseXor // // Access: public // // Arguments: // al_Value1 The first value to be used in the operation (e.g. 55). // al_Value2 The second value to be used in the operation (e.g. 44). // // Returns: Long // The result of the XOR operation (e.g. 27). // If either argument's value is NULL, function returns NULL. // // Description: Performs a bitwise exclusive OR operation (al_Value1 XOR al_Value2), // which exclusively ORs each bit of the values. // (55 XOR 44) = 27 // ////////////////////////////////////////////////////////////////////////////// // // Revision History // // Version // 5.0 Initial version // ////////////////////////////////////////////////////////////////////////////// // /* * Open Source PowerBuilder Foundation Class Libraries * * Copyright (c) 2004-2005, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted in accordance with the GNU Lesser General * Public License Version 2.1, February 1999 * * http://www.gnu.org/copyleft/lesser.html * * ==================================================================== * * This software consists of voluntary contributions made by many * individuals and was originally based on software copyright (c) * 1996-2004 Sybase, Inc. http://www.sybase.com. For more * information on the Open Source PowerBuilder Foundation Class * Libraries see http://pfc.codexchange.sybase.com */ // ////////////////////////////////////////////////////////////////////////////// Integer li_Cnt Long ll_Result Boolean lb_Value1[32], lb_Value2[32] // Check for nulls If IsNull(al_Value1) Or IsNull(al_Value2) Then SetNull(ll_Result) Return ll_Result End If // Get all bits for both values For li_Cnt = 1 To 32 lb_Value1[li_Cnt] = uof_getbit(al_Value1, li_Cnt) lb_Value2[li_Cnt] = uof_getbit(al_Value2, li_Cnt) Next // Perfor the XOR For li_Cnt = 1 To 32 If (lb_Value1[li_Cnt] And Not lb_Value2[li_Cnt]) Or & (Not lb_Value1[li_Cnt] And lb_Value2[li_Cnt]) Then ll_Result = ll_Result + (2^(li_Cnt - 1)) End If Next Return ll_Result boolean uof_getbit(long al_decimal, unsignedinteger ai_bit) ////////////////////////////////////////////////////////////////////////////// // // Function: of_GetBit // // Access: public // // Arguments: // al_decimal Decimal value whose on/off value needs to be determined (e.g. 47). // ai_bit Position bit from right to left on the Decimal value. // // Returns: boolean // True if the value is On. // False if the value is Off. // If any argument's value is NULL, function returns NULL. // // Description: Determines if the nth binary bit of a decimal number is // 1 or 0. // ////////////////////////////////////////////////////////////////////////////// // // Revision History // // Version // 5.0 Initial version // 5.0.03 Fixed problem when dealing with large numbers (>32k) // from "mod int" to "int mod" // ////////////////////////////////////////////////////////////////////////////// // /* * Open Source PowerBuilder Foundation Class Libraries * * Copyright (c) 2004-2005, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted in accordance with the GNU Lesser General * Public License Version 2.1, February 1999 * * http://www.gnu.org/copyleft/lesser.html * * ==================================================================== * * This software consists of voluntary contributions made by many * individuals and was originally based on software copyright (c) * 1996-2004 Sybase, Inc. http://www.sybase.com. For more * information on the Open Source PowerBuilder Foundation Class * Libraries see http://pfc.codexchange.sybase.com */ // ////////////////////////////////////////////////////////////////////////////// Boolean lb_null //Check parameters If IsNull(al_decimal) or IsNull(ai_bit) then SetNull(lb_null) Return lb_null End If //Assumption ai_bit is the nth bit counting right to left with //the leftmost bit being bit one. //al_decimal is a binary number as a base 10 long. If Int(Mod(al_decimal / (2 ^(ai_bit - 1)), 2)) > 0 Then Return True End If Return False
Hors ligne
buck a écrit:
Bonjour,
Sinon en powerbuilder natif, j'avais eu besoin de cette opération pour piloter les TPE. J'avais extrait les 2 méthodes nécessaires de la PowerBuilder Foundation Class :
C'est surement ce qu'il y a de plus simple, après selon le volume de données à traiter par le XOR faut voir.
Hors ligne
Alors le truc, c'est que les arguments pour cette fonction, ce sont des long.
or moi, je dois faire ce code, donc :
s := ‘XX-YYYY-YYYY’; r := 0; for i:=1 to 12 do r := r xor byte(s[i]); ZZ := intToHex(r,2);
avec par exemple s = "A0-3ABE-8D94" ......
en gros de l'hexadécimal dans un string.
du coup, euh ... je sais pas ....
j'avais commencé à coder ça, mais ça marche pas, forcément.
ll_r = 0 for i = 1 to 12 ll_r =bitwisexor(ll_r, left(right(ls_chaine_remote, 11), i)) next
(et donc c'est le ls_chaine_remote qui est égal à "A0-3ABE-8D94")
Dernière modification par ben147 (21-12-2017 10:54:53)
Hors ligne
Hello, j'avais pas tilté mais ton code c'est pas du C mais du Pascal.
Si tu as un pb suffisement récent utilise blob + getbyte :
string ls_chaine_remote = "A0-3ABE-8D94" blob lbl_blob byte lby_byte long ll_r = 0 int i lbl_blob = blob( ls_chaine_remote ) for i = 1 to 12 getByte( lbl_blob, i, ref lby_byte) ll_r = uof_bitwisexor(ll_r, lby_byte) next string ls_zz //ls_zz = to_hex2(r) //my tohex2: string ls_alpha = "0123456789ABCDEF" ls_zz = mid(ls_alpha, 1+ ll_r/16, 1) + mid(ls_alpha, 1 + mod(ll_r,16), 1) messagebox( "xor ops", "got zz="+ls_zz+" from r="+string(ll_r) )
Hors ligne
blob et getbyte ça a l'air de passer, mais au passage de bitwisexor j'ai un bad runtime fonction reference.
bon c'est peut-être parce que j'ai importé la fonction depuis le PBX. je vais essayer en la codant en pb natif, du coup, pour voir.
Hors ligne
Bonjour,
je me permet de ré ouvrir ce topic, parce que visiblement, le calcul de mon checksum n'est pas bon .... et je comprend pas pourquoi ....
voici mon code :
lbl_blob = blob( ls_chaine_remote ) for i = 1 to 12 getByte( lbl_blob, i, ref lby_byte) ll_r = uof_bitwisexor(ll_r, lby_byte) next string ls_alpha = "0123456789ABCDEF" ls_FINREMOTEID = mid(ls_alpha, 1+ ll_r/16, 1) + mid(ls_alpha, 1 + mod(ll_r,16), 1)
avec ls_chaine_remote = "A0-3ABE-8D94"
mon calcul me ramène "6C", et on me dit qu'il devrait ramener "75" ....
et là, je comprend pas .... est-ce que par hasard d'un coup d’œil quelqu'un peut me dire ou est-ce que j'ai foiré ? .....
pour rappel, dans les spec, j'ai ça :
Il s’agit d’un checksum de contrôle basé sur les 12 premiers caractères du REMOTE_ID (tirets compris).
On le calcule en effectuant un « ou exclusif bit-à-bit » sur ces 12 caractères.
La valeur hexadécimale du résultat ainsi obtenu est interprétée comme une chaine de deux caractères également en lettres majuscules.
Exemple :
s := ‘XX-YYYY-YYYY’;
r := 0;
for i:=1 to 12 do
r := r xor byte(s[i]);
ZZ := intToHex(r,2);
Hors ligne