C Racine commune

C Racine commune - C - Programmation

Marsh Posté le 17-04-2016 à 23:28:19    

Bonjour,
 
Je suis à la recherché d'une function en C ou d'un algorithme qui permettrait de garder seulement les racines communes dans une liste classé par ordre alphabetique.
J'ai essayé avec un strtok mais sans success.
 
Par exemple: bonjour, bonsoir => racine commune bon
Pour info: MaListe est une variable globale contenant les mots bonjour, bonsoir ... etc
 

Code :
  1. void RootCommon(void)
  2. {
  3.     unsigned int MyLen1, MyLen2, MyLen;
  4.     unsigned int MyFlg;
  5.     unsigned char MyChar1, MyChar2;
  6.     unsigned int MyIdx;   
  7.     unsigned char MyRoot[20];
  8.     // Init.
  9.     MyLen = 0;
  10.     MyLen1 = 0;
  11.     MyLen2 = 0;
  12.     MyFlg = 0;
  13.     MyIndex = 0;
  14.     MyChar1 = 0;
  15.     MyChar2 = 0;
  16.     printf("\n" );
  17.     while (MyFlg == 0)
  18.     {
  19.         MyPtr1 = *(MaListe + MyIndex);
  20.         MyPtr2 = *(MaListe + MyIndex+1);
  21.         MyLen1 = strlen(MyPtr1);
  22.         MyLen2 = strlen(MyPtr2);
  23.         if (MyLen1 > MyLen2)
  24.             MyLen = MyLen2;
  25.         else
  26.             MyLen = MyLen1;
  27.         memset((void*) MyRoot,'\0', sizeof(unsigned char)*20);
  28.         for(MyIdx=0; MyIdx < MyLen; MyIdx++)
  29.         {
  30.             MyChar1 = *(MyPtr1+MyIdx);
  31.             MyChar2 = *(MyPtr2+MyIdx);
  32.             if (MyChar1 != MyChar2)
  33.             {
  34.                 if (strlen((const char*)MyRoot)>0)
  35.                     printf("Racine commune:%s\n",MyRoot);
  36.                 break;
  37.             }
  38.             else
  39.             {
  40.                 MyRoot[MyIdx]=MyChar1;
  41.                 printf(" |_Mot %02d - Lettre %c - Mot %02d - Lettre %c\n",
  42.                         MyIndex, MyChar1, MyIndex+1, MyChar2);
  43.             }
  44.             if (MyIdx == (MyLen-1))
  45.             {
  46.                 memset((void*) MyRoot, '\0', sizeof(unsigned char)*20);
  47.                 printf("  |_Mot %s entierement contenu dans mot %s\n", MyPtr1, MyPtr2);
  48.             }
  49.         }
  50.         printf("\n" );
  51.        
  52.         MyIndex++;
  53.         if ((MyIndex+1) > NbrMot)
  54.             MyFlg = 1;
  55.     }

Reply

Marsh Posté le 17-04-2016 à 23:28:19   

Reply

Marsh Posté le 18-04-2016 à 13:57:18    

Si tu veux de l'aide c'est toujours bien de faciliter la tâche aux gens en donnant un exemple complet et compilable.
 

Code :
  1. > "gcc" "tst.c" -Wall -O3 -c
  2. tst.c: In function 'RootCommon':
  3. tst.c:13:2: error: 'MyIndex' undeclared (first use in this function)
  4. tst.c:13:2: note: each undeclared identifier is reported only once for each function it appears in
  5. tst.c:16:2: warning: implicit declaration of function 'printf' [-Wimplicit-function-declaration]
  6. tst.c:16:2: warning: incompatible implicit declaration of built-in function 'printf' [enabled by default]
  7. tst.c:19:3: error: 'MyPtr1' undeclared (first use in this function)
  8. tst.c:19:14: error: 'MaListe' undeclared (first use in this function)
  9. tst.c:20:3: error: 'MyPtr2' undeclared (first use in this function)
  10. tst.c:21:3: warning: implicit declaration of function 'strlen' [-Wimplicit-function-declaration]
  11. tst.c:21:12: warning: incompatible implicit declaration of built-in function 'strlen' [enabled by default]
  12. tst.c:27:3: warning: implicit declaration of function 'memset' [-Wimplicit-function-declaration]
  13. tst.c:27:3: warning: incompatible implicit declaration of built-in function 'memset' [enabled by default]
  14. tst.c:53:21: error: 'NbrMot' undeclared (first use in this function)
  15. tst.c:55:1: error: expected declaration or statement at end of input


 
Certes, c'est des choses faciles à corriger, mais bon...
 
Ceci étant, les signed/unsigned char c'est pour des nombres, pour des caractères on utilise simplement char. Pourquoi tu as mis un cast void* dans l'appel de memset()? Et pour strlen() si tu déclares ton MyRoot simplement comme char[] pas besoin de cast non plus (testé avec GCC 4.7.2 -Wall).

Reply

Marsh Posté le 18-04-2016 à 20:47:54    

Bon, je m'ennuais, c'est ce genre de truc dont tu as besoin? A completer...
 

Code :
  1. #include <stdio.h>
  2. #include <string.h>
  3. #define SZ_BUF 20
  4. int main(void)
  5. {
  6.     char *mot1="abcdefghjklhfdsdcpogrdaa";
  7.     char *mot2="abcdefghjklhfdsdcpogrdbb";
  8.    
  9.     char racine[SZ_BUF];
  10.    
  11.     if(strcmp(mot1, mot2)==0)
  12.     {
  13.         printf("(1) et (2) sont identiques\n" );
  14.     }
  15.     else if(strstr(mot1, mot2))
  16.     {
  17.         printf("%s (2) est contenu dans %s (1)\n", mot2, mot1);
  18.     }
  19.     else if(strstr(mot2, mot1))
  20.     {
  21.         printf("%s (1) est contenu dans %s (2)\n", mot1, mot2);
  22.     }
  23.     else
  24.     {
  25.         int i;
  26.         for(i=0;mot1[i]&&mot2[i]&&mot1[i]==mot2[i]&&i<(SZ_BUF-1);i++)
  27.             racine[i]=mot1[i];
  28.         racine[i]='\0';
  29.        
  30.         if(i)
  31.         {
  32.             printf("racine commune: %s\n", racine);
  33.         }
  34.     }
  35.    
  36.     return 0;
  37. }

Reply

Marsh Posté le 19-04-2016 à 23:09:35    

rat de combat a écrit :

Bon, je m'ennuais, c'est ce genre de truc dont tu as besoin? A completer...
 

Code :
  1. #include <stdio.h>
  2. #include <string.h>
  3. #define SZ_BUF 20
  4. int main(void)
  5. {
  6.     char *mot1="abcdefghjklhfdsdcpogrdaa";
  7.     char *mot2="abcdefghjklhfdsdcpogrdbb";
  8.    
  9.     char racine[SZ_BUF];
  10.    
  11.     if(strcmp(mot1, mot2)==0)
  12.     {
  13.         printf("(1) et (2) sont identiques\n" );
  14.     }
  15.     else if(strstr(mot1, mot2))
  16.     {
  17.         printf("%s (2) est contenu dans %s (1)\n", mot2, mot1);
  18.     }
  19.     else if(strstr(mot2, mot1))
  20.     {
  21.         printf("%s (1) est contenu dans %s (2)\n", mot1, mot2);
  22.     }
  23.     else
  24.     {
  25.         int i;
  26.         for(i=0;mot1[i]&&mot2[i]&&mot1[i]==mot2[i]&&i<(SZ_BUF-1);i++)
  27.             racine[i]=mot1[i];
  28.         racine[i]='\0';
  29.        
  30.         if(i)
  31.         {
  32.             printf("racine commune: %s\n", racine);
  33.         }
  34.     }
  35.    
  36.     return 0;
  37. }



 
Bonsoir,
 
Merci pour votre réponse et désolé pour le programme qui ne compile pas, j'ai fait un copier-coller brutal.
Effectivement votre code marche cependant je pense que l'analyse de mon problème n'est pas la bonne.
 
Mon besoin est de pouvoir isoler des termes afin de définir une racine commune
Par exemple; j'ai les mots suivants classés de façon alphabetique donc sans doublon:
- adverb
- adverbial
- adverbially
- adversary
- adverse
- adversity
 
Le résultat que je souhaite obtenir aprés le passage de ma fonction est le suivant:
- adverb car adverb, adverbial et adverbially ont pour racine commune seulement adverb
- advers car adversary, adverse et adversity ont pour racine commune seulement advers
 
C'est là que je commence à bloquer, je ne sais pas comment procéder soit je parcours chaque mot lettre par lettre: la 1ere lettre, la 2e lettre et la 3e lettre et j'isole ...
J'ai repris votre programme et en modifiant les mot1, mot2 en les liant à un tableau contenant mes exemples ... mais sans succès

Reply

Marsh Posté le 19-04-2016 à 23:10:38    

rat de combat a écrit :

Bon, je m'ennuais, c'est ce genre de truc dont tu as besoin? A completer...
 

Code :
  1. #include <stdio.h>
  2. #include <string.h>
  3. #define SZ_BUF 20
  4. int main(void)
  5. {
  6.     char *mot1="abcdefghjklhfdsdcpogrdaa";
  7.     char *mot2="abcdefghjklhfdsdcpogrdbb";
  8.    
  9.     char racine[SZ_BUF];
  10.    
  11.     if(strcmp(mot1, mot2)==0)
  12.     {
  13.         printf("(1) et (2) sont identiques\n" );
  14.     }
  15.     else if(strstr(mot1, mot2))
  16.     {
  17.         printf("%s (2) est contenu dans %s (1)\n", mot2, mot1);
  18.     }
  19.     else if(strstr(mot2, mot1))
  20.     {
  21.         printf("%s (1) est contenu dans %s (2)\n", mot1, mot2);
  22.     }
  23.     else
  24.     {
  25.         int i;
  26.         for(i=0;mot1[i]&&mot2[i]&&mot1[i]==mot2[i]&&i<(SZ_BUF-1);i++)
  27.             racine[i]=mot1[i];
  28.         racine[i]='\0';
  29.        
  30.         if(i)
  31.         {
  32.             printf("racine commune: %s\n", racine);
  33.         }
  34.     }
  35.    
  36.     return 0;
  37. }



 
Bonsoir,
 
Merci pour votre réponse et désolé pour le programme qui ne compile pas, j'ai fait un copier-coller brutal.
Effectivement votre code marche cependant je pense que l'analyse de mon problème n'est pas la bonne.
 
Mon besoin est de pouvoir isoler des termes afin de définir une racine commune
Par exemple; j'ai les mots suivants classés de façon alphabetique donc sans doublon:
- adverb
- adverbial
- adverbially
- adversary
- adverse
- adversity
 
Le résultat que je souhaite obtenir aprés le passage de ma fonction est le suivant:
- adverb car adverb, adverbial et adverbially ont pour racine commune seulement adverb
- advers car adversary, adverse et adversity ont pour racine commune seulement advers
 
C'est là que je commence à bloquer, je ne sais pas comment procéder soit je parcours chaque mot lettre par lettre: la 1ere lettre, la 2e lettre et la 3e lettre et j'isole ...
J'ai repris votre programme et en modifiant les mot1, mot2 en les liant à un tableau contenant mes exemples ... mais sans succès

Reply

Marsh Posté le 20-04-2016 à 10:22:20    

Je fais ce genre de chose avec un arbre n-aire. (eg: http://www.chambily.com/recursivite/chap_VII_4.htm )

 

Bon ça peut sembler énorme à mettre en place pour ce que tu veux faire, mais c'est très puissant!


Message édité par h3bus le 20-04-2016 à 10:22:38

---------------
sheep++
Reply

Marsh Posté le 20-04-2016 à 10:27:42    

Certes, mais c'est pas ça qui va donner les racines. Il lui faut une heuristique pour déterminer quand on considère que la terminaison d'un mot ne fait plus partie de la racine commune, et pour le moment, je n'ai pas vu qu'il en propose une.
 
A+,


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

Marsh Posté le 20-04-2016 à 11:58:42    

Effectivement, il faut un critère.
 
Je m'ennuyais donc j'ai fait un exemple en python

Code :
  1. class Wordstree():
  2.     def __init__(self, word="" ):
  3.         self.children = {}
  4.         self.isword = False
  5.        
  6.         if len(word) == 0:
  7.             self.value = ''
  8.            
  9.         else:
  10.             self.value = word[0]
  11.            
  12.             if len(word) > 1:
  13.                 self.children[word[1]]= Wordstree(word[1:])
  14.             else:
  15.                 self.isword = True
  16.    
  17.     def append(self, word):
  18.         if len(word) == 0:
  19.             return
  20.            
  21.         elif word[0] in self.children:
  22.             self.children[word[0]].append(word[1:])
  23.        
  24.         else:
  25.             self.children[word[0]] = Wordstree(word)
  26.        
  27.         if len(word) == 1:
  28.             self.isword = True
  29.    
  30.     def isRoot(self):
  31.         return len(self.children) > 1
  32.    
  33.     def getChildRoots(self, root="" ):
  34.         roots = []
  35.        
  36.         if self.isRoot():
  37.             for key in self.children.iterkeys():
  38.                 roots += [root+self.value+key]
  39.            
  40.         for key, value in self.children.iteritems():
  41.             roots += value.getChildRoots(root + self.value)
  42.        
  43.         return roots
  44. words = [
  45.     "adverb",
  46.     "adverbial",
  47.     "adverbially",
  48.     "adversary",
  49.     "adverse",
  50.     "adversity"
  51.     ]
  52. tree = Wordstree();
  53. for word in words:
  54.     tree.append(word)
  55. print tree.getChildRoots()


 
Résultat:

Code :
  1. >python wordtree.py
  2. ['advers', 'adverb', 'adversa', 'adversi', 'adverse']


---------------
sheep++
Reply

Marsh Posté le 20-04-2016 à 14:30:02    

sined40 a écrit :

Effectivement votre code marche cependant je pense que l'analyse de mon problème n'est pas la bonne.


Je me disais bien que c'était trop facile... Désolé, je sèche...

Reply

Sujets relatifs:

Leave a Replay

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