Commentaire sur un code en C

jeff -  
lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   -
Bonsoir à tous , je vous présente un programme qui est une version réduite à l'essentiel du programme UNIX wc ( word count ) . Ce programme compte les lignes , les caractères , les mots en définissant un mot approximativement comme toute séquence de caractères qui ne contient ni espace , ni tabulation , ni fin de ligne :

Je vais commenter ce code jusqu'à ce que je sache le faire , à la fin j'arrive pas à le commenter , j'ai besoin de votre aide svp
#include <stdio.h>

#define DEDANS 1 /*à l'intérieur d'un mot*/
#define DEHORS 0 /*à l'extérieur d'un mot*/

int main()

{

int c, nl, nm, nc, etat; /* déclaration des variables à utiliser dans le programme */

etat = DEHORS;
nl = nm = nc = 0;

/*affectation des valeurs aux variables*/

while ( (c = getchar() ) != EOF) / tant que la variable c prendre un caratère en entrée différent de EOF )
{
++nc; /* on compte le nombre de caractères */
if ( c == '\n' ) 
++nl;

/* si ce caractère est une fin de ligne , on compte les lignes , enfin on les incrémente */
if ( c == ' ' || c == 'n\' || c == '\t' ) /* si le caractère pris en entrée est une fin de ligne , une tabulation ou un espace */ et ensuite je n'arrive plus à comprendre la logique du programme , l'état est DEHORS ok ? MAIS 0 PARTIR DU ELSE IF... çà donne : si l'état est dehors alors l'état = dedans? çà va pas...
etat = DEHORS;
else if ( etat == DEHORS )
{
etat = DEADANS;
++nm;
}
}
printf("%d %d %d\n", nl, nm, nc);
}




