Tester 3 lettres

Tester 3 lettres - C - Programmation

Marsh Posté le 27-03-2005 à 19:48:08    


Bonjour.
 
 
J'ai un problème :D
 
Je dois écrire un programme (en C, donc) qui compte le nombre d'occurence d'un mot de trois lettres dans un texte. (Texte qui est ouvert dans un fichier)
 
J'arrive à compter le nombre d'occurence d'une lettre, mais pour ce qui est du groupe de trois lettres, ça fait deux jours que je tourne dans tous les sens les éventualités qui passent dans ma tête, mais rien à faire. Arrive pas  :sarcastic:  
 
Est-ce que vous pourriez m'aiguiller siouplé ?
:D
 
Merci !
 
 
Emmylou.
 
 

Reply

Marsh Posté le 27-03-2005 à 19:48:08   

Reply

Marsh Posté le 27-03-2005 à 19:51:53    

Tu peux faire des strstr() en reprenant à chaque fois à la position renvoyée + 3.

Reply

Marsh Posté le 27-03-2005 à 19:54:11    


 Euh.
 
J'vais avoir l'air bête, hein, mais j'ai pas tout compris.
 
...
 
[Désolée...]
 

Reply

Marsh Posté le 27-03-2005 à 20:01:52    

StrStr() te retourne un pointeur sur l'occurence trouvée, donc tu en fais un autre en donnant comme chaine de départ la chaine précédente + 3 afin de recommencer la recherche après.

Reply

Marsh Posté le 27-03-2005 à 20:05:29    


Je sais que je suis affreusement chiante, mais strstr() ne figurant pas dans mon catalogue réduit (j'ai commencé les cours de prog en janvier) de fonctions, j'avoue avoir des réticences à me lancer dans quelque chose comme ça. Vu qu'en plus j'le connais carrément pas.
 
J'n'ai pas précisé que je dois écrire une fonction qui compte le nombre d'occurences du groupe de lettres que je saisi au clavier dans le programme principal.
C'était peut-être important ?
 
:sarcastic:

Reply

Marsh Posté le 27-03-2005 à 20:22:40    

man strstr


---------------
Nos estans firs di nosse pitite patreye...
Reply

Marsh Posté le 27-03-2005 à 20:24:03    

Et les automates à piles c'est pour les chiens ?  :D


Message édité par Chronoklazm le 27-03-2005 à 20:24:17

---------------
Scheme is a programmable programming language ! I heard it through the grapevine !
Reply

Marsh Posté le 27-03-2005 à 20:29:20    


Pardon ?

Reply

Marsh Posté le 27-03-2005 à 20:35:01    

Soit une pile (ou meme un petit buffer), tu lis un caractere, tu le stocke dans la pile en ayant verifier qu'elle ne contient pas plus de 3 caracteres, si c'est le cas et que tu lis un espace tu incremente ton compteur et ainsi de suite ...
Je te laisse gerer le cas ou t'as plus de 3 carac dans la pile :)


---------------
Scheme is a programmable programming language ! I heard it through the grapevine !
Reply

Marsh Posté le 27-03-2005 à 20:45:46    


o_O
 
Et ça, ça va me permettre de trouver le nombre d'occurence du mot de 3 lettres que je cherche ?
 
Je me suis peut-être mal expliquée.
 
Je suis sensée écrire une fonction qui prend en argument une chaîne s de 3 caractères et retourne le nombre d'occurences de cette chaîne dans un fichier.
Et dans mon programme principal, je dois ouvrir le dit-fichier et demander à l'utilisateur de choisir un mot de 3 lettres auquel j'appliquerai la fonction écrite précédemment.
 
...
 

Reply

Marsh Posté le 27-03-2005 à 20:45:46   

Reply

Marsh Posté le 27-03-2005 à 20:50:02    

Si tu as deja fait le test pour ue lettre, pour 3 c'est pareil, sauf que dans ton test :
char* p
if(*p=='a') deviens :
if(*p=='a' && *(p+1)=='b' && *(p+2)=='c')
en rajoutant un test pour verifier que tu ne sors pas du fichier en p+1 et p+2

Reply

Marsh Posté le 27-03-2005 à 22:05:52    


Euh, oui mais je suis sensée me servir de chaines de caractères et je ne connais pas les lettres que je teste...
 
Bon, j'ai fait ça :
 
int NbOccurr (char s[])
{
    int nb_car, i;
    char m[4];
    nb_car=0;
    fscanf(f, "%s", &m);
    i=0;
    while (s[i]!=EOF && s[i+1]!=EOF && s[i+2]!=EOF)
    {
          if (m[0]==s[i] && m[1]==s[i+1] && m[2]==s[i+2])
          nb_car++;    
          i=i+3;
    }
    return nb_car;
}
 
 
Mais ça ne marche pas
 
:'(

Reply

Marsh Posté le 27-03-2005 à 23:57:40    

fscanf(f, "%s", &m);
 
m est déjà une adresse (pour vulgariser)
donc pas besoin du & devant
 
j'attire ton attention sur le fait que c'est pas correct d'utilier un scanf de cette façon pour lire une chaîne de caractère
%3s serait mieux dans ce cas la (si j'me souviens bien, pke j'utilise pour ainsi dire jamais les scanf)
 
EOF n'est pas très indiqué ici, '\0' serait mieux puisque ce n'est qu'une chaîne de caractère
 
i=i+3; ==> i += 3; ;)
 
 
edit : ainsi que les { et } pour ton if, car tu as 2 instructions à éxécuter ;)
pense aussi à faire incrémenter i quand tu ne trouve pas de suite de caractères


