[Débutant] Incrémeter une chaine unsigned char

Incrémeter une chaine unsigned char [Débutant] - C - Programmation

Marsh Posté le 28-05-2006 à 14:22:26    

Salut,
 
J'ai un variable :
unsigned char chaine[]={0x00,0x00,0x00,...,0x00};
 
Je souhaites l'incrémenter :
{0x01,0x00,0x00,...,0x00};
{0x02,0x00,0x00,...,0x00};
....
jusqu'à
{0xFF,0xFF,0xFF,...,0xFF};
 
Google est pas trés bavard sur le sujet...
Merci d'avance :)

Reply

Marsh Posté le 28-05-2006 à 14:22:26   

Reply

Marsh Posté le 28-05-2006 à 14:34:32    

strikenet a écrit :

Google est pas trés bavard sur le sujet...


C'est comme si tu demandais à google comment boucler de 1 à 10. Il y a des trucs que personne n'écrit car il suffit d'un peu de réflexion...
 

strikenet a écrit :

unsigned char chaine[]={0x00,0x00,0x00,...,0x00};
 
Je souhaites l'incrémenter :
{0x01,0x00,0x00,...,0x00};
{0x02,0x00,0x00,...,0x00};
....
jusqu'à
{0xFF,0xFF,0xFF,...,0xFF};


 
Sois tu utilises une fonction récursive, sois tu fais des boucles imbriquées

for (chaine[10]=0; chaine[10] < 0xff; chaine[10]++)
{
    for (chaine[9]=0; chaine[9] < 0xff; chaine[9]++)
    {
        etc <...>
    }
}


 
Au fait, tu pourras jamais aller jusqu'à 0xff car si tu écris

for (chaine[x]=0; chaine[x] <= 0xff; chaine[x]++)
    <...>


Ben une fois que la chaine[x] atteint 0xff et qu'elle est incrémentée, elle repasse à 0 (hé oui, elle ne fait qu'un char) => boucle infinie !!!

Message cité 1 fois
Message édité par Sve@r le 28-05-2006 à 14:38:11

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 28-05-2006 à 15:46:13    

Pourquoi tu parles d'utiliser des fonctions récursives alors que ce n'est pas un problème récursif ?
 
Sinon moi je ferai un truc du genre :

Code :
  1. #include <stdio.h>
  2. int lastValue(unsigned char *chaine, int taille)
  3. {
  4.   while (taille--)
  5.   {
  6.     if (chaine[taille] != 0xFF)
  7.       return 0;
  8.   }
  9.   return 1;
  10. }
  11. void inc(unsigned char *chaine, int taille)
  12. {
  13.   int i;
  14.   for (i = 0; i < taille; ++i)
  15.   {
  16.     if (++chaine[i])
  17.       break;
  18.   }
  19. }
  20. int main()
  21. {
  22.   unsigned char chaine[] = {0, 0};
  23.   int taille = 2;
  24.   while (!lastValue(chaine, taille))
  25.   {
  26.     inc(chaine, taille);
  27.     printf ("%X %X\n", chaine[0], chaine[1]);
  28.   }
  29. }

Reply

Marsh Posté le 28-05-2006 à 18:42:00    

Tarabiscote a écrit :

Pourquoi tu parles d'utiliser des fonctions récursives alors que ce n'est pas un problème récursif ?

tout est récursif :

Code :
  1. #include <stdio.h>
  2. void inc(unsigned char *chaine, int taille)
  3. {
  4. if (taille)
  5. {
  6.  while (*chaine != 0xFF)
  7.   (*chaine)++;
  8.  inc(++chaine,--taille);
  9. }
  10. }
  11. int main(void)
  12. unsigned char chaine[] = {0, 0}; 
  13. int taille = 2;
  14. inc(chaine, taille);   
  15. printf ("%X %X\n", chaine[0], chaine[1]); 
  16. return 0;
  17. }

Je suis d'accord avec toi que ça ne présente aucun intérêt; mais bon.

Message cité 1 fois
Message édité par Trap D le 28-05-2006 à 18:43:07
Reply

Marsh Posté le 28-05-2006 à 19:29:38    

Enfin ce n’est pas ce que j'appelle du récursif.
Pour moi faire quelque chose de récursif, c'est (en très gros) réutiliser les valeurs précédentes afin de résoudre le problème.
Par exemple avec les tours de Hanoi (je sais exemple très connu) si on connais l'ensemble des coups précédents on peut trouver immédiatement le coup suivant, en itératif (on connais uniquement la situation actuel) c'est tout de suite plus dur (quand je dit dur c'est pas seulement écrire l'algorithme mais surtout la complexité du calcul).
 
