Probléme sur une boucle

Résolu
andoid Messages postés 106 Date d'inscription samedi 31 mars 2012 Statut Membre Dernière intervention 16 juin 2013 - 15 oct. 2011 à 08:44
andoid Messages postés 106 Date d'inscription samedi 31 mars 2012 Statut Membre Dernière intervention 16 juin 2013 - 19 oct. 2011 à 15:09
bonjour!

dans la correction de tp j'ai vu cette boucle que j'arrive pas comprendre

while(*s != 0)
{

for(;isspace(*s);s++);

if(*s == 0)
break;

i++;
for(;!(*s == 0 || isspace(*s));s++);
}
je voulais comprendre ce que font les 2 boucles for

4 réponses

pop70 Messages postés 181 Date d'inscription mardi 6 avril 2010 Statut Membre Dernière intervention 7 janvier 2012 10
16 oct. 2011 à 21:09
Ah je n'étais pas loin
En effet la fonction compte le nombre de mots dans la chaine qu'on lui envoie, ce qui revient à compter le nombre d'espace + 1:

int compte_mots(const char *c)
{
    int i=0;

    while(*c != 0) /* boucle tant que c n'est pas à la fin de la chaine */
    {

        for(; isspace(*c); c++) /* Boucle qui dit commence par rien faire (il n'y a rien avant le premier point virgule), */
        {                   /*     puis tant que c ne pointe pas sur un espace dans la chaine,(isspace renvoie 0 s'il *c n'est pas un espace),
                                   on déplace c d'un caractère sur la droite (c++).
                                */
            ; /* Et dans la boucle on ne fait rien, le point-virgule seul, indique "FAIRE : aucune action". (comme dans le for)*/
        }

        if(*c == 0) /* Si *c est à la fin de la chaine, on quitte le while, */
            break; /* grace au break. */

        i++; /* Sinon, i s'incrémente de 1. */
        for(; !(*c == 0 || isspace(*c)); c++) /* Et puis on refait un boucle qui commence par "ne rien faire", comme la précédente, */
        {                                     /* et qui tant que *c n'est pas à la fin de la chaine (0), ou n'est pas un espace (isspace),
                                              /* alors c se déplace d'un caractère sur la droite. */
            ;  /* Et encore une action vide. */
        }
    }

    return i; /* Enfin on retourne i qui vaut le nombre de mots dans la chaine. (nombre d'espaces + 1) */

}


Ce qu'il faut bien comprendre c'est qu'au départ, le paramètre "c" de compte_mots est un pointeur char, il contient l'adresse de la première lettre d'une chaine (celle passée en argument).
Ensuite, les boucles servent à décaler de 1 l'adresse sur laquelle pointe "c", jusqu'à la fin de la chaine.

Exemple:
Si on fait compte_mots("AB C DEF");
La chaine passée est "AB C DEF\0" le '\0' est rajouté automatiquement de façon à pouvoir trouver la fin de la chaine.
La fin de chaine vaut 0, son code hexadécimal est 0, donc la chaine passée est en réalité (en héxa) : 0x41 0x42 0x20 0x43 0x20 0x44 0x45 0x46 0x00.
Il y a un caractère supplémentaire, que l'on ne voit pas lors de l'affichage.

Au début de la fonction, c pointe sur le premier élément de la chaine, donc A (0x41).
puis on le déplace de 1 sur la droite jusqu'à ce que isspace() soit vrai.
Autrement dit c commence sur A (0x41), puis B(0x42), puis "ESPACE"(0x20). Or à cet instant, isspace renvoit quelque chose différent de 0 car il tombe sur un espace, et on sort donc de la première boucle.

On incrémente i de 1 (donc i 1), puis on regarde si "c" est à la fin de la chaine: if (*c 0) revient à if (*c == 0x00).

Ensuite, on passe au 2ème for, ç'est la même boucle que la précédente, à la différence près que cette fois-ci, si "c" est à la fin de la chaine, on sort également du for.
Donc c va passer de "ESPACE" (0x00) à C(0x43), puis de C à "ESPACE"(0x20), ce qui va provoquer la fin de la boucle, augmenter i de 1(donc i vaut maintenant 2) et ramener au début du while,

On en arrive au premier for une seconde fois, qui va déplacer c de "ESPACE" à D (0x44), puis de D à E (0x45), puis de E à F (0x46), et enfin de F à "fin de chaine"(0x00), c qui stoppe le for et le while.

Et sinon, le if (*c == 0) ne sert strictement à rien, comme au moment où il est appelé, *c vaut forcément un espace, il ne peut pas valloir fin de chaine.
On peut carrément supprimer avec le break, réessaye sans et tu verras qu'il n'y a aucune différence.

Autre chose, isspace ne se contente pas d'être vrai quand il croise un espace: 0x20, il renvoie également vrai s'il tombe sur une tabulation(0x09), un saut de ligne(0x0A), une tabulation verticale (0x0B), un feed (0x0C), et un retour chariot (0x0D).


Voilà, j'espère que c'est un peu plus clair pour toi.


C++dialement,
Pop70
3
pop70 Messages postés 181 Date d'inscription mardi 6 avril 2010 Statut Membre Dernière intervention 7 janvier 2012 10
15 oct. 2011 à 18:17
Salut, avoir le code source en entier permettrait de mieux voir à quoi sert cette portion, toutefois voici un exemple de ce à quoi il pourrait servir:


#include <stdio.h>

int main()
{

    char chaine[] = "test de chaine";
    char *s = chaine;
    int i = 0;

    while(*s != 0) // Tant que s n'est pas arrivé à la fin de la chaine.
    {

        for(; isspace(*s); s++); // Déplace s d'un caractère à droite, à la fin s pointe sur le prochain espace.

        if(*s == 0) // Quitte la boucle si s est sur le caractere de fin de chaine(0).
            break;

        i++; // Incrémentation de i.
        for(; !(*s == 0 || isspace(*s)); s++); /* Tant que s n'est pas à la fin de la chaine
                                                    ou ne vaut pas un espace, s se deplace sur un caractère à droite.
                                                    à la fin de cette boucle s pointe sur l'espace suivant,
                                                    ou la fin de chaine s'il n'y en a pas.*/
    }


    printf ("%d", i); /* Au total i vaut le nombre d'espaces + 1 (caractère de fin de chaine).
                        Dans cet exemple: 3.*/
    return 0;
}


C++dialement,

Pop70
0
andoid Messages postés 106 Date d'inscription samedi 31 mars 2012 Statut Membre Dernière intervention 16 juin 2013
16 oct. 2011 à 19:44
bah tien voici le corps de la fonction:

int compte_mots(const char *c)
{
int i=0;
/*Les charactéres sont considérés comme des int*/
while(*c != 0)
{
/*pour chaque espace blanc rentré j'avance*/
for(;isspace(*c);c++){;}
/*Si *c est nulle je sort de la boucle*/
if(*c == 0)
break;
/*J'incrémente mon compteur */
i++;
for(;!(*c == 0 || isspace(*c));c++){;}
}

return i;

}
0
andoid Messages postés 106 Date d'inscription samedi 31 mars 2012 Statut Membre Dernière intervention 16 juin 2013
19 oct. 2011 à 15:09
Merci
0
Rejoignez-nous