Message édité par Deadog le 28-03-2005 à 16:38:10
Reply

Marsh Posté le 28-03-2005 à 16:01:30    


[Ca veut dire quoi les * que tout le monde met partout et dont ma chère prof ne m'a jamais parlé ?]
 
Tenant compte de ces conseils, j'ai changé :
 
int NbOccurr (char s[])
{
    int nb_car, i, a;
    char l;
    nb_car=0;
    l=getc(f);
    a=0;
    while (l!=EOF)
    {
          for (i=0;i<=2;i++)
          {
              if (l==s[i]) a++;
              l=getc(f);    
          }
          if (a==3) nb_car++;
          a=0;
          i=0;
          l=getc(f);
    }
    return nb_car;
}
 
 
Mais ça marche toujours pas.
Ahah.

Reply

Marsh Posté le 28-03-2005 à 16:07:20    

Achète toi un livre comme celui-çi par exemple http://www.amazon.fr/exec/obidos/A [...] 03-0104201
 
pour au moin avoir les bases parceque sinon c'est pas la peine, tu perds ton temp et tu fais perdre celui des autres sur des banalités, c'est pas méchant c'est juste vrai.

Reply

Marsh Posté le 28-03-2005 à 16:14:39    


Merci.
C'est à elle
http://www.dil.univ-mrs.fr/~godbert/
qu'il faut dire ça.
 
En attendant, il aurait suffi de dire 'y a ça qui va pas et en changeant ça, ça marche', le temps aurait été moins perdu...
C'est pas méchant, juste vrai.

Reply

Marsh Posté le 28-03-2005 à 16:31:49    

les * sont ce qui caractèrise les adresses mémoires (ou pointeur)
visiblement tu n'as pas encore vu ça donc ne t'en occupe pas ;)  
 
reprend ce que je t'ai dit, et pê que ça marchera [:spamafote]


Message édité par Deadog le 28-03-2005 à 16:37:28
Reply

Marsh Posté le 28-03-2005 à 17:10:41    

Emmylou a écrit :