Sinon quand on dit que les fonctions en C sont récursives c'est parce qu'elles recopient les valeurs hors ici seul les pointeurs sont recopié donc ce n’est pas vraiment récursif (a moins que les anciens pointeurs te servent à quelque chose ?), tu aurais du plutôt recopier les tableaux à chaque appel (enfin je suis d’accord c’est inutile de faire du récursif donc on s’en passera).

Reply

Marsh Posté le 28-05-2006 à 19:33:50    

non ce que tu décris c'est le terme "incrémental"

Reply

Marsh Posté le 28-05-2006 à 19:35:12    

Trap D a écrit :

tout est récursif :

Code :
  1. #include <stdio.h>
  2. void inc(unsigned char *chaine, int taille)
  3. {
  4. if (taille)
  5. {
  6.  while (*chaine != 0xFF)
  7.   (*chaine)++;
  8.  inc(++chaine,--taille);
  9. }
  10. }
  11. int main(void)
  12. unsigned char chaine[] = {0, 0}; 
  13. int taille = 2;
  14. inc(chaine, taille);   
  15. printf ("%X %X\n", chaine[0], chaine[1]); 
  16. return 0;
  17. }

Je suis d'accord avec toi que ça ne présente aucun intérêt; mais bon.


 
Ca ne serait pas plutôt:
 

Code :
  1. #include <stdio.h>
  2. void inc(unsigned char *chaine, int taille)
  3. {
  4. if (taille)
  5. {
  6.  while (*chaine != 0xFF) {
  7.                 (*chaine)++;
  8.                 inc(++chaine,--taille);
  9.                 }
  10. }
  11. }
  12. int main(void)
  13. unsigned char chaine[] = {0, 0}; 
  14. int taille = 2;
  15. inc(chaine, taille);   
  16. printf ("%X %X\n", chaine[0], chaine[1]); 
  17. return 0;
  18. }

Message cité 1 fois
Message édité par simple_stupid le 28-05-2006 à 19:36:37
Reply

Marsh Posté le 28-05-2006 à 20:38:00    

Sve@r a écrit :


Ben une fois que la chaine[x] atteint 0xff et qu'elle est incrémentée, elle repasse à 0 (hé oui, elle ne fait qu'un char) => boucle infinie !!!


 
ouai, enfin tout overflow arithmetique entraine un comportement indefini (ca peut revenir à 0 ou rester bloqué au max ou autre). Il vaut mieux repasser explicitement à 0  :)

Reply

Marsh Posté le 28-05-2006 à 20:59:14    

KangOl a écrit :

non ce que tu décris c'est le terme "incrémental"


Qu’est ce que tu veux dire par incrémental ?
 
Sinon je n'arrive toujours pas à voir où est le récursif quand on empile des paramètres juste pour le plaisir de dépiler après que le calcul ne soit terminé.
L'intérêt c'est quand même bien d'utiliser ce que l'on a empilé non ?
 
Bien sûr le programme est récursif mais cette petite partie récursive ne fait absolument rien enfin ce n'est que mon point de vu.

Reply

Marsh Posté le 28-05-2006 à 21:11:59    

http://fr.wikipedia.org/wiki/Fonction_r%C3%A9cursive
c'est clairement le cas ici !
 
par incrémental, je veux juste dire qu'on se base sur ce qui a été calculé avant pour faire le calcul courant
la plupart du temps pour résoudre ce genre de problème de manière fonctionnel, on utilise la récursivité

Reply

Marsh Posté le 28-05-2006 à 21:11:59   

Reply

Marsh Posté le 28-05-2006 à 21:15:48    

simple_stupid a écrit :

Ca ne serait pas plutôt:
 

Code :
  1. #include <stdio.h>
  2. void inc(unsigned char *chaine, int taille)
  3. {
  4. if (taille)
  5. {
  6.  while (*chaine != 0xFF) {
  7.                 (*chaine)++;
  8.                 inc(++chaine,--taille);
  9.                 }
  10. }
  11. }
  12. int main(void)
  13. unsigned char chaine[] = {0, 0}; 
  14. int taille = 2;
  15. inc(chaine, taille);   
  16. printf ("%X %X\n", chaine[0], chaine[1]); 
  17. return 0;
  18. }


Ben non  :non:  
Programme testé  :D  

Reply

Marsh Posté le 28-05-2006 à 21:28:20    

Code :
  1. void inc(unsigned char *chaine, size_t taille)
  2. {
  3. if (!taille)
  4.  return;
  5. if (*chaine == 0xFF)
  6.  inc(chaine + 1, taille - 1);
  7. else
  8.  ++*chaine;
  9. }

