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
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 :
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.
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.
First solve the problem. Then, write the code. ~ John Johnson
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);
}
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.
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.
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
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.
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 ||
#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 !
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...
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.
En recherche d'emploi.
Mehdi - Mentor iOS
En recherche d'emploi.