5 réponses

  1. teebo Messages postés 33585 Date d'inscription   Statut Contributeur Dernière intervention   1 797
     
    Salut

    En fait mettons que tu ais:

    Ceci est mon texte.


    Quand tu arrives au premier espace, tu remarques que tu es dehors (sous entendu, d'un mot), tu reboucles, et si tu as un caractère normal (pas espace, ni tab, ni retour charriot, autrement dit une lettre ou un chiffre (manque d'ailleurs les ponctuations, passons)) et que tu étais "dehors" alors tu comptes un mot de plus et tu remets ton compteur à dedans...

    J'éspère avoir éclairé, sinon hésite pas à redemander, j'ai bien compris le truc mais mon explication me semble pas tiptop...
    0
  2. jeff
     
    ton explication n'est pas si mal , mais là où il faudrait m'éclairer alors c'est sur ton "reboucle" :

    elfe if ( etat == DEHORS ) /* donc si l'état de la variable est DEHORS , autrement dit qu'on sort d'un mot */

    etat = DEDANS; /* etat devient DEDANS , çà va pas j'ai du mal là , c'est surement le rebouclage que tu as voulu m'expliquer mais j'ai pas bien saisi la structure de ce doee alorrs */

    mais on est d'accord que la variable etat est simplement là pour compter les mots , pas les lignes ni les caractères...
    0
  3. teebo Messages postés 33585 Date d'inscription   Statut Contributeur Dernière intervention   1 797
     
    Bon, je te réécris le programme en pseudo code vite fait avec juste la partie intéressante...

    while (not EOF)
        if (char actuel est une fin de mot)
            etat=dehors
        else if (etat=dehors)
            nm++;
            etat=dedans;
    


    Donc en fait tu arrives à la fin d'un mot (à un caractère qui est "dehors" du mot), tu dis que tu es dehors, et tu boucle (ton while), si le caractère suivant est une lettre, tu passes dans le else, tu remarques que avant tu étais dehors, alors tu précises que tu rentre "dedans" un mot, et tu augmentes ton compteur.

    Tu pourrais te passer éventuellement de ça en faisant

    while (not EOF)
        if (char actuel est une fin de mot)
             nm++;
    


    Mais tu courerais le risque d'avoir deux espaces et donc de compter

    je[ ][ ]teste
    Comme 3 mots(les [] sont là que pour la compréhensions de mes deux espaces...)

    C'est mieux?

    0
  4. jeff
     
    oui c'est plus clair merci beaucoup
    0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
     
    Salut,

    Une version reduite en Perl.
    J'ai le même résultat que wc
    [lamitest@localhost bin]$ cat suppr_espace_dans_fichier.pl | wc -l
    8
    [lamitest@localhost bin]$ cat suppr_espace_dans_fichier.pl | wc -w
    16
    [lamitest@localhost bin]$ cat suppr_espace_dans_fichier.pl | wc -c
    130
    [lamitest@localhost bin]$
    

    Script perl
    #! /usr/bin/perl -w
    
    use strict;
    $"="\n"; # separateur de liste pour affichage
    my @nb_mots;
    my @nb_caracteres;
    while(<>){
            push @nb_mots,$_=~/\w[^\W]+/g;# mot=tout caractère mot sauf les caractères spéciaux
            push @nb_caracteres,$_=~/./gsm; # n'importe quel caractère
    }
    print "Nombre lignes : $.\n";
    print "Nombre mots : ",scalar @nb_mots,"\nNombre caractères : ",scalar @nb_caracteres,"\n";
    ######## le calcul s'arrête ici #########
    # affiche mots et caractères comptés - pour voir à l'écran - pas obligatoire dans le code
    print "-" x 5,"Les mots qui sont comptés","-" x 5,"\n@nb_mots\n";
    print "-" x 5,"Les caractères qui sont comptés","-" x 5,"\n";
    
    # affichage des caractères et leur code Ascii
    
    foreach (@nb_caracteres){
    print $_," - ",ord $_,"\n";
    }
    
    

    Mais c'est délicat. Comment tu veux qu'on considère :
    chomp(my ?
    Comme 2 mots : chomp et my
    ou comme un seul puisuqu'il n'y a pas d'espace.
    /\w[^\W]/ dans ce cas j'ai chomp et my donc 2 mots
    /[^\t\n\s]/ dans ce cas j'ai chomp(my comme un seul mot
    

    1. Le fichier que j'ai utilisé comme exemple (un autre script).
    #! /usr/bin/perl -w
    
    use strict;
    
    print "Entrez une phrase : ";
    chomp(my $chaine=<STDIN>);
    $chaine=~s/\s+/x/g;
    print "$chaine\n";
    

    2. Le résultat
    [lamitest@localhost bin]$ perl wc_en_perl_v_reduite.pl suppr_espace_dans_fichier.pl 
    Nombre lignes : 8
    Nombre mots : 16
    Nombre caractères : 130
    -----Les mots qui sont comptés-----
    usr
    bin
    perl
    use
    strict
    print
    Entrez
    une
    phrase
    chomp
    my
    chaine
    STDIN
    chaine
    print
    chaine
    -----Les caractères qui sont comptés-----
    # - 35
    ! - 33
      - 32
    / - 47
    u - 117
    s - 115
    r - 114
    / - 47
    b - 98
    i - 105
    n - 110
    / - 47
    p - 112
    e - 101
    r - 114
    l - 108
      - 32
    - - 45
    w - 119
    u - 117
    s - 115
    e - 101
      - 32
    s - 115
    t - 116
    r - 114
    i - 105
    c - 99
    t - 116
    ; - 59
    p - 112
    r - 114
    i - 105
    n - 110
    t - 116
      - 32
    " - 34
    E - 69
    n - 110
    t - 116
    r - 114
    e - 101
    z - 122
      - 32
    u - 117
    n - 110
    e - 101
      - 32
    p - 112
    h - 104
    r - 114
    a - 97
    s - 115
    e - 101
      - 32
    : - 58
      - 32
    " - 34
    ; - 59
    c - 99
    h - 104
    o - 111
    m - 109
    p - 112
    ( - 40
    m - 109
    y - 121
      - 32
    $ - 36
    c - 99
    h - 104
    a - 97
    i - 105
    n - 110
    e - 101
    = - 61
    < - 60
    S - 83
    T - 84
    D - 68
    I - 73
    N - 78
    > - 62
    ) - 41
    ; - 59
    $ - 36
    c - 99
    h - 104
    a - 97
    i - 105
    n - 110
    e - 101
    = - 61
    ~ - 126
    s - 115
    / - 47
    \ - 92
    s - 115
    + - 43
    / - 47
    x - 120
    / - 47
    g - 103
    ; - 59
    p - 112
    r - 114
    i - 105
    n - 110
    t - 116
      - 32
    " - 34
    $ - 36
    c - 99
    h - 104
    a - 97
    i - 105
    n - 110
    e - 101
    \ - 92
    n - 110
    " - 34
    ; - 59
    
    0