m'enfin ...

Reply

Marsh Posté le 28-05-2006 à 21:49:54    

Taz a écrit :

Code :
  1. void inc(unsigned char *chaine, size_t taille)
  2. {
  3. if (!taille)
  4.  return;
  5. if (*chaine == 0xFF)
  6.  inc(chaine + 1, taille - 1);
  7. else
  8.  ++*chaine;
  9. }

m'enfin ...

Je suis fatigué où c'est vous, le but du jeu c'est d'obtenir 0xFF partout, pas 1 2 (simple_stupid) ou 1 0 (Taz) ...
Tu voulais sans doute écrire  

Code :
  1. void inc(unsigned char *chaine, int taille)
  2. {
  3. if (taille)
  4. {
  5.  (*chaine)++;
  6.  if (*chaine != 0xFF)
  7.  {
  8.   inc(chaine,taille);
  9.  }
  10.  else
  11.   inc(++chaine, --taille);
  12. }
  13. }


Reply

Marsh Posté le 28-05-2006 à 22:00:50    

Sinon y'a ça aussi en stock

Code :
  1. void inc(unsigned char *chaine, int taille)
  2. {
  3. while (--taille >= 0)
  4. {
  5.  while(++chaine[taille] != 0xFF)
  6.   ;
  7. }
  8. }

Reply

Marsh Posté le 28-05-2006 à 22:05:26    

???
 
memset(chaine, 0xFF, taille).

Reply

Marsh Posté le 28-05-2006 à 22:07:17    

skelter a écrit :

enfin tout overflow arithmetique entraine un comportement indefini (ca peut revenir à 0 ou rester bloqué au max ou autre).


Pas en C !!!
 

Tarabiscote a écrit :

Enfin ce n’est pas ce que j'appelle du récursif.
Pour moi faire quelque chose de récursif, c'est (en très gros) réutiliser les valeurs précédentes afin de résoudre le problème.


Faire qqchose de récursif c'est s'appeler soi-même. Et t'es pas obligé de renvoyer une valeur calculée lors de l'appel infèrieur. Tu peux très bien avoir des fonctions récursives de type "void"
Regarde cet exemple

Code :
  1. void affiche(
  2. unsigned long nb   /* Nombre à afficher */
  3. unsigned short base)  /* Base d'affichage */
  4. {
  5. /* Vérification fin récursivité */
  6. if (nb == 0)
  7.  return;   /* Fin récursivité */
  8. /* Appel récursif */
  9. affiche(nb / base, base);
  10. /* Affichage du reste (affiché lors de la remontée) */
  11. printf("%hu", nb % base);
  12. }


 
Tu passes à "affich" un nombre (par exemple 250) et une base (par exemple 7) et il t'affiche le nombre "250" en base "7" (en l'ocurrence 505)...
Oui, je sais, strtoul() le fait aussi mais c'était pour donner un exemple de récursivité sans récupération de valeur...


Message édité par Sve@r le 28-05-2006 à 22:31:53

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 28-05-2006 à 22:31:56    

Trap D a écrit :

Sinon y'a ça aussi en stock

Code :
  1. void inc(unsigned char *chaine, int taille)
  2. {
  3. while (--taille >= 0)
  4. {
  5.  while(++chaine[taille] != 0xFF)
  6.   ;
  7. }
  8. }



T'as pas compris ce qu'il voulait faire.
 
Il veut toutes les valeurs de
{0, 0, ..., 0}
à
{0xff, 0xff, ..., 0xff}
 
en passant par exemple par:
 
{0,1, 18, 0xf}
 
 
Ton code donne pas toutes ces possibilités.
D'ailleurs, c'est stupide, parce que si c'est juste pour arriver à ton résultat, un memset suffit.

Reply

Marsh Posté le 28-05-2006 à 22:33:30    

Taz a écrit :

???
 
memset(chaine, 0xFF, taille).


Je crois qu'il veut aussi un affichage de chaque valeur intermédiaire (enfin c'est mon avis)  :D  
 
Si strikenet lit tout ce qu'on a écrit, il va vraiment nous prendre pour des foldingos [:ddr555]


Message édité par Sve@r le 28-05-2006 à 23:00:09

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 28-05-2006 à 23:00:23    

C'est bien ce que je disais, je suis fatigué  :D

Reply

Marsh Posté le 28-05-2006 à 23:18:07    

Bon, j'espère que j'ai compris maintenant :

