Menu

Manipulation des fichiers [Fermé]

Messages postés
52
Date d'inscription
mercredi 21 juin 2017
Statut
Membre
Dernière intervention
15 juin 2019
- - Dernière réponse : [Dal]
Messages postés
5169
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
18 juillet 2019
- 14 juin 2018 à 19:28
Bonjour ici, je suis débutant en C et j'ai besoin d'aide.

J'ai un fichier .txt qui contient les mots français, je veux faire un dictionnaire avec un système de prédiction, par exemple lorsque l'utilisateur écrit 'pro' on lui liste tous les mots commençant par pro comme :programme, progrès, prophète,proprement,propriétaire, projet... Plus l'utilisateur écrit plus on élimine les mots n'ayant pas trait à la recherche. Comme dans l"exemple précédent si l'utilisateur écrit 'prop' on ne restera qu'avec prophète, propriétaire et proprement. Dans le cas où il tape un mot qui n'existe pas on lui propose des mots qui sont proches de celui qu'il a écrit.
Afficher la suite 

6 réponses

Messages postés
94
Date d'inscription
lundi 23 juillet 2012
Statut
Membre
Dernière intervention
5 juin 2019
4
0
Merci
Bonjour,
Concernant ta demande ce que je peux te conseiller c'est d'utiliser "conio.h" notamment la fonction _kbhit(), qui te permettra de récupérer les touches en temps réel. De plus tu va devoir ouvrir ton fichier et y séparer tout les mots. L'algorithme devra fonctionner de la manière suivante:

- L'utilisateur tape une lettre
- Le programme sélectionne tous les mots qui commencent par cette lettre.
- Il affichent ces mots
- Lorsque qu'une nouvelle lettre est appuyée, efface l'écran , affiche les lettres déjà tapée et recommence la recherche

Si tu as besoin de plus de détails sur comment developer chaque étape du programme, ou si tu as de nouvelles questions n'hésites pas à les poser,

Cordialement Christo974
Jessekamba
Messages postés
52
Date d'inscription
mercredi 21 juin 2017
Statut
Membre
Dernière intervention
15 juin 2019
-
Merci Christo947.
Justement j'ai besoin de plus de détails pour développer chaque étape, si peux m'aider sur ce coup là
Messages postés
5169
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
18 juillet 2019
786
0
Merci
Salut Jessekamba,

C'est bizarre de vouloir faire ce type de choses sur la console ... c'est plutôt typiquement une intéraction qu'on trouve dans des programmes avec une interface graphique, ou un navigateur qui dialogue en asynchrone en JavaScript avec un serveur (lequel peut faire tourner un cgi écrit en C pour les performances).

Si tu dois vraiment le faire avec une intéraction en console, tu pourrais voir si tu ne peux pas utiliser une bibliothèque déjà faite pour cela, car simuler une intéraction au clavier à coups de
_kbhit()
(ou plutôt de
_getch()
) est loin d'être simple.

Sous Linux et systèmes de type Unix, tu as Readline qui est fait pour cela, et qui gère aussi la complétion. Il y a un portage pour Windows de la bibliothèque :

https://tiswww.case.edu/php/chet/readline/rltop.html
http://gnuwin32.sourceforge.net/packages/readline.htm
http://www.delorie.com/gnu/docs/readline/rlman_45.html

Comme c'est sous GNU GPL, ton programme le sera aussi.

Sinon, pour une bibliothèque C avec une licence plus douce, tu as : https://github.com/antirez/linenoise (mais c'est destiné à des systèmes POSIX, pas Windows). Celle-ci https://github.com/arangodb/linenoise-ng, en C++, gère Windows aussi.

En C, il y a aussi http://thrysoee.dk/editline/ (http://mingweditline.sourceforge.net/?Description pour Windows)

Sur un autre sujet, si tu as beaucoup de mots dans ton fichier, et que les temps de réponse sont critiques, tu pourrais réfléchir à une structure de données sous forme d'arbre pour un algorithme efficace de recherche des possibilités de complétion.

Pour les suggestions de mots mal orthographiés, tu peux voir l'excellent article de Peter Norvig http://www.norvig.com/spell-correct.html et la proposition d'implémentation en C de Marcelo Toledo : http://marcelotoledo.com/how-to-write-a-spelling-corrector/


Dal
[Dal]
Messages postés
5169
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
18 juillet 2019
786 -
en C, tu peux utiliser
memcmp()
disponible avec string.h pour comparer le contenu de deux blocs mémoire sur un certain nombre de bytes, ce que tu peux utiliser pour comparer un radical par rapport à une chaîne plus longue.

par exemple :

#include <stdio.h>
#include <string.h>

int main(void)
{
    int n, len;
    char radical[BUFSIZ];
    char * dict[] = {
        "programme",
        "progrès",
        "prophète",
        "proprement",
        "propriétaire",
        "projet"
    };
    const int dict_size = 6;

    /* l'utilisateur tape quelque chose */
    strncpy(radical, "prop", BUFSIZ);
    printf("suggestions pour \"%s\" : ", radical);
    len = strlen(radical);
    for (n = 0; n < dict_size; n++) {
        if (memcmp(radical, dict[n], len) == 0)
            printf("%s ", dict[n]);
    }
    printf("\n");

    return 0;
}

donne (en ligne de commande sous Linux) :
$ gcc -Wall 35400720.c
$ ./a.out
suggestions pour "prop" : prophète proprement propriétaire
$

plus de détails sur memcmp() ici : http://www.cplusplus.com/reference/cstring/memcmp/

Dal
Jessekamba
Messages postés
52
Date d'inscription
mercredi 21 juin 2017
Statut
Membre
Dernière intervention
15 juin 2019
-
Merci dal. J'ai compris l'algorithme avant de le compiler, mais après l'avoir tappé, il génère des erreurs. On dit qu'il ya des bibliothèques qui manquent
[Dal]
Messages postés
5169
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
18 juillet 2019
786 -
Si tu parles du code d'exemple pour memcmp que j'ai posté ci-dessus, il ne nécessite aucune bibliothèque externe, juste la bibliothèque standard du C.Si tu parles d'autres chose, je ne sais pas de quoi tu parles :-)

Fais un copier coller de ton code et des messages d'erreur et poste le tout sur le forum entre balises "code"
Jessekamba
Messages postés
52
Date d'inscription
mercredi 21 juin 2017
Statut
Membre
Dernière intervention
15 juin 2019
-




Ce sont les erreurs que j'ai
Jessekamba
Messages postés
52
Date d'inscription
mercredi 21 juin 2017
Statut
Membre
Dernière intervention
15 juin 2019
-
Et j'ai posté aussi le code pour que tu voie
Messages postés
52
Date d'inscription
mercredi 21 juin 2017
Statut
Membre
Dernière intervention
15 juin 2019
0
Merci
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{

int n, len;
 char radical[BUFSIZ];
 char * dict[] = {'programme','progres','prophete','projet','proprement','proprietaire'};
 const int dict_size=6;
 strncpy(radical,'prop',BUFSIZ);
 printf("suggestion pour \'%s\':",radical );
 len=strlen(radical);
 for (n=0;n<dict_size;n++){


 	if (memcmp(radical,dict[n],len )==0)
 		printf("%s",dict[n] );
 }

printf("\n");
return 0;
}
[Dal]
Messages postés
5169
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
18 juillet 2019
786 -
Mon code avait pour objectif de répondre à ta question "Le Langage C n'a pas une fonction comme like en VBA qui compare les données si elles sont les même ?" en te donnant un exemple simple d'utilisation de la fonction standard memcmp, pas de faire le programme à ta place. Je ne sais pas si, dans ton cas, un simple tableau de pointeurs sur des chaînes C est pertinent.

comment je peux faire pour le faire à partir de mon fichier txt qui contient les mots ?

Renseigne toi sur les fonctions standard fopen, fgets (pour lire ligne par ligne dans un fichier texte) et fread (pour lire en blocs). Tu devras gérer la mémoire nécessaire avec malloc / free.

Mais j'aimerais le demander a l utilisateur, quand il tape on vérifie s'il existe dans le fichier et on lui donne les résultats

Pour lire quelque chose au clavier, tu peux utiliser des fonctions standard du C comme scanf ou fgets, mais elles interrompront l'exécution du programme tant que l'utilisateur n'aura pas tapé entrée. Si tu veux vraiment un affichage de suggestions qui puissent s'afficher alors que l'utilisateur n'a pas encore validé sa saisie, cela n'existe pas en C standard.

Si GNU readline (qui peut être utilisé pour afficher des suggestions sur la base d'un radical en pressant Tab) ne convient pas à tes besoins, tu peux construire ta propre interface utilisateur avec ncurses, pdcurses, l'API Windows si tu es sous Windows, ou faire quelque chose de très basique avec conio.h.

Tout cela est plus ou moins complexe à mettre en oeuvre, plus ou moins ergonomique, et on ne peut pas faire ces choix à ta place.

A vrai dire, comme indiqué dans mon post d'origine, je ne comprend pas très bien ton projet, ni pourquoi tu fais cela en ligne de commande (et en C). De plus, tu dis que tu es débutant, et ce projet est loin de convenir à un débutant si tu veux vraiment le faire comme tu le dis. Peux-tu en dire plus ?

Dal
[Dal]
Messages postés
5169
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
18 juillet 2019
786 -
sinon, par rapport à ton code là : https://www.commentcamarche.net/forum/affich-35400720-manipulation-des-fichiers#17

il affiche toute la liste de mots sur chaque ligne du fichier parce que tu fais un
puts(buffer);
après avoir lu chaque ligne avec fgets.

si tu veux afficher ce mot seulement s'il existe dans le dictionnaire, met ce
puts(buffer);
dans les accolades du
if (strcmp(buffer,tab)==0)
...

l'indentation de ton code n'est pas lisible
[Dal]
Messages postés
5169
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
18 juillet 2019
786 -
il y a aussi un bogue dans ton code, lorsque tu demande le mot avec fgets, ton code pour supprimer le newline devrait être :

    {
        char *p=strchr(tab,'\n');
        if (p != NULL)
            *p='\0';
    }

au lieu de ce que tu as écrit, qui écrase juste le pointeur p avec 0

tu le fais correctement ensuite pour les fgets lisant à partir du fichier.
Jessekamba
Messages postés
52
Date d'inscription
mercredi 21 juin 2017
Statut
Membre
Dernière intervention
15 juin 2019
-
Merci dal. Je m'y met et je consulte déjà le lien.
Et concernant le code que j'ai posté j'ai dû apporter des changements mais cette fois ci, le programme me retourne le même mot entré au clavier comme résultat.
[Dal]
Messages postés
5169
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
18 juillet 2019
786 -
quel est le code désormais ?
Messages postés
52
Date d'inscription
mercredi 21 juin 2017
Statut
Membre
Dernière intervention
15 juin 2019
0
Merci
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){
char tab[BUFSIZ];
char buffer[BUFSIZ];
FILE * fp=fopen("dictionnaire_francais.txt","r");
if (fp == NULL){
fputs("Erreur a l ouverture du fichier \n",stderr);
return EXIT_FAILURE;
}
puts("Votre mot");
fgets(tab, sizeof tab,stdin);
puts(tab);

{
char *p=strchr(tab,'\n');
if (p != NULL)
p='\0' ;
}
while (fgets(buffer,sizeof(buffer),fp)){
 char *p= strchr(buffer,'\n'); 
if (p != NULL){ *p='\0'; } 

 if (strcmp(buffer,tab)==0){
 puts("existe"); 
 puts(buffer);
}
}
fclose(fp);
fp= NULL;
return 0;
} 
[Dal]
Messages postés
5169
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
18 juillet 2019
786 -
tu n'as toujours pas corrigé la ligne 20 comme je te disais de le faire https://www.commentcamarche.net/forum/affich-35400720-manipulation-des-fichiers#20

remplace
p='\0' ;
par
*p='\0';
sinon tu écrases ton pointeur
[Dal]
Messages postés
5169
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
18 juillet 2019
786 -
note que tu devrais plutôt stocker en mémoire les mots du dictionnaire, car tu ne vas pas ouvrir le fichier et parcourir son contenu à chaque fois que tu voudras vérifier un mot.
Messages postés
52
Date d'inscription
mercredi 21 juin 2017
Statut
Membre
Dernière intervention
15 juin 2019
0
Merci
Je viens de remplacer maintenant mais, ça ne change rien. On me renvoi toujours le même mot
[Dal]
Messages postés
5169
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
18 juillet 2019
786 -
ton code corrigé comme je te l'indique :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){
    char tab[BUFSIZ];
    char buffer[BUFSIZ];
    FILE * fp=fopen("dictionnaire_francais.txt","r");
    if (fp == NULL){
        fputs("Erreur a l ouverture du fichier \n",stderr);
        return EXIT_FAILURE;
    }
    puts("Votre mot");
    fgets(tab, sizeof tab,stdin);
    puts(tab);

    {
        char *p=strchr(tab,'\n');
        if (p != NULL)
            *p='\0';
    }
    while (fgets(buffer,sizeof(buffer),fp)){
        char *p= strchr(buffer,'\n');
        if (p != NULL){ *p='\0'; }

        if (strcmp(buffer,tab)==0){
            puts("existe");
            puts(buffer);
        }
    }
    fclose(fp);
    fp= NULL;
    return 0;
}

avec dictionnaire_francais.txt comprenant (avec les accents retirés, comme tu l'as écris dans ton code là https://www.commentcamarche.net/forum/affich-35400720-manipulation-des-fichiers#12) :

programme
progres
prophete
projet
proprement
proprietaire

compilé et exécuté avec différentes valeurs :

$ gcc -Wall 35400720.c
$ ./a.out
Votre mot
pprojet
pprojet

$ ./a.out
Votre mot
projet
projet

existe
projet
$

renvoie bien "existe" si le mot existe dans le fichier.

Dal
Messages postés
5169
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
18 juillet 2019
786
0
Merci
Sinon, comme indiqué précédemment, tu devrais plutôt stocker en mémoire les mots du dictionnaire, car tu ne vas pas ouvrir le fichier et parcourir son contenu à chaque fois que tu voudras vérifier un mot.

Tu peux éventuellement utiliser la méthode décrite dans ce post :

https://www.commentcamarche.net/forum/affich-35265601-novice-dans-la-programmation#17

pour charger la totalité du fichier avec fread et parser le contenu en sous-chaînes représentant les mots avec strtok et
'\n'
comme caractère séparateur.

Dal
[Dal]
Messages postés
5169
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
18 juillet 2019
786 -
Note que dans cet exemple, les chaînes sont stockées dans un tableau.

Si ton dictionnaire est volumineux, et que tu as fait le choix d'une structure de données sous forme de tableau, il se peut que l'exécution de ton programme soit étranglée si tu fais des recherches séquentielles dans le tableau, qui peuvent pénaliser les temps d'exécution. Il te faudra alors réfléchir à une structure de données et algorithme de recherche plus efficace.

J'ai déjà mentionné les arbres ternaire de recherche, qui paraissent adaptés à une recherche par radical.

Sin, en fait, les recherches par radical ne t'intéressent pas, pour des recherches à l'identique, les hash sont rapides, mais ils sont complexes à mettre en oeuvre.

Autrement, pour des recherches à l'identique (et dans une certaine mesure par radical), tu peux obtenir des performances acceptables de recherche sur un tableau ordonné avec un algorithme de recherche dichotomique. C'est sans doutes l'optimisation la plus à la portée d'un débutant, si tu as besoin d'optimiser les temps d'exécution :

https://fr.wikipedia.org/wiki/Recherche_dichotomique

En tout cas, bon courage pour la finalisation de ton projet :-)

Dal