Recherche de voyelles dans un fichier

Recherche de voyelles dans un fichier - C - Programmation

Marsh Posté le 17-04-2010 à 13:18:50    

Bonjour a tous  :)  
 
Pourquoi mon code ne trouve pas tout les voyelles qui se trouve dans mon texte ?
 

Code :
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #define TAILLE_MAX 1000
  4. int main(int argc, char *argv[])
  5. {
  6. char voy[6] = {'a','e','i','o','u','y'};
  7. int compte[6] = {0}, i;
  8. FILE* fichier = NULL;
  9. char chaine[TAILLE_MAX] = "";
  10.    if ((fichier = fopen("test.txt", "r" )) != NULL)
  11. {
  12.          while (fgets(chaine, TAILLE_MAX, fichier) != NULL) // On lit le fichier tant qu'on ne reçoit pas d'erreur (NULL)
  13.           {
  14.              for(i = 0; i < 6; i++)
  15.              if(chaine[i] == voy[i])
  16.              compte[i] = compte[i] + 1; // On affiche la chaîne qu'on vient de lire
  17.           }
  18.     printf("Votre texte comporte :\n" );
  19.     for(i = 0; i < 6; i++)
  20.     printf("%d fois la lettre %c\n", compte[i], voy[i]);
  21.     fclose(fichier);
  22. }
  23.   return 0;
  24. }

Reply

Marsh Posté le 17-04-2010 à 13:18:50   

Reply

Marsh Posté le 17-04-2010 à 15:28:05    

- tu ne regardes que les 6 premiers caractères de chaque ligne lue
- tu ne compares chacun de ces caractères qu'avec une seule voyelle
 
En prime,
- les constantes magiques comme 6, c'est mal
- l'indentation aléatoire


---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 17-04-2010 à 15:44:45    

Je dois faire quoi pour l'arranger?

Reply

Marsh Posté le 17-04-2010 à 15:53:41    

- regarder chaque caractère de tes lignes
- les comparer avec toutes les voyelles
- définir un nom symbolique et l'utiliser à la place de 6
- indenter correctement


---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 17-04-2010 à 15:55:17    

Quand tu fais
for(i = 0; i < 6; i++)
    if(chaine[i] == voy[i])
tu testes seulement si le i-eme caractère de la chaine est la i-eme voyelle au lieu de tester si chaque caractère de la chaine est la i-me voyelle.

 

En modifiant un peu ton code ceci marche:

Code :
  1. #include <stdio.h>
  2. #include <string.h>
  3. #define TAILLE_MAX 1000
  4. int main(int argc, char *argv[])
  5. {
  6.   char voy[6] = {'a','e','i','o','u','y'};
  7.   int compte[6] = {0}, i, j;
  8.   FILE* fichier = NULL;
  9.   char chaine[TAILLE_MAX] = "";
  10.   if ((fichier = fopen("test.txt", "r" )) != NULL)
  11.     {
  12.       while (fgets(chaine, TAILLE_MAX, fichier) != NULL) // On lit le fichier tant qu'on ne reçoit pas d'erreur (NULL)
  13.         {
  14.           for (i = 0; i <strlen(chaine); i++) {
  15.             for(j = 0; j < 6; j++) {
  16.               if(chaine[i] == voy[j])
  17.                 compte[j] = compte[j] + 1; // On affiche la chaîne qu'on vient de lire
  18.             }
  19.           }
  20.         }
  21.       printf("Votre texte comporte :\n" );
  22.       for(i = 0; i < 6; i++)
  23.         printf("%d fois la lettre %c\n", compte[i], voy[i]);
  24.       fclose(fichier);
  25.     }
  26.   return 0;
  27. }
 

Une version un peu plus évoluée, qui teste aussi les majuscules:

Code :
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #define TAILLE_MAX 1000
  5. int main(int argc, char *argv[])
  6. {
  7.   char voy[12] = {'a', 'e', 'i', 'o', 'u', 'y',
  8.                   'A', 'E', 'I', 'O', 'U', 'Y'};
  9.  
  10.   int compte[6] = {0};
  11.   char buffer[TAILLE_MAX];
  12.   FILE* fichier = fopen("test.txt", "r" );
  13.   int i, j, lgchaine;
  14.   if (!fichier) {
  15.     printf("Cannot open text.txt\n" );
  16.     return EXIT_FAILURE;
  17.   }
  18.   while (fgets(buffer, TAILLE_MAX, fichier)) {
  19.     lgchaine = strlen(buffer);
  20.     for (i = 0; i <lgchaine; ++i) { // Pour chaque caractère de la chaine
  21.       for(j = 0; j < 6; ++j) { // Pour chaque voyelle
  22.         if(buffer[i] == voy[j] || buffer[i] == voy[j+6]) { // On teste la minuscule et la majuscule
  23.           ++compte[j];
  24.           break; // Si on a trouvé une voyelle, inutile de tester les autres
  25.         }
  26.       }
  27.     }
  28.   }
  29.   fclose(fichier);
  30.   printf("Votre texte comporte :\n" );
  31.   for(i = 0; i < 6; ++i) {
  32.     printf("%d fois la lettre %c\n", compte[i], voy[i]);
  33.   }
  34.  
  35.   return EXIT_SUCCESS;
  36. }
 

La même chose avec un switch:

Code :
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #define TAILLE_MAX 1000
  4. int main(int argc, char *argv[])
  5. {
  6.   char voy[6] = {'a', 'e', 'i', 'o', 'u', 'y'};
  7.   int compte[6] = {0};
  8.   char buffer[TAILLE_MAX];
  9.   FILE* fichier = fopen("test.txt", "r" );
  10.   int i;
  11.   if (!fichier) {
  12.     printf("Cannot open text.txt\n" );
  13.     return EXIT_FAILURE;
  14.   }
  15.   while (fgets(buffer, TAILLE_MAX, fichier)) {
  16.     i = 0;
  17.     while (buffer[i]) {
  18.       switch (buffer[i]) {
  19.       case 'a': case 'A': ++compte[0]; break;
  20.       case 'e': case 'E': ++compte[1]; break;
  21.       case 'i': case 'I': ++compte[2]; break
  22.       case 'o': case 'O': ++compte[3]; break;
  23.       case 'u': case 'U': ++compte[4]; break;
  24.       case 'y': case 'Y': ++compte[5]; break;
  25.       default: break;
  26.       }
  27.       ++i;
  28.     }
  29.   }
  30.   fclose(fichier);
  31.   printf("Votre texte comporte :\n" );
  32.   for(i = 0; i < 6; ++i) {
  33.     printf("%d fois la lettre %c\n", compte[i], voy[i]);
  34.   }
  35.  
  36.   return EXIT_SUCCESS;
  37. }


A+,

Message cité 1 fois
Message édité par gilou le 17-04-2010 à 16:06:12

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 17-04-2010 à 18:12:55    

gilou a écrit :


Une version un peu plus évoluée, qui teste aussi les majuscules:

Code :
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #define TAILLE_MAX 1000
  5. int main(int argc, char *argv[])
  6. {
  7.   char voy[12] = {'a', 'e', 'i', 'o', 'u', 'y',
  8.                   'A', 'E', 'I', 'O', 'U', 'Y'};
  9. ...
  10.            if(buffer[i] == voy[j] || buffer[i] == voy[j+6]) { // On teste la minuscule et la majuscule
  11. }




Mouais. tolower() aurait été ici assez approprié...

Code :
  1. if(tolower(buffer[i]) == voy[j]) { // On teste la minuscule et la majuscule
  2. ...


 
Là où on s'amuserait, ce serait pour tester les é, è, ê, ë, î, ï, ...


Message édité par Sve@r le 17-04-2010 à 18:14:54

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

Marsh Posté le 17-04-2010 à 18:26:54    

En effet. ça serait surtout approprié dans le switch (buffer[i])
un switch (tolower(buffer[i])) permet de virer la moitié des cases du switch.
De toute façon, si j'avais vraiment codé cela en dehors d'une amélioration du code donné, j'aurais introduit une structure de donnée struct avec un champ lettre et un champ compte, car c'est ce que suggère le problème.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 17-04-2010 à 18:45:25    

gilou a écrit :

De toute façon, si j'avais vraiment codé cela en dehors d'une amélioration du code donné, j'aurais introduit une structure de donnée struct avec un champ lettre et un champ compte, car c'est ce que suggère le problème.


 
Voire même un champ "tableau de lettres" associé au champ compte ce qui permet ainsi de compter les é, è, ê comme la même lettre...


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

Marsh Posté le 17-04-2010 à 19:16:04    

Je ferais plutôt cela au niveau d'une fonction dédiée mytolower, car ça risque de compliquer l'algorithmique d'un exo a la base simple, mais c'est une question de gout.
 
Et on peut vite arriver aux questions métaphysiques: si on compte aussi les consonnes, un ß compte t'il pour deux s? etc
A+,


Message édité par gilou le 17-04-2010 à 19:20:21

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 17-04-2010 à 19:35:05    

Merci gilou c'est ok  :D  
 
Si j'ai compris mon 1er code test que les 6 premiers caractères sur 1000 c'est ça ou pas?
 

Code :
  1. while (fgets(chaine, TAILLE_MAX, fichier) != NULL)
  2.           {
  3.              for(i = 0; i < 6; i++)
  4.              if(chaine[i] == voy[i])
  5.              compte[i] = compte[i] + 1;
  6.           }


 
PS: Tu utilise  for (i = 0; i <strlen(chaine); i++) mais je peut mettre aussi for (i = 0; i <TAILLE_MAX; i++) ?

Reply

Marsh Posté le 17-04-2010 à 19:35:05   

Reply

Marsh Posté le 17-04-2010 à 19:53:22    

lassault1 a écrit :

Merci gilou c'est ok  :D  
 
Si j'ai compris mon 1er code test que les 6 premiers caractères sur 1000 c'est ça ou pas?

Code :
  1. while (fgets(chaine, TAILLE_MAX, fichier) != NULL)
  2.           {
  3.              for(i = 0; i < 6; i++)
  4.              if(chaine[i] == voy[i])
  5.              compte[i] = compte[i] + 1;
  6.           }



Même pas: ton code teste si le premier caractère est 'a', si le 2e est 'e', si le 3e est 'i'... et si le 6e est 'y'. :D
 

lassault1 a écrit :

PS: Tu utilise  for (i = 0; i <strlen(chaine); i++) mais je peut mettre aussi for (i = 0; i <TAILLE_MAX; i++) ?

Surtout pas: si la ligne lue par fgets et copiée dans chaine fait moins que TAILLE_MAX caractères tu vas continuer a tester pour des caractères qui trainent dans le reste du tableau chaine, mais qui n'ont pas été mis la par fgets.
C'est a ça que sert la limitation  i <strlen(chaine): a ne tester que les caractères effectivement copiés par fgets.
fgets met un '\0' a la fin de ce qu'il copie, et c'est ce que détecte strlen pour calculer la bonne longueur.
A+,


Message édité par gilou le 17-04-2010 à 19:56:12

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 17-04-2010 à 20:15:41    

Citation :

Même pas: ton code teste si le premier caractère est 'a', si le 2e est 'e', si le 3e est 'i'... et si le 6e est 'y'.  :D


 
C'est pas ce que j'ai dis  :??:  ?
 

Citation :

Surtout pas: si la ligne lue par fgets et copiée dans chaine fait moins que TAILLE_MAX caractères tu vas continuer a tester pour des caractères qui trainent dans le reste du tableau chaine, mais qui n'ont pas été mis la par fgets.
C'est a ça que sert la limitation  i <strlen(chaine): a ne tester que les caractères effectivement copiés par fgets.
fgets met un '\0' a la fin de ce qu'il copie, et c'est ce que détecte strlen pour calculer la bonne longueur.
A+,


 
Ok !  dans ce cas strlen(chaine) sert a optimisé la boucle ?

Reply

Marsh Posté le 17-04-2010 à 20:26:08    

Non, à la rendre correcte.  Si par hasard (ou parce que la ligne précédente était plus longue) il y a une voyelle après la fin de la ligne, tu la compterais.
 
Pour optimiser, il vaut mieux ne calculer strlen qu'une fois en stockant le résultat dans une variable, ce qu'avait fait Gilou dans une de ses versions.


---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 17-04-2010 à 20:59:15    

lassault1 a écrit :

Citation :

Même pas: ton code teste si le premier caractère est 'a', si le 2e est 'e', si le 3e est 'i'... et si le 6e est 'y'.  :D


 
C'est pas ce que j'ai dis  :??:  ?

Non, ce que tu as dit, que tu testes seulement les 6 premier caracteres, ca signifierait que ton code teste si le premier caractère est 'a',ou 'e', ou 'i'... ou 'y', puis qu'il teste si le 2e caractère est 'a',ou 'e', ou 'i'... ou 'y', ... puis qu'il teste si le 6e caractère est 'a',ou 'e', ou 'i'... ou 'y'.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 21-04-2010 à 00:09:15    

Code :
  1. # if ((fichier = fopen("test.txt", "r" )) != NULL)
  2. #     {
  3. #       while (fgets(chaine, TAILLE_MAX, fichier) != NULL) // On lit le fichier tant qu'on ne reçoit pas d'erreur (NULL)
  4. #         {
  5. #           for (i = 0; i <strlen(chaine); i++) {
  6. #             for(j = 0; j < 6; j++) {
  7. #               if(chaine[i] == voy[j])
  8. #                 compte[j] = compte[j] + 1; // On affiche la chaîne qu'on vient de lire
  9. #             }
  10. #           }
  11. #         }


 
Pourquoi pas avoir mis tout simplement for(i = 0; i < sizeof(chaine); i++) au lieu de :
 

Code :
  1. for (i = 0; i <strlen(chaine); i++)

Reply

Marsh Posté le 21-04-2010 à 03:04:52    

Parce que sur un tableau, sizeof d'un tableau, ca renvoie le nombre total de cases, ca se fout complètement de la position du \0 dans le tableau.
Exemple:
char chaine[8] = "Toto"; ca mt les caractères T, o, t, o et \0 en position 0, 1, 2, 3 et 4 du tableau.
sizeof(chaine) vaut 8, mais strlen(chaine) vaut 4 (4 caractères avant le \0)
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 21-04-2010 à 12:47:52    

Merci gilou..

Reply

Sujets relatifs:

Leave a Replay

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