Code :
  1. void inc(unsigned char *chaine, int taille)
  2. {
  3. int t= 0;
  4. while (t < taille)
  5. {
  6.  t = 0;
  7.  printf("%d %d %d\n", chaine[0], chaine[1], chaine[2]);
  8.  while (t < taille && ++chaine[t] == 0xFF)
  9.  {
  10.   chaine[t] = 0;
  11.   t++;
  12.  }
  13. }
  14. }

, j'ai testé l'affichage sur 3 caractères et seulement jusqu'à 3, sinon j'y suis encore à 2 heures du matin.
 

Reply

Marsh Posté le 28-05-2006 à 23:29:59    

Trap D a écrit :

Bon, j'espère que j'ai compris maintenant :

Code :
  1. printf("%d %d %d\n", chaine[0], chaine[1], chaine[2]);



On peut rendre l'affichage indépendant de la taille de la chaîne

Code :
  1. for (i=0; i < taille; i++)
  2. printf("%d ", chaine[i]);
  3. printf("\n" );


 

Trap D a écrit :

j'ai testé l'affichage sur 3 caractères et seulement jusqu'à 3, sinon j'y suis encore à 2 heures du matin.


Tu peux réduire la plage de valeurs possibles en remplaçant "0xff" par "0x05"
 
PS: Ca sent bizarrement le "brute force hack" cet algo... :sol:

Message cité 1 fois
Message édité par Sve@r le 28-05-2006 à 23:30:32

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 28-05-2006 à 23:30:34    

KangOl a écrit :

http://fr.wikipedia.org/wiki/Fonction_r%C3%A9cursive
c'est clairement le cas ici !
 
par incrémental, je veux juste dire qu'on se base sur ce qui a été calculé avant pour faire le calcul courant
la plupart du temps pour résoudre ce genre de problème de manière fonctionnel, on utilise la récursivité


 
Je remet pas en cause le fait que le programme soit bien récursif mais juste le fait que ça n’a aucun rapport avec le problème présent autrement dit dans le code généré il suffit (grosso modo) de remplacer le call par un jmp et ça fait le même chose si ce n’est que ça supprime la récursivité qui ne fait absolument rien ici à part empiler et dépilé inutilement un pointeur et un entier dont on ne réutilisera jamais la valeur.
 
Donc oui on peut toujours écrire des fonctions récursives et non le problème ci-dessus n’est pas récursif.
 
Voila j’espère que je suis plus clair cette fois. :)

Reply

Marsh Posté le 29-05-2006 à 00:44:43    

tout est recursif. Et la meilleur maniere d'ecrire ce genre de cochonenrie c'ets un algo recursif.  :o

Reply

Marsh Posté le 29-05-2006 à 01:27:53    

Joel F a écrit :

tout est recursif. Et la meilleur maniere d'ecrire ce genre de cochonenrie c'ets un algo recursif.  :o


Si c'est une cochonerie de force 8, pas de problèmes :  
 
http://mapage.noos.fr/emdel/goret.htm


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 29-05-2006 à 08:20:58    

Sve@r a écrit :

Tu peux réduire la plage de valeurs possibles en remplaçant "0xff" par "0x05"
 
PS: Ca sent bizarrement le "brute force hack" cet algo... :sol:

C'est ce que j'avais fait  :)  
Pour ce qui est du hack, tout à fait d'accord.

Reply

Marsh Posté le 29-05-2006 à 09:57:42    

bah alors pareil que moi mais de droite à gauche ?

Reply

Marsh Posté le 29-05-2006 à 10:00:12    

Emmanuel Delahaye a écrit :


Si c'est une cochonerie de force 8, pas de problèmes :
http://mapage.noos.fr/emdel/goret.htm


 
Je ne vois pas pourquoi , on ets plus en 1980 et les compilo gére correctement ce genre de code ...

Reply

Marsh Posté le 29-05-2006 à 10:28:11    

#  Plus d'un return par fonction
 
pascal ?

Reply

Marsh Posté le 29-05-2006 à 11:31:24    

Joel F a écrit :

Je ne vois pas pourquoi , on ets plus en 1980 et les compilo gére correctement ce genre de code ...


La récursion terminale (tail recursion), oui. Mais si il faut de la pile, tout peut arriver...

Code :
  1. void free_list (struct node *p)
  2. {
  3.    if (p->next != NULL)
  4.    {
  5.       free_list (p->next);
  6.       free (p);
  7.    }
  8. }


C'est joli, mais ça peut fumer...

Message cité 2 fois
Message édité par Emmanuel Delahaye le 29-05-2006 à 11:31:58

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 29-05-2006 à 11:33:10    

Taz a écrit :