[Ca veut dire quoi les * que tout le monde met partout et dont ma chère prof ne m'a jamais parlé ?]
 
Tenant compte de ces conseils, j'ai changé :
 
int NbOccurr (char s[])
{
    int nb_car, i, a;
    char l;
    nb_car=0;
    l=getc(f);
    a=0;
    while (l!=EOF)
    {
          for (i=0;i<=2;i++)
          {
              if (l==s[i]) a++;
              l=getc(f);    
          }
          if (a==3) nb_car++;
          a=0;
          i=0;
          l=getc(f);
    }
    return nb_car;
}
 
 
Mais ça marche toujours pas.
Ahah.


 
Euh... d'où tu le sors ce "f" ?
Je comprends bien qu'il s'agit du fichier que tu lis. Ce que je demande, c'est pourquoi ce "f" n'est pas défini dans la fonction.
Oups... je commence à penser qu'il s'agit ici d'une variable globale. Pas joli. Bon, c'est pas grave mais tu devrais apprendre à éviter d'utiliser des variables globales car c'est source de confusion (la preuve, j'en suis réduit à supposer que cette variable est bien définie et bien initialisée) et on peut toujours s'en passer.
Par ailleurs, ne dis pas que tu ne connais pas le "*" puisque ce fameux "f" doit probablement être de type "FILE *"
 
Maintenant, on va parler d'algorithmie. C'est la traduction en ordres simples, souvent dans un pseudo langage, de la résolution d'un problème
- Tu commences par lire un octet dans ton fichier
- Ensuite, si cet octet correspond à ta première lettre, tu lis 3 octets à suivre, tant que les octets lus correspondent aux lettres de ta chaîne. Donc, déjà, tu risques de lire un octet de trop (tu as déjà lu un premier octet).
- Puis tu refais une lecture supplémentaire (deux octets lus en trop). Il est fortement probable que tu sautes des occurences
Tu devrais repenser la logique de ta solution avant de la traduire en C
 
On peut te donner une solution mais il vaut mieux que tu la trouves par toi-même. Ca te sera beaucoup plus profitable.
Enfin essaie d'utiliser des noms de variable significatifs tu t'y retrouveras beaucoup mieux. "nb_car" correspond au nombre d'occurences et pas au nombre de caractères. "a" correspond au nombre de caractères mais faut le deviner.


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

Marsh Posté le 28-03-2005 à 17:22:19    


Effectivement, le 'f' est de type FILE défini en variable globale. (L'initiative n'est pas de moi, on m'a dit que c'était mieux, peut-êter parce que mon expérience se réduit à trois mois)
Alors, oui, je connais les * puisque je connais les FILE mais je ne l'avais jamais vu autre part, ça m'a un peu perturbée, ces * partout.  
 
Hem.
J'avoue que celui-ci n'était pas particulièrement joli, comme algorithme (bien que l'esthétique informatique me passe quelques kilomètres au dessus)
J'en ai donc un autre, qui apparemment ne marche pas non plus (ou bien je suis folle, ce qui est aussi possible) où je lis caractère par caractère.
Je teste le premier, s'il correspond au premier de ma chaîne, je teste celui d'après, et si celui-ci correspond au 2d de ma chaîne je teste une 3e fois et j'incrémente s'il y a encore correspondance.
 
Puis je ne demandais pas une solution toute faite, mes principes s'y refusent [et d'ailleurs, le cas échéant, j'aurais fait mon embêtante s'il y avait eu quoi que ce soit que je comprenais pas :D], juste un éventuel aiguillage (ou 'ton truc est complètement faux' :p )
 
 
Merci déjà pour tout ce que j'ai appris :)

Reply

Marsh Posté le 28-03-2005 à 17:51:19    

Emmylou a écrit :

Effectivement, le 'f' est de type FILE défini en variable globale.

Tu veux dire "FILE *" (c'est très important de rester très précis quand on parle de pointeurs)
 

Emmylou a écrit :

(L'initiative n'est pas de moi, on m'a dit que c'était mieux, peut-êter parce que mon expérience se réduit à trois mois)

Mieux aujourd'hui pour simplifier. Plus tard, on te dira qu'en fait il ne faut pas. Prépare toi à cette éventualité
 

Emmylou a écrit :

Alors, oui, je connais les * puisque je connais les FILE mais je ne l'avais jamais vu autre part, ça m'a un peu perturbée, ces * partout.

Plus tard tu seras très à l'aise avec une ou deux étoiles (au delà, ça devient invivable)
 

Emmylou a écrit :

J'en ai donc un autre, qui apparemment ne marche pas non plus (ou bien je suis folle, ce qui est aussi possible) où je lis caractère par caractère.
Je teste le premier, s'il correspond au premier de ma chaîne, je teste celui d'après, et si celui-ci correspond au 2d de ma chaîne je teste une 3e fois et j'incrémente s'il y a encore correspondance.

En fait, le problème ne vient pas de la première lecture mais souvent des lectures suivantes. D'où est-ce que tu repars si seulement une ou deux lettres correspondent ? Est-ce que tu relis quand-même 3 nouvelles lettres ? Imagine que ton fichier commence apr "ABABCDE" et tu cherches "ABC". Tu commences par comparer "ABC" avec "ABA" => pas bon. Est-ce que tu repars sur "BCD" ou sur le "ABC" suivant ?
Essaye de travailler avec un papier. Pose tes lettres dans tes cases et déroule ton algorithme en imagination. J'espère que tu réussiras. En tout cas, ton idée est la bonne.
 

Emmylou a écrit :

Merci déjà pour tout ce que j'ai appris :)

On est là pour ça


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

Marsh Posté le 28-03-2005 à 18:11:54    

Je n'ai peut etre pas compris le probleme mais pour moi un "mot de 3 lettres" est une suite de 3 lettres puis un espace, donc quand on lit "ABABCDE"; on lira "A" puis "B" puis "A" ensuite avant de comparer "ABA" avec la chaine qu'on cherche on verifie si le 4ieme caractere est un espace ou un point etc ? Si c'est le cas on passe directement au mot suivant sans se preoccuper de la comparaison.
 
Non ?
 
EDIT : Bon pour cette histoire d'espace, en C il y a une fonction qui s'appelle ungetc qui remet un caractere lu dans un fichier ... ca peut eventuellement servir (j'en dis pas plus)


Message édité par Chronoklazm le 28-03-2005 à 18:21:47

---------------
Scheme is a programmable programming language ! I heard it through the grapevine !
Reply

Marsh Posté le 28-03-2005 à 18:30:02    

Mais...
quand je fais ça
 
while (l!=EOF)
    {
          if (l==s[0])
              {
                           l=getc(f);
                           if (l==s[1])
                           {
                                         l=getc(f);
                                         if (l==s[2])
                                         {
                                                     occur++;
                                                     l=getc(f);
                                         }
                                         
Il faudrait que je mette un 'else' à chaque 'if' qui referait à chaque fois ? Ca n'a pas de sens, je n'aurais jamais fini !  
Pourtant, il faudrait qu'à chaque fois que les lettres ne correspondent pas je refasse le test à partir du début...
[Je pense 'si l n'est pas égale à s[0] on en prend une autre, on réessaie, mais dans ce cas, si c'est encore pas égal à s[0]... Ensuite, si c'est égal à s[0], mais pas à s[1], on en prend une autre et on recommence du début, et si c'est égal à s[1] mais pas à s[2], on...' O_O ]
 
 
Est-ce qu'il existe une [... Je cherche le bon mot, je suppose que je ne l'ai pas] fonction (?) qui me permettrait de revenir au début et tester la lettre avec la première de mon mot ?
 
 

Reply

Marsh Posté le 28-03-2005 à 18:45:23    

mais ton premier truc marchait très bien mis à part qql erreurs !!
 

Code :
  1. while (s[i]!=0 && s[i+1]!=0 && s[i+2]!=0)
  2.     {
  3.           if (m[0]==s[i] && m[1]==s[i+1] && m[2]==s[i+2])
  4.             nb_car++;
  5.            
  6.           i++;
  7.     }


 
ça c'est ce que tu avais fait au début avec qql trucs corrigé
le principe m'a l'air bon dans un monde parfait
 
m constitue les 3 lettres recherchés
s constitue toutes une chaîne de caract contenant le texte dans lequel tu recherches


Message édité par Deadog le 28-03-2005 à 18:46:06
Reply

Marsh Posté le 28-03-2005 à 18:48:49    


Et sachant que le texte que je recherche est rangé dans mon fichier f, pour que s corresponde à ce texte, il suffirait que je fasse fscanf (f,"%s",s)  ?

Reply

Marsh Posté le 28-03-2005 à 19:01:44    

non, car tu ne connais sans doute pas d'avance (cad au moment ou s'éxécute ton programme) le nb de caractère dans ton fichier et tu risques donc le débordement de mémoire
 
cette partie la est à changé, mais ce n'est pas bien compliqué
tu fais ta fonction pour qu'elle puisse prendre 2 paramètres : char s[] et char m[]
 
et tu appelles ta fonction en lui fournissant ce dont elle a besoin
et pour lui fournir s[], tu utilises, par expl, fgets comme ceci :
 

Code :
  1. char buffer[BUFSIZ];
  2. while(fgets(buffer, BUFSIZ-1, f) != NULL) {
  3.   NbOccurr(buffer, "ABC" );
  4. }


 
sachant que BUFSIZ est déjà définie dans la lib standard ;)
 
(avec pê tes modif à faire, j'ai pas testé  :sleep:  )
 


Message édité par Deadog le 28-03-2005 à 19:03:15
Reply

Marsh Posté le 28-03-2005 à 19:21:28    

Je n'ai pas le droit de changer ma fonction pour qu'elle prenne deux paramètres.
[Si j'avais le droit de choisir, j'aurais balancé les profs par la fenêtre]

Reply

Marsh Posté le 28-03-2005 à 19:22:25    

bon bah fait ça dans la fonction elle même alors ;)
et dans le while tu mes ce qu'il faut [:spamafote] ;)

Reply

Marsh Posté le 28-03-2005 à 21:39:55    

Chronoklazm a écrit :

Je n'ai peut etre pas compris le probleme mais pour moi un "mot de 3 lettres" est une suite de 3 lettres puis un espace, donc quand on lit "ABABCDE"; on lira "A" puis "B" puis "A" ensuite avant de comparer "ABA" avec la chaine qu'on cherche on verifie si le 4ieme caractere est un espace ou un point etc ? Si c'est le cas on passe directement au mot suivant sans se preoccuper de la comparaison.
 
Non ?
 
EDIT : Bon pour cette histoire d'espace, en C il y a une fonction qui s'appelle ungetc qui remet un caractere lu dans un fichier ... ca peut eventuellement servir (j'en dis pas plus)


 
Oui, je crois que quelque part il y a une incompréhension sur l'énoncé du problème.
Est-ce que le problème est de rechercher le nombre de fois où on trouve une occurence de 3 lettres dans une suite de lettres... ou est-ce que le problème est de rechercher les mots qui ont 3 lettres et dont les lettres correspondent aux lettres demandées ?


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

Marsh Posté le 01-04-2005 à 01:30:44    

Code :
  1. //  la base
  2. unsigned int laClef(unsigned char mot[3])
  3. {
  4.     return mot[2]*65536+mot[1]*256+mot[0]; // trouve un chiffre qui représente
  5. }
  6. // et compte tous les triplets ;)
  7. void compterLes3Mots(char *leTexte, unsigned int laTaille)
  8. {
  9.     unsigned int *lesTuples,indice;
  10.     lesTuples=(unsigned int*)calloc(1<<8*3,sizeof(unsigned int));
  11.     for(indice=0;indice<=laTaille-3;indice++)
  12.     {
  13.         lesTuples[laClef(&leTexte[indice])]++;
  14.     }
  15. /* et voila,
  16. tous les 3-mots de la chaine sont dans ce tableau,
  17. normalement on peut écrire :
  18. printf("cat est écrit %d fois",lesTuples[laClef("cat" )]);
  19. printf("DOG est écrit %d fois",lesTuples[laClef("DOG" )]);
  20.  
  21. unsigned int x=7*256*256+7*256+7;  
  22. printf("si le fichier est un nombre en base 256, 777 y apparraît %d fois",lesTuples[laClef((char*)&x)]);
  23. ou bien sortir des listes (triées) :
  24. for(indice=0;indice<(1<<8*3);indice++) // pour tous les triplets
  25. {
  26.     if(lesTuples[indice]>=7) // qui apparaissent au moins 7x dans leTexte...
  27.  {
  28.   ///...
  29. */
  30.     free(lesTuples);
  31. }
  32. //fra - 0 garanties//

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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