Problème de traduction d'un Checksum Perl en langage C++

Signaler
Messages postés
13
Date d'inscription
mardi 29 juin 2010
Statut
Membre
Dernière intervention
30 juin 2010
-
Messages postés
13
Date d'inscription
mardi 29 juin 2010
Statut
Membre
Dernière intervention
30 juin 2010
-
Bonjour a tous :)
Je suis nouveau sur le site et je viens a votre rencontre car je suis sur un code qui me pose problème depuis quelque jour déjà.

Alors voila mon tuteur de stage m'a demandé de transcrire un code en Perl en C++

Il s'agit d'un code allant chercher des informations sur un capteur et a les sortir après calcul dans une console.
En ce moment je bloque sur la fonction qui permet de calculer un CRC16.

Voici le code en Perl :

#!/usr/bin/perl -w

sub checksum16 ($) {
# calculates the checksum 16 of the given string argument
my @bytes = unpack("C*", $_[0]);
my $sum = 0;
foreach(@bytes) {
$sum += $_;
$sum %= 2**16;
}
return $sum;
}

J'ai essayé plusieurs choses mais même après plusieurs je n'arrive pas a avoir quelques chose de concret.
Cela fait 3 jours que je parcours le net a la recherche d'un tuto ou d'un prototype pour le faire mais je n'arrive pas a faire la correspondance.

Je vous montre une ébauche de ma transcription en C++ :

#include <stdio.h>
#include <math.h>

typedef unsigned int CRC;

CRC crc_16(unsigned char c);

CRC crc_16(unsigned char c)
{
   int i,j,k;

   for(i=0;i!=8;c>>=1,i++)
   {
        j = CRC+CRC;
k = pow(2,16);
     	j = CRC%k;
      	
CRC = j;

   }
   return CRC;
}


Voila si quelqu'un peut me donner quelques infos pour que je puisse avancer un peu cela m'aiderait beaucoup :)

Merci d'avance.




Avoir le refrain beau a rechercher des crosses....serait prendre a revers la haine a écoper...

10 réponses

Messages postés
13
Date d'inscription
mardi 29 juin 2010
Statut
Membre
Dernière intervention
30 juin 2010

J'ai oublié de préciser que mon code en C++ me retourne toujours 0... :p

Avoir le refrain beau a rechercher des crosses....serait prendre a rever la haine a écoper...
Messages postés
13
Date d'inscription
mardi 29 juin 2010
Statut
Membre
Dernière intervention
30 juin 2010

Petit Up car j'avance un peu mais ce n'est pas encore ca :p

J'ai un problème de concordance entre les 2 codes:

Quand j'exécute le code Perl, j'obtiens 116

#!/usr/bin/perl -w

sub checksum16 ($) {
# calculates the checksum 16 of the given string argument
my @bytes = unpack("C*", $_[0]);
my $sum = 0;
foreach(@bytes) {
$sum += $_;
$sum %= 2**16;
}
return $sum;
}
print checksum16 ("t");
print "\n";

et quand j'execute le code C++ avec le même parametre j'obtiens 4294967268

#include <stdio.h>
#include <math.h>
#include <string.h>

typedef const char CRC;

CRC crc_16(unsigned char c)
{
   int i,j,k = 0;

   for(i=0;i!=8;c>>=1,i++)
   {
        k += c;
k %= 1<<16;
   }
   return k;
}

int main()
{
printf("%u",crc_16('t'));
printf ("\n");
return 0;
}



Voila :p
Si quelqu'un sait ce qui ne va pas, qu'il n'hésite pas je suis ouvert a toute critique:p

Cordialement,
Dredd






Avoir le refrain beau a rechercher des crosses....serait prendre a rever la haine a écoper...
Messages postés
3820
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
1 décembre 2020
113
Si on reprend ton exemple en Perl (je met "toto" au lieu de "t"):
#!/usr/bin/perl -w

sub checksum16 ($) {
# calculates the checksum 16
# of the given string argument
    my @bytes = unpack("C*", $_[0]);
    my $sum = 0;
    foreach(@bytes) {
$sum += $_;
$sum %= 2**16;
    }
    return $sum;
}
print checksum16 ("toto");
print "\n";


On observe que l'utilisateur donne une chaîne de caractère et non un seul et unique caractère. Chacun des éléments est alors accumulé dans sum, puis un modulo de 2**16 est fait.
En C:
2**16 => 2 << 15 (et pas 16, fait le décalage sur un papier, tu verras :p)
Une chaine de caractère, c'est char*.

Au final, on peut faire:
#include <stdio.h>

unsigned int crc_16(char* s)
{
  unsigned int sum = 0;
  while (s && *s)
  {
    sum += *s;
    sum %= 2 << 15;
    ++s;
  }

  return sum;
}

int main(void)
{
  printf("%u\n", crc_16("toto"));

  return 0;
}


_____________________________________________
Historique de mes créations, et quelques articles:[ http://0217021.free.fr/portfolio
http://0217021.free.fr/portfolio]
Messages postés
13
Date d'inscription
mardi 29 juin 2010
Statut
Membre
Dernière intervention
30 juin 2010

J'ai enfin réussi :)
Mon problème venait du fait que je ne prenais pas en compte la longueur du caractère.

#include <cstdlib>
#include <cstdio>
#include <string>

typedef const char CRC;

CRC crc_16( char c)
{
   int i,j,k = 0;

   for(i=0;i<sizeof(c);i++)
   {

        k += c;
k %= 2<<16;
c>>=1;
   }
   return k;
}

int main()
{
printf("%d",crc_16('t'));
printf ("\n");
return 0;
}




Avoir le refrain beau a rechercher des crosses....serait prendre a rever la haine a écoper...
Messages postés
3820
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
1 décembre 2020
113
Voir mon commentaire :)
Ton code n'a pas besoin de la boucle, puisque sizeof (c) 1. Donc il n'y a jamais accumulation. Ce qui équivaudrait à faire: printf("%d",crc_16('t'));> printf("%d", 't');



_____________________________________________
Historique de mes créations, et quelques articles:[ http://0217021.free.fr/portfolio
http://0217021.free.fr/portfolio]
Messages postés
13
Date d'inscription
mardi 29 juin 2010
Statut
Membre
Dernière intervention
30 juin 2010

Edit : cela ne marche qui si on met 1 caractère xD

j'ai testé ton code, il marche parfaitement, je me chope un warning mais cela marche quand même :p

Merci beaucoup en tout cas:)

Je retourne a la suite de mon code en Perl:p
Je repasserais surement par ici d'ici peu xD

Cordialement,
Dredd


Avoir le refrain beau a rechercher des crosses....serait prendre a rever la haine a écoper...
Messages postés
3820
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
1 décembre 2020
113
je me chope un warning

Ça m'étonne, j'ai compilé en "-ansi -pedantic" (le mode le plus strict). Quel est le warning ?

_____________________________________________
Historique de mes créations, et quelques articles:[ http://0217021.free.fr/portfolio
http://0217021.free.fr/portfolio]
Messages postés
13
Date d'inscription
mardi 29 juin 2010
Statut
Membre
Dernière intervention
30 juin 2010

je me chope ca :

romain@romain-laptop:~/Documents/Traduction Perl -> C++$ g++ -o test test_sum2.cpp
test_sum2.cpp: In function ‘int main()’:
test_sum2.cpp:18: warning: deprecated conversion from string constant to ‘char*’


Avoir le refrain beau a rechercher des crosses....serait prendre a rever la haine a écoper...
Messages postés
3820
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
1 décembre 2020
113
A ba oui évidemment !
Tu compiles en C++, alors que c'est codé en C !!!

2 solutions:
- Tu le fais en C, et tu compiles avec:
gcc -W -Wall -ansi -pedantic test_sum2.c -o test


- Tu le fais en C++, et tu compiles avec:
g++ -W -Wall -Wabi -pedantic test_sum2.cpp -o test


Avec:
#include 

unsigned int crc_16(const std::string& s)
{
  unsigned int sum = 0;
  const unsigned int size = s.size();
  for (unsigned int i = 0; i < size; ++i)
  {
    sum += s[i];
    sum %= 2 << 15;
  }

  return sum;
}

int main()
{
  std::cout << crc_16("toto") << std::endl;

  return 0;
}


_____________________________________________
Historique de mes créations, et quelques articles:[ http://0217021.free.fr/portfolio
http://0217021.free.fr/portfolio]
Messages postés
13
Date d'inscription
mardi 29 juin 2010
Statut
Membre
Dernière intervention
30 juin 2010

Merci beaucoup de toutes ces précisions CptPingu, cela m'aide beaucoup :)
Tu m'a l'air de t'y connaitre pas mal :p
Je repasserais par ici si j'ai d'autre soucis :)
A la revoyure

Cordialement,
Dredd


Avoir le refrain beau a rechercher des crosses....serait prendre a revers la haine a écoper...