#  Plus d'un return par fonction
pascal ?


 :ouch:  Tu parles du Pascal ? Je parle du C...
 


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 29-05-2006 à 11:36:20    

Emmanuel Delahaye a écrit :

La récursion terminale (tail recursion), oui. Mais si il faut de la pile, tout peut arriver.


C'est clairement le cas du probléme ...

Reply

Marsh Posté le 29-05-2006 à 11:45:50    

Joel F a écrit :

C'est clairement le cas du probléme ...


Quel problème ?
 


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 29-05-2006 à 12:24:05    

Comme on parlait de récursif, voilà une méthode :

Code :
  1. void inc(char *str, int ind, int taille)
  2. {
  3. if (ind == taille)
  4. {
  5.  int i;
  6.  for(i = 0; i < taille; i++)
  7.   printf("%02X ", (unsigned char) str[i]);
  8.  puts("" );
  9. }
  10. else
  11. {
  12.  char *tmp = malloc(taille);
  13.  if (tmp != NULL)
  14.  {
  15.   memcpy(tmp, str, taille);
  16.   do
  17.   {
  18.    inc(tmp, ind+1, taille);
  19.   }
  20.   while(++tmp[ind] != 0x00);
  21.   free(tmp);
  22.  }
  23.  else
  24.  {
  25.   fprintf(stderr, "Pb malloc\n" );
  26.   exit(0);
  27.  }
  28. }
  29. }


Message édité par Trap D le 29-05-2006 à 12:26:53
Reply

Marsh Posté le 29-05-2006 à 18:42:39    

Salut,
 
Maintenant j'ai le choix. Merci à tous ! :hello:
Il ne me reste plus qu'à étudier vos codes. Je retourne sur Dev C++.
 
Merci encore.

Reply

Marsh Posté le 29-05-2006 à 19:15:48    

strikenet a écrit :

Salut,
 
Maintenant j'ai le choix. Merci à tous ! :hello:
Il ne me reste plus qu'à étudier vos codes. Je retourne sur Dev C++.
 
Merci encore.


T'as pas tellement le choix. Le seul code potable est celui de Trap D qui est simple et élégant. Tous les autres c'est que du délire sur la récursivité (qu'il faut éviter chaque fois qu'on peut)...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 29-05-2006 à 19:20:48    

et genre le code de Trap D c'est pas du recursif ? [:pingouino]

Reply

Marsh Posté le 29-05-2006 à 20:31:48    

Emmanuel Delahaye a écrit :

Si c'est une cochonerie de force 8, pas de problèmes :  
http://mapage.noos.fr/emdel/goret.htm


Heureusement que je ne programme pas en C, sinon mon code serai probablement inclassable, ou obligerait l'ajout d'une onzième force qui inclurait les dix précédentes. Enfin, je crois qu'il y a un peu de parti pris, et c'est normal, c'est ta page  ;)

Reply

Marsh Posté le 29-05-2006 à 20:34:36    

++fab a écrit :

Heureusement que je ne programme pas en C, sinon mon code serai probablement inclassable, ou obligerait l'ajout d'une onzième force qui inclurait les dix précédentes. Enfin, je crois qu'il y a un peu de parti pris, et c'est normal, c'est ta page  ;)


Tu as tout compris.


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 29-05-2006 à 20:54:36    

Emmanuel Delahaye a écrit :

La récursion terminale (tail recursion), oui. Mais si il faut de la pile, tout peut arriver...

Code :
  1. void free_list (struct node *p)
  2. {
  3.    if (p->next != NULL)
  4.    {
  5.       free_list (p->next);
  6.       free (p);
  7.    }
  8. }


C'est joli, mais ça peut fumer...


 
Les compilos C arrivent à reconnaitre une récursion terminale et à "l'applatir" ?


---------------
Me: Django Localization, Yogo Puzzle, Chrome Grapher, C++ Signals, Brainf*ck.
Reply

Marsh Posté le 29-05-2006 à 21:03:47    

Joel F a écrit :

et genre le code de Trap D c'est pas du recursif ? [:pingouino]


Je parlais de sa fonction postée le 28 mai...

Code :
  1. void inc(unsigned char *chaine, int taille)
  2. {
  3.     int t= 0;
  4.     while (t < taille)
  5.     {
  6.         printf("%d %d %d\n", chaine[0], chaine[1], chaine[2]);
  7.         t = 0;
  8.         while (t < taille && ++chaine[t] == 0xFF)
  9.         {
  10.             chaine[t] = 0;
  11.             t++;
  12.         }
  13.     }
  14. }


Message édité par Sve@r le 29-05-2006 à 21:06:30

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed