Partage
  • Partager sur Facebook
  • Partager sur Twitter

Comparer deux chaînes avec une marge d'erreur

    10 mai 2016 à 18:52:09

    Bonjour bonjour.

    J'ai une petite question qui me pose bien des soucis :/

    Je suis sur la création d'un "Assistant" en C, qui répond à des questions basiques et qui lance, sur demande, d'autres partie de mon programme (convertisseurs, stockage de données etc, mais on s'en fiche ^^)

    Le probleme, c'est que pour que le logiciel comprenne la phrase de l'utilisateur, celle ci ne doit comporter aucune faute. Et comme vous vous en doutez, cela pose des problemes.

    Mon système fonctionne comme ça :

    Je déclare toutes mes phrases me servant de modèles dans des chaines :

    char douze[] = "Quel_est_le_sens_de_la_vie";

    Puis on demande à l'utilisateur de taper une chaine :

    char Question[500] = "";
    
    scanf("%s", Question);

    Ensuite, on compare les deux chaines

    if (strcmp(douze, Question) == 0)
        {
            printf("\n\n42, bien sur.\n\n\n");
            AssistantExecute();
        }

    Et si les deux chaines sont identiques, le programme repond puis relance la fonction servant à entrer le texte.

    Si les chaines ne sont pas identiques, la programme passe au if suivant pour comparer jusqu'à toutes les phrases, et si aucune ne correspond :

     else
        {
            printf("\n\nJe ne connais pas cette phrase, desole.\n\n\n");
            AssistantExecute();
        }

    Ma question : Comment faire pour que si j'écrive par exemple "Quel_es_le_sens_de_la_vie" ou encore "Qel_est_le_sans_de_la_vie", le programme comprenne (avec une marge d'erreur limitée bien sur) qu'il s'agit de "Quel_est_le_sens_de_la_vie" ?

    M'apporter des informations par exemple un topic qui en parle un tuto ou que vous m'expliquiez vous même (je vous préviens je suis vraiment débutant, bien que je fasse des codes de plusieurs milliers de lignes avec seulement des trucs basics ^^) serait vraiment sympa !

    Ou alors/et quelque chose qui pourrait reconnaitre mot par mot une phrase pour que par exemple "Tu_es_qui" corresponde à "Qui_es_tu"

    Merci d'avance !



    • Partager sur Facebook
    • Partager sur Twitter
      12 mai 2016 à 10:29:06

      Bonjour,

      Tu vas pouvoir t'orienter vers une distance entre tes deux chaînes (distance de Levenshtein par exemple) pour calculer la proximité entre tes chaînes. À toi ensuite de définir un seuil à partir duquel tu considères les chaînes comme semblables.

      • Partager sur Facebook
      • Partager sur Twitter
        12 mai 2016 à 13:13:16

        Merci de ta réponse, c'est quelque chose comme ça ? (trouvé sur wiki pour l'exemple)

        private Int32 levenshtein(String a, String b)
                {
        
                    if (string.IsNullOrEmpty(a))
                    {
                        if (!string.IsNullOrEmpty(b))
                        {
                            return b.Length;
                        }
                        return 0;
                    }
        
                    if (string.IsNullOrEmpty(b))
                    {
                        if (!string.IsNullOrEmpty(a))
                        {
                            return a.Length;
                        }
                        return 0;
                    }
        
                    Int32 cost;
                    Int32[,] d = new int[a.Length + 1, b.Length + 1];
                    Int32 min1;
                    Int32 min2;
                    Int32 min3;
        
                    for (Int32 i = 0; i <= d.GetUpperBound(0); i += 1)
                    {
                        d[i, 0] = i;
                    }
        
                    for (Int32 i = 0; i <= d.GetUpperBound(1); i += 1)
                    {
                        d[0, i] = i;
                    }
        
                    for (Int32 i = 1; i <= d.GetUpperBound(0); i += 1)
                    {
                        for (Int32 j = 1; j <= d.GetUpperBound(1); j += 1)
                        {
                            cost = Convert.ToInt32(!(a[i-1] == b[j - 1]));
        
                            min1 = d[i - 1, j] + 1;
                            min2 = d[i, j - 1] + 1;
                            min3 = d[i - 1, j - 1] + cost;
                            d[i, j] = Math.Min(Math.Min(min1, min2), min3);
                        }
                    }
        
                    return d[d.GetUpperBound(0), d.GetUpperBound(1)];
        
                }

        Si c'est le cas j'ai pas le niveau pour tout comprendre et j'ai pas envie d'implémenter du code que je ne comprend pas :/

        Tu connaitrais un bon tuto/cours ? Car mes recherches me donne des choses qui, j'ai l'impression, n'ont pas trop de rapport '-'

        Bonne journée.

        • Partager sur Facebook
        • Partager sur Twitter
          12 mai 2016 à 14:25:12

          Oui c'est bien cet algorithme. Non je ne connais pas de cours sur la question, mais ça n'est pas si compliqué. Il s'agit d'itérer sur les deux chaînes et d'accumuler les nombres de modifications minimales pour passer d'une chaîne à l'autre (une modification pouvant être un remplacement, une insertion ou une suppression).

          Le code que tu montres s'appuie par exemple sur une matrice N×M pour stocker ces coûts et les propager de façon à ce que la distance totale se retrouve dans la dernière case de la dernière ligne de ta matrice. Mais il y a d'autres implémentations possibles pour l'algorithme, notamment certaines qui se basent sur deux vecteurs plutôt qu'une matrice.

          Sans intégrer une fonction que tu ne comprends pas, tu peux tout de même faire appel à une bibliothèque externe qui l'implémente, non ? C'est même sûrement ce que tu fais déjà avec la fonction scanf, tu l'utilises sans en comprendre toutes les subtilités.

          • Partager sur Facebook
          • Partager sur Twitter
            12 mai 2016 à 17:26:17

            D'accord merci beaucoup, je vais essayer de chercher des cours sur ça, mais dans le pire des cas j'attendrais de connaître plus de choses car je suis vraiment débutant pour l'instant.

            Oui mais je doute qu'une bibliothèque puisse faire ceci en une simple lignes de codes :p et dans tous les cas je n'aime pas trop, certe je ne sais pas COMMENT marche vraiment scanf (et au passage je ne l'utilise pas vraiment ^^ du fgets pour que cela écrive dans ma chaine, que le programme la compare grace a des mots clés avec un str str aux réponses pré-enregistré, et donc que le programme me réponde/execute mes ordres, enfin bref revenons à notre sujet), mais je sais bien sur a quoi il correspond, alors que copier coller un texte depuis google c'est pas mon truc ça :)

            Bonne journée et merci.

            • Partager sur Facebook
            • Partager sur Twitter
              12 mai 2016 à 21:18:45

              Si une bibliothèque comporte cette fonction, je ne vois pas pourquoi tu ne pourrais pas l'utiliser avec une simple ligne de code.

              • Partager sur Facebook
              • Partager sur Twitter

              Comparer deux chaînes avec une marge d'erreur

              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
              • Editeur
              • Markdown