Partage
  • Partager sur Facebook
  • Partager sur Twitter

Les espaces superflues

suppression des espaces superflues en utilisant les pointeurs

Anonyme
    28 juillet 2016 à 22:10:31

    Salut,

    j'ai essaye de supprimer les espaces superflues dans une phrase donnée mais mon code ne marche pas

    je veux savoir mieux et apprendre comment faire ça sans erreurs !

    #include<stdio.h>
    #include<stdlib.h>
    #include<ctype.h>
    #include<string.h>
    #include<conio.h>
    
    //prototypes
    
    char* strspace(char *chaine);
    
    //main
    int main(void)
    {
    	char phrase[1000];
    
    	puts(" \n \n Donner une phrase  \n \n  ");
    	gets(phrase);
    	strspace(phrase);
    	printf(" \n \n   Votre phrase apr%cs modification         : \t  %s        \n \n \n  ", phrase);
    
    	getch();
    }
    
    char* strspace(char * chaine)
    {
    	//declaration
    
    	char  *pointeur1 = NULL;
    	int longueur = strlen(chaine);
    
    	//traitement
    	if (longueur == 0)
    	{
    		printf(" \n \n FATAL ERROR !!!!!!!!!!!!!!  \n \n \n  ");
    		printf(" IMPOSSIBLE DE TRAVAILLER AVEC UNE CHAINE VIDE  \n \n \n  ");
    		exit(EXIT_FAILURE);
    	}
    	pointeur1 = chaine;
    	for (pointeur1 = chaine; pointeur1 < chaine + longueur - 1; pointeur1++)
    	{
    		if (isspace(*pointeur1) && isspace(*(pointeur1 + 1)))
    		{
    			*pointeur1 =*(pointeur1+1);
    
    		}
    	}
    	*chaine = *pointeur1;
    	return pointeur1;
    }



    • Partager sur Facebook
    • Partager sur Twitter
      28 juillet 2016 à 23:42:25

      Bonjour,

      Un gros bug est dans le printf, avec un "%c" et un "%s", mais un seul paramètre suivant.

      Dans strspace, il n'y a aucune raison de refuser de traiter les chaines vides.

      Il n'y a que des commentaires inutiles dans le code, mais il manque des commentaires cruciaux, comme
      - que retourne strspace
      - que fait strspace des espaces initiaux
      - que fait strspace des espaces finaux

      L'algorithme implémenté est extrêmement douteux.
      Et l'implémentation serait plus claire avec deux indices à la place du (mal nommé) pointeur1 ; un indice de lecture de chaine, et un indice d'écriture de chaine.

      -
      Edité par Marc Mongenet 28 juillet 2016 à 23:42:58

      • Partager sur Facebook
      • Partager sur Twitter
      Anonyme
        29 juillet 2016 à 21:25:58

        salut,

        j'ai pas compris le principe  

        une fois que je que je comprends le principe ce problème sera résolu directement 

        • Partager sur Facebook
        • Partager sur Twitter
          29 juillet 2016 à 22:48:13

          Afficher 2 carrés sur trois en maîtrise du C et demander de l'aide sur un programme qui supprime des espaces superflus.... Tu ne trouves pas ça un peu exagéré ? D'autant plus que ce n'est pas la première fois :

          https://openclassrooms.com/forum/sujet/les-structures-13

          https://openclassrooms.com/forum/sujet/concatiner-deux-chaines

          https://openclassrooms.com/forum/sujet/sprintf-1

          https://openclassrooms.com/forum/sujet/passage-par-adresse-et-les-pointeurs-1

          etc.....

          FaresBenslama a écrit:

          une fois que je que je comprends le principe ce problème sera résolu directement 

          J'en doute pas  ! ;)

          • Partager sur Facebook
          • Partager sur Twitter
          Anonyme
            29 juillet 2016 à 23:23:58

            Bonjour,

            Avant toutes choses, débarrasse-toi de ton gets() et remplace-le par un fgets() plutôt.

            Ensuite, le int longueur = strlen(chaine); c'est plutôt dans un size_t qu'il faudrait le stocker. Tu cherches à savoir ce qu'est size_t ? La question a déjà été posée ici.

            Tu peux remplacer if (longueur == 0) par if (!longueur), ça revient au même.

            Après, à la vue de ton code, je pense effectivement que le principe n'est pas maîtrisé.

            Pour la condition de la boucle for, je ne vois pas trop pourquoi tu écris ceci pointeur1 < chaine + longueur - 1 surtout que si tu voulais une condition de fin de boucle, tu pouvais écrire *pointeur1 tout simplement.

            Pour la condition if, c'est compris donc je n'y reviens pas.

            Ensuite pour cette ligne *pointeur1 =*(pointeur1+1); j'ai l'impression que tu essaies de modifier la chaîne directement (même si c'est fait de manière maladroite). Je sais que le C n'est pas un langage orienté objet, mais dans d'autre langages de ce type qui utilisent une méthode agissant sur des chaînes de caractères, en principe on ne modifie jamais cette chaîne, on en renvoie toujours une autre. Et puis on sait jamais si ton client en a besoin plus tard. Donc tu as très bien mis le type de valeur renvoyé par ta fonction. La suite sera de réadapter le code en considération de tous ces éléments.

            Donc le principe c'est : tu créé un pointeur sur caractère que tu initialise. Tu vas lui allouer suffisamment d'espace pour un simple caractère de fin de chaîne. Ensuite dans ta boucle, quand ta condition sera vérifiée (donc deux espaces trouvés à la suite), tu reboucles sans continuer les instructions. Sinon, tu ré-alloues une case-mémoire supplémentaire à ta chaîne et tu ajoutes le pointeur sur caractère. Et tu ajoutes à nouveau un caractère de fin de chaîne à la fin puisqu'il a été remplacé par ton nouveau caractère. Et une fois que c'est fini, tu renvoies simplement l'adresse de la chaîne allouée dynamiquement et tu n'oublie pas de libérer la mémoire dans la fonction principale.

            J'espère que j'ai été suffisamment clair pour toi, j'ai essayé d'expliquer au mieux.

            • Partager sur Facebook
            • Partager sur Twitter
              29 juillet 2016 à 23:45:36

              AminNairi a écrit:

              [...]

              Donc le principe c'est : tu créé un pointeur sur caractère que tu initialise. Tu vas lui allouer suffisamment d'espace pour un simple caractère de fin de chaîne. Ensuite dans ta boucle, quand ta condition sera vérifiée (donc deux espaces trouvés à la suite), tu reboucles sans continuer les instructions. Sinon, tu ré-alloues une case-mémoire supplémentaire à ta chaîne et tu ajoutes le pointeur sur caractère. Et tu ajoutes à nouveau un caractère de fin de chaîne à la fin puisqu'il a été remplacé par ton nouveau caractère. Et une fois que c'est fini, tu renvoies simplement l'adresse de la chaîne allouée dynamiquement et tu n'oublie pas de libérer la mémoire dans la fonction principale.

              Bonjour,

              bon c'est un peu HS, mais c'est très inefficace de procéder ainsi. Il vaut mieux préférer une réallocation exponentielle plutôt que linéaire. En même temps le PO n'a clairement pas le niveau.

              AminNairi a écrit:

              [...]
              Ensuite pour cette ligne *pointeur1 =*(pointeur1+1); j'ai l'impression que tu essaies de modifier la chaîne directement (même si c'est fait de manière maladroite). Je sais que le C n'est pas un langage orienté objet, mais dans d'autre langages de ce type qui utilisent une méthode agissant sur des chaînes de caractères, en principe on ne modifie jamais cette chaîne, on en renvoie toujours une autre. Et puis on sait jamais si ton client en a besoin plus tard. Donc tu as très bien mis le type de valeur renvoyé par ta fonction. La suite sera de réadapter le code en considération de tous ces éléments.

              [...]

              Mouais, c'est usuel quand même de faire un traitement in place en C car ce qu'on utilise comme string n'est pas imutable, contrairement à d'autres langages.

              • Partager sur Facebook
              • Partager sur Twitter
              First solve the problem. Then, write the code. ~ John Johnson
              Anonyme
                31 juillet 2016 à 3:53:05

                AminNairi a écrit:

                Bonjour,

                Avant toutes choses, débarrasse-toi de ton gets() et remplace-le par un fgets() plutôt.

                Ensuite, le int longueur = strlen(chaine); c'est plutôt dans un size_t qu'il faudrait le stocker. Tu cherches à savoir ce qu'est size_t ? La question a déjà été posée ici.

                Tu peux remplacer if (longueur == 0) par if (!longueur), ça revient au même.

                Après, à la vue de ton code, je pense effectivement que le principe n'est pas maîtrisé.

                Pour la condition de la boucle for, je ne vois pas trop pourquoi tu écris ceci pointeur1 < chaine + longueur - 1 surtout que si tu voulais une condition de fin de boucle, tu pouvais écrire *pointeur1 tout simplement.

                Pour la condition if, c'est compris donc je n'y reviens pas.

                Ensuite pour cette ligne *pointeur1 =*(pointeur1+1); j'ai l'impression que tu essaies de modifier la chaîne directement (même si c'est fait de manière maladroite). Je sais que le C n'est pas un langage orienté objet, mais dans d'autre langages de ce type qui utilisent une méthode agissant sur des chaînes de caractères, en principe on ne modifie jamais cette chaîne, on en renvoie toujours une autre. Et puis on sait jamais si ton client en a besoin plus tard. Donc tu as très bien mis le type de valeur renvoyé par ta fonction. La suite sera de réadapter le code en considération de tous ces éléments.

                Donc le principe c'est : tu créé un pointeur sur caractère que tu initialise. Tu vas lui allouer suffisamment d'espace pour un simple caractère de fin de chaîne. Ensuite dans ta boucle, quand ta condition sera vérifiée (donc deux espaces trouvés à la suite), tu reboucles sans continuer les instructions. Sinon, tu ré-alloues une case-mémoire supplémentaire à ta chaîne et tu ajoutes le pointeur sur caractère. Et tu ajoutes à nouveau un caractère de fin de chaîne à la fin puisqu'il a été remplacé par ton nouveau caractère. Et une fois que c'est fini, tu renvoies simplement l'adresse de la chaîne allouée dynamiquement et tu n'oublie pas de libérer la mémoire dans la fonction principale.

                J'espère que j'ai été suffisamment clair pour toi, j'ai essayé d'expliquer au mieux.


                Désolé je n'ai pas compris le principe de supression de l'espace 

                mais voici ma nouvelle correction

                #include<stdio.h>
                #include<stdlib.h>
                #include<ctype.h>
                #include<string.h>
                #include<conio.h>
                
                //prototypes
                
                void strspace(char *chaine);
                
                //main
                
                
                int main(void)
                {
                	char phrase[1000];
                	int i, j;
                	puts(" \n \n Donner une phrase  \n \n  ");
                	gets(phrase);
                	strspace(phrase);
                		getch();
                }
                
                void strspace(char * chaine)
                {
                	//declaration
                
                
                	int longueur = strlen(chaine) - 1;
                	char *p1=chaine, *p2;
                	int i, j;
                
                	p1 = chaine;
                
                	
                
                
                
                	for (i = 0; *p1; i++)
                	{
                		for (j = i + 1; *p1;j++)
                		{
                
                			if (isspace(*(p1+i) && isspace(*(p1+j))))
                			{
                				free(p1+i);
                			}
                		}
                	}
                	printf(" \n %s    \n ", p1);
                }
                



                • Partager sur Facebook
                • Partager sur Twitter
                Anonyme
                  31 juillet 2016 à 11:26:04

                  Utiliser deux boucles for imbriquées pour pouvoir naviguer avec deux pointeurs qui se suivent n'est pas une approche intuitive du problème à mon avis.

                  Mon approche est la suivante :

                  char *chaine = {'A','B','C',' ',' ',' ',' ',' ','E','F','G','\0'};
                                   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑
                                   0   1   2   3   4   5   6   7   8   9   10  11
                  
                  Création d'une nouvelle chaîne de taille 1 pour le \0
                  
                  Tant que le parcours de la chaîne n'est pas fini et que le caractère n'est pas un \0
                  
                      Si l'indice actuel et l'indice suivant sont des espaces
                  
                          Continuer la boucle comme si de rien était
                  
                      Sinon
                  
                          Augmenter de 1 l'espace de la nouvelle chaîne
                  
                          Ajouter le caractère actuel
                  
                          Ajouter à l'indice ( actuel + 1 ) le \0

                  Bien sûr, dans ton code-source, il y aura plusieurs vérifications, sûrement des variables en plus. Comme noté plus haut, ce n'est pas la meilleure des approches. Cependant, cela devrait être suffisamment simple à comprendre pour toi, sous réserve que tu ai bien compris le chapitre sur les chaînes de caractères, les tableaux et l'allocation dynamique.

                  • Partager sur Facebook
                  • Partager sur Twitter
                    31 juillet 2016 à 20:29:45

                    AminNairi a écrit:

                    Je sais que le C n'est pas un langage orienté objet, mais dans d'autre langages de ce type qui utilisent une méthode agissant sur des chaînes de caractères, en principe on ne modifie jamais cette chaîne, on en renvoie toujours une autre.

                    En C, on ne fait généralement pas ainsi, car:

                    * la gestion de la mémoire est difficile
                    * ça crée une dépendance à malloc, alors que l'appelant peut utiliser une autre solution d'allocation mémoire

                    On fait une fonction qui modifie en place, cette dernière pouvant être appelée par d'autres fonctions qui font l'allocation.

                    -
                    Edité par Marc Mongenet 1 août 2016 à 10:01:01

                    • Partager sur Facebook
                    • Partager sur Twitter
                      31 juillet 2016 à 23:17:31

                      Bonjour,

                      ton nouveau code est bien loin de la solution (une double boucle pourquoi? un test avec des parenthèses mal placées. un appel de fonction 'au hasard').

                      Il faut suivre le cheminement indiqué par AminNairi.
                      Et comme ta fonction suppose une une unique chaîne en entrée/sortie, il faut recopier la nouvelle dans l'ancienne à la fin.

                      Sinon, on peut aussi modifier directement la chaîne initiale et c'est même un peu plus simple.

                      On a 2 indices (iread et iwrite) qui commencent à 0
                      Tant que le caractère[iread] n'est pas un \0, incrémentant toujours iread
                          Si caractère[iread] et caractère[iread+1] sont des espaces
                              Continuer la boucle comme si de rien était
                          Sinon
                              caractère[iwrite] = caractère[iread]
                              incrémenter iwrite qui est aussi le compteur des caractères écrits
                      mettre un \0 dans caractère[iwrite] pour fermer la chaîne

                      -
                      Edité par Dalfab 31 juillet 2016 à 23:18:21

                      • Partager sur Facebook
                      • Partager sur Twitter

                      En recherche d'emploi.

                      Anonyme
                        1 août 2016 à 4:00:34

                        void strspace(char * chaine)
                        {
                        	//declaration
                        
                        	int i=0, j=0;
                        
                        
                        	while (chaine[i] != '\0')
                        	{
                        	
                        		chaine[j] = chaine[i];
                        		if ((chaine[i] != ' ') && (chaine[i + 1]) != ' ')
                        		{
                        			
                        			j++;
                        		}
                        i++	;
                        }
                        chaine[j]='\0';	
                        	
                        	printf(" \n   %s    \n ",chaine);
                        }
                        le résultat d'affichage est faux signifie qu'il y'a une erreur dans mon code

                        -
                        Edité par Anonyme 1 août 2016 à 4:08:22

                        • Partager sur Facebook
                        • Partager sur Twitter
                          1 août 2016 à 12:53:00

                          Ca ressemble à un exercice que j'ai eu à faire à l'école dont je te poste le code ici,

                          Par contre, la fonction se contente d'afficher la phrase sans les espaces superflus (pas d'espace en début de ligne, pas plus d'un espace pour séparer deux mots, pas d'espace à la fin d'une phrase) sans jamais la modifier, mais à toi de t'en inspirer.

                          #include <stdio.h>
                          #include <stdlib.h>
                          #include <unistd.h>
                          
                          void    ft_expand_str(const char *str)
                          {
                              int space_back;
                              
                              space_back = 0;
                              if (str)
                              {
                                  while (*str)
                                  {
                                      while (*str && *str != ' ' && *str != '\t')
                                      {
                                          write(1, str, 1);
                                          space_back = 1;
                                          str++;
                                      }
                                      while (*str == ' ' || *str == '\t')
                                      {
                                          str++;
                                          if ((*str) && (*str != ' ') && (*str != '\t') && (space_back == 1))
                                          {
                                              write(1, " ", 1);
                                              space_back = 0;
                                          }
                                      }
                                  }
                              }
                          }
                          
                          int main(int argc, const char * argv[])
                          {
                              char str[1024];
                              printf("Rentrez une phrase\n");
                              fgets(str, sizeof(str), stdin);
                              ft_expand_str(str);
                              
                              return (0);
                          }



                          • Partager sur Facebook
                          • Partager sur Twitter

                          Mehdi - Mentor iOS

                            1 août 2016 à 16:02:23

                            @FaresBenslama

                            Tu as changé la chronologie de mon algorithme (tu commences par écraser une valeur que tu testes ensuite!)
                            Et pour inverser un test, le && doit devenir un || 

                            Essaye :

                             while ( chaine[i] != '\0' )
                             {
                                if ( !isspace(chaine[i]) || !isspace(chaine[i + 1]) )
                                {
                                   chaine[j++] = chaine[i];
                                }
                                i++;
                             }
                             chaine[j] = '\0';

                            correctif, erreur de ma part la copie avant est sans danger, il reste l'erreur lors du test

                            -
                            Edité par Dalfab 1 août 2016 à 16:09:19

                            • Partager sur Facebook
                            • Partager sur Twitter

                            En recherche d'emploi.

                              1 août 2016 à 17:38:39

                              #include <stdio.h>
                              
                              
                              void strspace(char str[])
                              {
                              	int read, write = 0;
                              
                              	while(str[read] != '\0')
                              	{
                              		if(str[read] == ' ' && (str[read + 1] == ' ' || str[read + 1] == '.'));
                              		else
                              		{
                              			str[write] = str[read];
                              			write++;
                              		}
                              
                              		read++;
                              	}
                              
                              	str[write] = '\0';
                              }
                              
                              int main(void)
                              {
                              	char str[] = "Je suis une  phrase       avec   des         espaces en      trop     .    ";
                              	strspace(str);
                              	printf("%s\n", str);
                              	return 0;
                              }
                              

                              Je te conseille de revoir le cours de programmation en Langage C pour être sûr que tu ais de bonnes base car là, il n'y a vraiment rien de compliqué depuis que Dalfab t'as donné le pseudo-code. Ce n'est plus que de la translation !

                              -
                              Edité par Xenoliss 1 août 2016 à 17:39:45

                              • Partager sur Facebook
                              • Partager sur Twitter
                              Anonyme
                                1 août 2016 à 21:37:35

                                Merci beaucoup les gens vous avez vraiment m'aider

                                mon point faible dans le language c est les chaines de caractères et les pointeurs sur char ;

                                • Partager sur Facebook
                                • Partager sur Twitter
                                Anonyme
                                  1 août 2016 à 21:54:46

                                  FaresBenslama a écrit:

                                  Merci beaucoup les gens vous avez vraiment m'aider

                                  mon point faible dans le language c est les chaines de caractères et les pointeurs sur char ;

                                  Cherches une dizaine d'exercices sur les chaînes de caractères, fais les tous en entiers et ne regardes la correction à la fin. L'étape de comparaison est très importante. Ne jettes jamais tes brouillons, si tu as des erreurs, mets en commentaires tes erreurs et corriges. Quand tu repasseras sur ton code, il faut que tu te repose les même questions et si tu comprends tes erreurs, c'est que tu es prêt.
                                   

                                  Refais pareil pour les tableaux. Et bien sûr pour les pointeurs. N'avance pas avant d'avoir compris. Ne te fie pas au compteur de temps du cours. Ce n'est pas parce que c'est mis "Facile" qu'il faut absolument terminer le cours avant le début des vacances. Moi ça m'a prit une semaine à comprendre réellement ce qu'est un pointeur alors que les autres chapitres ne m'ont jamais pris plus d'une demi-journée. Chacun ses faiblesses et ses forces.

                                  Et il n'y a pas que le site OCR, compare un peu avec d'autres, lit la documentation en anglais si tu es courageux.

                                  Bonnes vacances... :lol:

                                  • Partager sur Facebook
                                  • Partager sur Twitter

                                  Les espaces superflues

                                  × 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