Salut,
Je voudrais savoir si il y une fonction dans la bibliothèque standard du C, une fonction qui permet la suppression d'un caractère quelconque dans une chaine de caractères.
Salut,
Je voudrais savoir si il y une fonction dans la bibliothèque standard du C, une fonction qui permet la suppression d'un caractère quelconque dans une chaine de caractères.
C'est en principe facile à programmer. Il suffit de décaler tous les caractères qui suivent le caractère à effacer d'une position. Ca se fait facilement avec memmove().
Thierry
Bonjour,
S'agit-il de supprimer un caractère quelconque dans une chaine ou de l'ensemble d'un caractère quelconque dans une chaine ?Je voudrais savoir si il y une fonction dans la bibliothèque standard du C, une fonction qui permet la suppression d'un caractère quelconque dans une chaine de caractères.
par exemple dans la chaine "une chaine codée en machine", supprimer la première occurrence du "c" ou bien toutes les occurrences de "c" ?
Dans mon cas il s'agit de supprimer toutes les occurences de"c"
Voila mon programme en entier.
Le problème est que la fonction supprime doit être appelé 2 fois pour que cela fonctionne correctement.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 #include <stdio.h> #include <stdlib.h> #define VIDE -1 /* le type des grilles de Sudoku */ typedef int Grille[9][9]; void initialiseGrille(Grille G); int lireGrille(Grille G); void afficheGrille(Grille G); void supprime(char *texte, char x); Grille G; char tab[172]; int main() { lireGrille(G); afficheGrille(G); return 0; } void initialiseGrille(Grille G) { int ligne, colonne; for(ligne=0; ligne<9; ligne++) { for(colonne=0; colonne<9; colonne++) G[ligne][colonne]=VIDE; } } int lireGrille(Grille G) { int ligne,colonne,i=0,j=0; FILE* fichier=NULL; fichier = fopen ("grille1.txt", "r" ); if(fichier==NULL) { printf("Impossible d'ouvrir le fichier grille1.txt\n"); return 0; } while (!feof(fichier)) { tab[i]=fgetc(fichier); i++; } supprime(tab, '|'); supprime(tab, '|'); //Prend le tableau tab et le met en forme pour que les valeur entre entre dans le tableau G for(ligne=0; ligne<9; ligne++) { for(colonne=0; colonne<9; colonne++) { G[ligne][colonne]=tab[j]; j++; } j+8; } fclose(fichier); return 1; } //Affiche les grille de sudoku en matraice 3*3 void afficheGrille(Grille G) { static char r[]="+---+---+---+"; int ligne, colonne; for(ligne=0; ligne<9; ligne++) { if(ligne==0 || ligne ==3 || ligne==6) printf("%s\n",r); printf("|"); for(colonne=0; colonne<9; colonne++) { if(colonne==3 || colonne==6) printf("|"); //if(G[ligne][colonne]==-1) printf(" "); printf("%c", G[ligne][colonne]); if(colonne==8) printf("|\n"); } } printf("%s\n",r); } void supprime(char *texte, char x) // supprime x dans la chaine texte { int p ,i; for(i=0;texte[i] != '\0';i++) { if (texte[i] == x) // on a trouve { for(p=i; texte[p]!=0; p++) texte[p]=texte[p+1]; } } }
Tu ne gères pas le cas où plusieurs occurrences du caractère à supprimer se suivent, ceci réglera le problème :
mais tu pourrais le faire en un seul passage ( une seule boucle ).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 void supprime(char *texte, char x) { int p ,i; for(i=0;texte[i] != '\0';i++) { if (texte[i] == x) { for(p=i; texte[p]!=0; p++) texte[p]=texte[p+1]; i--; } } }
Bonjour,
C'est pas facile de reprendre tout le code. Pour la suppression de toutes les occurences d'un caractère presque quelconque dans une chaine, je propose :
Il est évident que l'on peut toujours en mettre moins dans ce qui était défini comme plus. Mais l'inverse n'est pas aussi facile ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 char * str_remove_all_char( char * z , short c ) { size_t sp = 0 ; size_t ep ; size_t i ; size_t j = 0 ; if( z != NULL ) { ep = strlen(z) ; ep -=1 ; while( z[sp] == c && sp <= ep ) sp++ ; while( z[ep] == c && ep > 0 ) ep-- ; if( sp <= ep ) { i = sp ; while ( i <= ep ) z[j++] = z[i++] ; z[j]= '\0' ; } else strcpy( z , "" ) ; } return z ; }
Bonjour,
C'est compliqué comme solutions.
N'oubliez pas que le C possède quelque chose de puissant : Les Pointeurs.
Soit Chaine la chaine a traiter,
On initialise au début de celle ci 2 pointeurs
1 de lecture qui va parcourir la chaine.
1 d'écriture qui recevra la valeur de celui de lecture et ne sera incrémenté que si la valeur lue est différente de celle a supprimer.
Bonne continuation.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 char *SupprimeCarChaine(char *Chaine,char Car) { char *Pe; // Pointeur d'écriture char *Pl; // Pointeur de lecture if(Chaine!=NULL) { Pe=Chaine; // Initialise les pointeurs en début de chaine Pl=Chaine; while(*Pe) // Parcours toute la chaine (Arrêt sur 0 terminal) { if(*Pl!=Car) // Si car lu différent de celui a supprimer, { *Pe=*Pl; // on le copie et incrément le pointeur d'écriture Pe++; } Pl++; // incrément le pointeur de lecture } *Pl=0; // Termine la chaine } return(Chaine); }
Ne passe pas le 2eme test...
Il est inutile de définir un paramètre de type short.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 #include <string.h> char *str_remove_all_char (char *z, short c) { size_t sp = 0; size_t ep; size_t i; size_t j = 0; if (z != NULL) { ep = strlen (z); ep -= 1; while (z[sp] == c && sp <= ep) sp++; while (z[ep] == c && ep > 0) ep--; if (sp <= ep) { i = sp; while (i <= ep) z[j++] = z[i++]; z[j] = '\0'; } else strcpy (z, ""); } return z; } #ifdef TEST #include <assert.h> #include <stdio.h> int main (void) { char s[] = "Hello world"; assert (strcmp (str_remove_all_char (s, 'x'), "Hello world") == 0); assert (strcmp (str_remove_all_char (s, 'o'), "Hell wrld") == 0); puts ("P A S S E D"); return 0; } #endif
1 - il est convertit en int
2 - la conversion génère du code machine supplémentaire
3 - il n'y a pas de paramètres de type char ou short dans la bibliothèque standard du C.
4 - de plus, ici, le paramètre concerne une constante caractère, qui est de type int en C.
Est-il nécessaire de faire plus compliqué que ça ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 #include <string.h> char *str_remove_all_char (char *z, int c) { if (z != NULL) { char const *pr = z; /* pointeur de lecture */ char *pw = z; /* pointeur ecriture */ int rc; /* caractere lu */ while ((rc = *pr) != 0) { if (rc != c) { *pw = *pr; pw++; } pr++; } *pw = 0; } return z; } #ifdef TEST #include <assert.h> #include <stdio.h> int main (void) { char s[] = "Hello world"; assert (str_remove_all_char (NULL, 'x') == NULL); assert (strcmp (str_remove_all_char (s, 0), "Hello world") == 0); assert (strcmp (str_remove_all_char (s, 'x'), "Hello world") == 0); assert (strcmp (str_remove_all_char (s, 'o'), "Hell wrld") == 0); assert (strcmp (str_remove_all_char (s, 'l'), "He wrd") == 0); assert (strcmp (str_remove_all_char (s, 'H'), "e wrd") == 0); assert (strcmp (str_remove_all_char (s, 'e'), " wrd") == 0); assert (strcmp (str_remove_all_char (s, 'd'), " wr") == 0); assert (strcmp (str_remove_all_char (s, ' '), "wr") == 0); assert (strcmp (str_remove_all_char (s, 'w'), "r") == 0); assert (strcmp (str_remove_all_char (s, 'r'), "") == 0); assert (strcmp (str_remove_all_char (s, 'y'), "") == 0); assert (strcmp (str_remove_all_char (s, 0), "") == 0); puts ("P A S S E D"); return 0; } #endif
Bonjour,
En fait ma proposition ne résoud pas le problème en travaillant uniquement sur les extrémités de la chaîne.
Pour ce qui est du codage du caractère en int pourquoi pas de toute façon un caractère est compris entre 0 et 255. Un octet pourrait suffire.
Bonjour,
Bien vu et désolé pour la boulette, bien que le lecteur ait rectifié de lui même, je vous transmet la version corrigée.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 char *SupprimeCarChaine(char *Chaine,char Car) { char *Pe; // Pointeur d'écriture char *Pl; // Pointeur de lecture if(Chaine!=NULL) { Pe=Chaine; // Initialise les pointeurs en début de chaine Pl=Chaine; while(*Pl) // Parcours toute la chaine (Arrêt sur 0 terminal) { if(*Pl!=Car) // Si car lu différent de celui a supprimer, { *Pe=*Pl; // on le copie et incrément le pointeur d'écriture Pe++; } Pl++; // incrément le pointeur de lecture } *Pe=0; // Termine la chaine } return(Chaine); }
Ce qui est très exactement http://www.developpez.net/forums/m3746706-12/ ...
pour le 1, je ne vois pas pourquoi, la fonction n'est pas variadic et le prototype est présent, dans le listing assembleur c'est bien un short qui est passé (2 bytes).
De plus, je préfère limité au maximum la plage de valeur de mes variables, et je trouve horrible cette manie qu'on les programmeurs C de tout déclarer en int. C'est une mauvaise pratique de programmation. Pour moi c'est au même niveau que limiter la portée des variables. Certes, en l'occurence, ici le bon type était effectivement int.
plus la plage est restreinte, moins de vérification il y a à faire. On voit encore trop souvent dans les codes avec des noms de variables avec les mots size ou length où le type est signé???? depuis quand la longueur d'une chaîne peut être négative? c'est un manque de cohérence flagrant.
Et quel est le rapport avec le fait d'utiliser short plutôt que int et de limiter au maximum la plage de valeur possible ?
Utiliser du signé ou du non signé selon le besoin est une chose, limiter la plage possible en est une autre.
En toute rigueur, le type "naturel" pour une taille ou une longueur est size_t (qui est d'ailleurs non signé). Maintenant il faut parfois composer avec d'autres contraintes (prototype de fonction existante, boucle décroissante, gestion d'erreur) et utiliser d'autres types, signés ou non.
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager