Problème pangramme
Résolu
Bonjour,
Alors voila mon problème: je veux un programme qui fait entré une phrase a un utilisateur puis retournant 1 si cette chaîne est un pangramme et 0 sinon.
ps : un pangramme est une phrase contenant les 26 lettres de l'alphabet
Mais voila mon programme ne me retourne que "0"
Alors voila mon problème: je veux un programme qui fait entré une phrase a un utilisateur puis retournant 1 si cette chaîne est un pangramme et 0 sinon.
ps : un pangramme est une phrase contenant les 26 lettres de l'alphabet
Mais voila mon programme ne me retourne que "0"
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char tab[]="";char chaineComparateur[26]="abcdefghijklmpopqrstuvwxyz"; int i;int longueurPhrase;int compteur;int compteur2=0;int compteur3=0; printf("Enter un phrase\n"); gets(tab); printf("\n"); longueurPhrase = strlen(tab); if (longueurPhrase < 26) printf("0"); else { for(i=longueurPhrase;i >= 0;i--) { for(compteur2 = 0; compteur2 <= longueurPhrase; compteur2++) { compteur = strncmp(tab,chaineComparateur,compteur3); compteur3++; } } if (compteur == 26) printf("1\n"); else printf("0\n"); }
3 réponses
Salut.
C'est n'importe quoi ! Comment espérer que ça fonctionne ?
déjà, pour commencer, il faudrait faire de tab un tableau de taille correcte ! Tu risque l'erreur de segmentation.
à quoi sert cette double boucle sur i et compteur2 ? a quoi sert compteur3 ? ta boucle peut se résumer en gros à compteur=strncmp(tab,chaineComparateur,longueurPhrase*longueurPhrase);car entre les deux rien n'est modifié.
Tu peux faire beaucoup plus simple en vérifiant juste que pour chaque lettre de l'alphabet elle est bien présente dans ta phrase.
C'est n'importe quoi ! Comment espérer que ça fonctionne ?
déjà, pour commencer, il faudrait faire de tab un tableau de taille correcte ! Tu risque l'erreur de segmentation.
à quoi sert cette double boucle sur i et compteur2 ? a quoi sert compteur3 ? ta boucle peut se résumer en gros à compteur=strncmp(tab,chaineComparateur,longueurPhrase*longueurPhrase);car entre les deux rien n'est modifié.
Tu peux faire beaucoup plus simple en vérifiant juste que pour chaque lettre de l'alphabet elle est bien présente dans ta phrase.
Voici quelques erreurs à corriger :
char tab[]="";
Cela créé un tableau tab d'une seule case. Il faut que tu indiques la longueur maximale de la phrase. Par exemple : char tab[255];
char chaineComparateur[26]="abcdefghijklmpopqrstuvwxyz"
Je te conseille de laisser de la plage pour mettre un '\0' en fin de chaîne. Donc : char chaineComparateur[27]="a...z"; ou tout simplement : char chaineComparateur[]="a...z";
gets(tab);
A ne pas utiliser ! Utilise plutôt la version fgets()... Et attention, cette fonction stocke le '\n' s'il reste de la place.
compteur = strncmp(tab,chaineComparateur,compteur3);
A revoir.
Il faudrait plutôt mettre : if (strchr(tab,chaineComparateur[...]...)
Tu as oublié : return 0;
Et enfin, je te conseille de créer une fonction spécifique. Et de revoir l'algorithme. Tu peux faire beaucoup plus simple.
L'idée est que : dès lors que tu constates qu'une lettre manque (strchr() renvoie NULL), ta fonction retournera 0. Cela fait une seule boucle for.
Cdlt,
char tab[]="";
Cela créé un tableau tab d'une seule case. Il faut que tu indiques la longueur maximale de la phrase. Par exemple : char tab[255];
char chaineComparateur[26]="abcdefghijklmpopqrstuvwxyz"
Je te conseille de laisser de la plage pour mettre un '\0' en fin de chaîne. Donc : char chaineComparateur[27]="a...z"; ou tout simplement : char chaineComparateur[]="a...z";
gets(tab);
A ne pas utiliser ! Utilise plutôt la version fgets()... Et attention, cette fonction stocke le '\n' s'il reste de la place.
compteur = strncmp(tab,chaineComparateur,compteur3);
A revoir.
Il faudrait plutôt mettre : if (strchr(tab,chaineComparateur[...]...)
Tu as oublié : return 0;
Et enfin, je te conseille de créer une fonction spécifique. Et de revoir l'algorithme. Tu peux faire beaucoup plus simple.
L'idée est que : dès lors que tu constates qu'une lettre manque (strchr() renvoie NULL), ta fonction retournera 0. Cela fait une seule boucle for.
Cdlt,
Il y a d'autres choses qui ne vont pas, tu ne gères absolument pas les histoires de minuscules et de majuscules.
Je te conseille de faire une fonction qui convertit les caractères que tu lis en minuscules (quand c'est possible), par exemple avec la fonction tolower(). Tu peux vérifier que le caractère est une lettre avec la fonction isalpha(). Pour plus de détails sur ces fonctions, tape dans google ou dans un terminal linux :
Si la conversion n'est pas possible tu retournes un caractère particulier (par exemple '\0').
Si le caractère a été converti avec succès tu le convertis en index car on va stocker dans un tableau qu'on a croisé cette lettre. Comme la plage des caractères de 'a' à 'z' correspond à une plage d'entiers consécutifs, on peut facilement convertir 'a' ... 'z' en (respectivement) 0 ... 26 comme ceci :
Bon maintenant, réfléchissons à quoi ressemblerait notre fonction is_pangramme. On a besoin de retourner une valeur "vrai" ou "faux", mais le type "bool" n'existe qu'en C++, pas en C. On va donc le définir. Cette fonction prend en paramètre une phrase de longueur indéterminée. C'est donc un "char *". Cette phrase n'est pas altérée par la fonction is_pangramme, donc encore mieux, c'est un "const char *" (ce qui permet d'appeler la fonction is_pangramme aussi bien pour des "char *" que des "const char *").
Ok maintenant comme l'a dit char sniper, il suffit de regarder les caractères de la phrase un par un et maintenir un tableau de "booleens" qui mémorise quels caractères ont été croisés. On initialise les 26 cases de ce tableau à "faux".
Pour chaque caractère de la phrase :
- Si la conversion réussi, tu mémorises dans le tableau que tu as croisé cette minuscule (en basculant la case correspondante à "vrai").
- Sinon tu ignores le caractères (c'est par un exemple un espace ou une ponctuation).
Une fois la phrase parcourue, tu regardes si dans ce tableau
Enfin, tu regardes si toutes les cases sont à "vrai" ou non. Dès qu'on rencontre une case à "faux", on sait que ce n'est pas un pangramme.
Ce qui nous mène par exemple à ce code :
Bon maintenant ce n'est pas encore parfait. Dans le cas général, la phrase peut comporter des caractères accentués. Malheureusement, un char ne permet pas d'encoder un caractère accentué proprement. On peut donc s'en sortir avec des wchar_t. Concrètement un wchar_t (wide char) est un caractère encodé sur 4 octets au lieu de 1 (ce qui permet de régler le problème des caractères accentués).
Du coup il faut adapter un peu le code, en particulier la fonction de conversion. En voici le squelette que je te laisse le soin de compléter.
Tu noteras que pour indiquer qu'une chaîne ou un caractère sont basés sur des wchar_t, on les précède d'un "L".
Il ne reste plus qu'à corrige également le type du paramètre de is_pangramme (qui devient un const wchar_ *) et de pc (qui devient aussi un const wchar_t *), faire appel à la fonction convertir_wchar au lieu de convertir_char et l'affaire est dans le sac.
Bonne chance
Je te conseille de faire une fonction qui convertit les caractères que tu lis en minuscules (quand c'est possible), par exemple avec la fonction tolower(). Tu peux vérifier que le caractère est une lettre avec la fonction isalpha(). Pour plus de détails sur ces fonctions, tape dans google ou dans un terminal linux :
man isalpha man tolower
Si la conversion n'est pas possible tu retournes un caractère particulier (par exemple '\0').
#include <ctype.h> char convertir_char(char c) { if (isalpha(c)) return tolower(c); return '\0'; }
Si le caractère a été converti avec succès tu le convertis en index car on va stocker dans un tableau qu'on a croisé cette lettre. Comme la plage des caractères de 'a' à 'z' correspond à une plage d'entiers consécutifs, on peut facilement convertir 'a' ... 'z' en (respectivement) 0 ... 26 comme ceci :
unsigned char_to_index(char c) { return c - 'a'; }
Bon maintenant, réfléchissons à quoi ressemblerait notre fonction is_pangramme. On a besoin de retourner une valeur "vrai" ou "faux", mais le type "bool" n'existe qu'en C++, pas en C. On va donc le définir. Cette fonction prend en paramètre une phrase de longueur indéterminée. C'est donc un "char *". Cette phrase n'est pas altérée par la fonction is_pangramme, donc encore mieux, c'est un "const char *" (ce qui permet d'appeler la fonction is_pangramme aussi bien pour des "char *" que des "const char *").
#define true 1 #define false 0 typedef int bool; bool is_pangramme(const char *phrase) { // ... }
Ok maintenant comme l'a dit char sniper, il suffit de regarder les caractères de la phrase un par un et maintenir un tableau de "booleens" qui mémorise quels caractères ont été croisés. On initialise les 26 cases de ce tableau à "faux".
Pour chaque caractère de la phrase :
- Si la conversion réussi, tu mémorises dans le tableau que tu as croisé cette minuscule (en basculant la case correspondante à "vrai").
- Sinon tu ignores le caractères (c'est par un exemple un espace ou une ponctuation).
Une fois la phrase parcourue, tu regardes si dans ce tableau
Enfin, tu regardes si toutes les cases sont à "vrai" ou non. Dès qu'on rencontre une case à "faux", on sait que ce n'est pas un pangramme.
Ce qui nous mène par exemple à ce code :
#include <ctype.h> #include <stdio.h> #define true 1 #define false 0 typedef int bool; char convertir_char(char c) { if (isalpha(c)) return tolower(c); return '\0'; } unsigned char_to_index(char c) { return c - 'a'; } bool is_pangramme(const char *phrase) { unsigned i; bool caracteres_vus[26]; char c; const char *pc = phrase; bool res = true; for(i = 0; i < 26; ++i) { caracteres_vus[i] = false; } for(; *pc; ++pc) { c = convertir_char(*pc); if (c) caracteres_vus[char_to_index(c)] = true; } for(i = 0; i < 26; ++i) { if(caracteres_vus[i] == false) { res = false; break; } } return res; } int main() { const char *phrase = "J'aime les loutres"; printf("is_pangramme(%s) = %d\n", phrase, is_pangramme(phrase)); return 0; }
Bon maintenant ce n'est pas encore parfait. Dans le cas général, la phrase peut comporter des caractères accentués. Malheureusement, un char ne permet pas d'encoder un caractère accentué proprement. On peut donc s'en sortir avec des wchar_t. Concrètement un wchar_t (wide char) est un caractère encodé sur 4 octets au lieu de 1 (ce qui permet de régler le problème des caractères accentués).
Du coup il faut adapter un peu le code, en particulier la fonction de conversion. En voici le squelette que je te laisse le soin de compléter.
#include <wchar.h> char convertir_wchar(wchar_t c) { if (isalpha(c)) return tolower(c); switch(c) { case L'é': case L'É': case L'ê': case L'Ê': case L'è': case L'È': case L'ë': case L'Ë': return 'e'; //... idem avec a, u, i, o, y default: break; } return '\0'; } // Exemple : // printf("%c\n", convertir_wchar(L'é')); // const wchar_t * phrase = L"J'aime les loutres";
Tu noteras que pour indiquer qu'une chaîne ou un caractère sont basés sur des wchar_t, on les précède d'un "L".
Il ne reste plus qu'à corrige également le type du paramètre de is_pangramme (qui devient un const wchar_ *) et de pc (qui devient aussi un const wchar_t *), faire appel à la fonction convertir_wchar au lieu de convertir_char et l'affaire est dans le sac.
Bonne chance