IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Suppression de caractères dans une chaine


Sujet :

C

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2019
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2019
    Messages : 3
    Par défaut Suppression de caractères dans une chaine
    Bonjour,

    J’ai une question concernant la suppression de caractères dans une chaîne de caractères.

    J’essaie de trouver le code qui répond à la question suivante :
    supprimer toutes les apparitions d’une sous chaîne de caractères qui se trouve dans une chaîne de caractères.

    Cette sous chaîne doit être précédé d’un caractère "particulier" pour être supprimée.

    Et à la fin du programme, on doit indiquer le nombre de suppressions.

    J'ai imaginé que chaine originale était "Taxattatxattaxat" et qu'on devait supprimer les "at" précédé par des "x"

    Pour ce qui est de la fonction main , j’ai fait cela :
    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
     
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #define N 128
     
    int main(int argc, char * argv []) {
     
        int nmbr = 0;
        char Sousch [2];
        char ch1[N];
     
        printf("Entrez la chaine originale ");
        gets(ch1);
        printf(" Entrez les deux caractères a supprimer");
        scanf("%c,%c",&Sousch[0],&Sousch[1]);
        nmbr = modifchaine(17 , ch1, Sousch);
        if (nmbr>0)
        {
            printf("nombre de suppressions : %d ", nmbr);
        }
        else
        { printf("Aucune suppression de caractères dans la chaine originale ");
        }
        system ("Pause");
     
        return 0;
    }

    Par contre pour la fonction qui me permettra de modifier la chaîne en fonction des conditions, j’ai eu du mal à la conclure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    int modifchaine(int n, char ch1[],char Sousch [2] );
     
    int i, j , nmbr = 0;
    char ChaineModifié[n];
     
    while  (i<n)
    {
        ChaineModifié [j] = ch1[i] // mettre le caractère dans la chaine modifie
        j++;
        if (ch1 [i]  == 'x')
            && (ch1 [i+1] == Sousch[0])
            && (ch1 [i+2] == Sousch[1] )
    Est-ce que quelqu’un peut m’expliquer comment conclure cette fonction s’il vous plaît ! Merci d'avance!

  2. #2
    Membre Expert Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    784
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 784
    Par défaut
    Hello,

    Ton code se base sur le fait que la chaine à supprimer n'est longue que de 2 caractères. Quid si la chaine en fait 32 ?

    Le plus simple: utiliser strchr() pour repérer le caractère sentinelle, et strncmp() ensuite pour s'assurer que la chaine à supprimer suit bien le caractère sentinelle.

    A répéter tant que l'on trouve un caractère sentinelle.

  3. #3
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2019
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2019
    Messages : 3
    Par défaut
    Salut,

    Oui la sous chaîne doit être de 2 caractères maximum, et je vais essayer ce que tu m'as conseillé. Merci !

  4. #4
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    Pourquoi faire du premier caractère un cas particulier ? Si 'x' est le premier caractère et "in" la chaîne à remplacer par "out" alors l'exercice se résume à remplacer les occurrences de "xin" par "xout".

  5. #5
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 833
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par ilyas2812 Voir le message
    J'ai imaginé que chaine originale était "Taxattatxattaxat" et qu'on devait supprimer les "at" précédé par des "x"
    Il faut faire attention avec le terme "suppression". Parce que si à notre niveau on parle de suppression (tout comme je peux effacer un mot dans cette phrase et tout se décale proprement tout seul), du point de vue du C il faut tout faire soi-même.
    Donc si ta chaine contient "Taxattatxattaxat", supprimer par exemple le premier "xat" se traduira alors par un décalage de tout ce qui suit jusqu'à la fin de la chaine. Et la chaine devient alors "Tatatxattaxat". Et on repart alors de cette chaine (et du même emplacement) pour continuer et refaire alors le travail de décalage si on retrouve une nouvelle occurrence. Bref un algo efficace mais à la base assez lourd.

    Ensuite évidemment on peut tenter d'optimiser. En établissant par exemple toutes les positions de "xat" puis en ne décalant que ce qui doit l'être et en calculant soigneusement la position finale de tout ce qui est à décaler.

    Citation Envoyé par ilyas2812 Voir le message
    Est-ce que quelqu’un peut m’expliquer comment conclure cette fonction s’il vous plaît !
    Personnellement j'écrirais une fonction dédiée au décalage d'une chaine de n caractères vers la gauche. Ensuite, une fois ladite fonction testée, suffirait d'appliquer la méthode d'edgarjacobs enrichie de la remarque de Matt_Houston (trouver la première occurence de "xat" => strstr() plus direct que strchr() + strncmp()) et appliquer ladite fonction. Et recommencer jusqu'à ce que tout ait été traité.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Pour un débutant, il est peut-être plus simple de travailler sur 2 chaînes. On copie dans la seconde les séquences que l'on souhaite conserver; quand une chaîne doit être remplacée, c'est la chaîne de remplacement qui va s'ajouter à la copie.
    C'est qu'en C, on aime bien faire tout sur place c'est plus rapide, moins consommateur de mémoire, mais un chouia plus compliqué.

  7. #7
    Membre Expert Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    784
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 784
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    ....plus direct que strchr() + strncmp())
    Les deux fonctions, c'est parce que j'avais imaginé un prototype du style char *fct_name(char *src,char sentinel,char *str2suppress); Cela évitait d'allouer une variable pour concaténer sentinel et str2suppress

  8. #8
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2019
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2019
    Messages : 3
    Par défaut j'ai presque reussi
    Salut,

    Tout d'abord merci à tous pour vos réponses ! Ensuite je précise que je viens seulement de débuter en c et que l'exercice que je vous ai présenté est un exercice d'un examen blanc de première année de bachelier ! Et donc je ne me maitrise pas trop les pointeurs pour l'instant. Ni les fonctions de la bibliothèque string

    Et concernant l'exercice, je l'ai presque fini, il tourne sur Xcode mais ne me donne pas ce que je veux !

    Voici le code . ! :

    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #define N 128
     
    void initSousChaine( char [] );
    void supprimeSousChaineAvecIndices(char [], char[]);
     
    int main(int argc, char *argv[])
    {
        char ch1 [N];
     
        printf("Entrez la chaine originale contenant maximum %d caracteres.\n", N - 1);
        gets(ch1);
     
        char sousChaine [3];
        initSousChaine(sousChaine);
     
     
        supprimeSousChaineAvecIndices(ch1, sousChaine);
     
     
        system("PAUSE");
        return 0;
    }
     
    void initSousChaine( char s[])
    {
        do
        {
            printf("Entrez une chaine a supprimer. \nAttention, chaine de 2 caracteres!\n");
            gets(s);
        }while(strlen(s) != 2);
    }
     
     
     
    void supprimeSousChaineAvecIndices(char s[], char ssch[])
    {
        int compteurDeSuppression = 0, indiceLecture = 0, indiceEcriture = 0;
     
        while( indiceLecture <= strlen(s))
        {
            printf("\nIndex actuel : %d\n", indiceLecture);
            if( (s[indiceLecture] == 'x') && (s[indiceLecture+1] == ssch[0]) &&
               (s[indiceLecture+2] == ssch[1]))
            {
                // La sous chaine est bien dedans
                printf("On a trouve, on supprime la sous chaine.\n");
                indiceLecture = indiceLecture +2;
                compteurDeSuppression++;
            }
            else
            {
                printf("On garde %c dans la chaine.\n", s[indiceLecture]);
                s[indiceEcriture] = s[indiceLecture];
                indiceEcriture++;
                indiceLecture++;
            }
        }
        printf("Nombre de remplacements : %d\n", compteurDeSuppression);
        printf("Chaine modifiee : ");
        puts(s);
    }

    et voici l'execution du programme !

    Nom : Capture d’écran 2019-02-01 à 18.54.12.png
Affichages : 2769
Taille : 151,0 Ko
    Nom : Capture d’écran 2019-02-01 à 18.54.22.png
Affichages : 1791
Taille : 21,8 Ko


    En fait je ne comprends pas pourquoi on garde le "a" de "la", la chaîne modifié devrait être "tratla"

    Merci

  9. #9
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 833
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par ilyas2812 Voir le message
    Tout d'abord merci à tous pour vos réponses !
    Alors pourquoi tu ne les utilises pas ? edgarjacobs te parle de strncmp() et moi de strstr(). Alors ok, cette dernière te retourne un pointeur donc admettons que tu ne sois pas à l'aise (ce qui est étonnant pour un truc que tu vas présenter au bac et dans lequel les pointeurs sont la base et les fondements des connaissances à acquérir mais admettons). Mais strncmp(), lui, il ne te retourne pas un pointeur. Et lui, il permet de vérifier en un coup si une partie d'une chaine correspond à un motif. Bref un seul appel remplace ton if( (s[indiceLecture] == 'x') && (s[indiceLecture+1] == ssch[0]) && (s[indiceLecture+2] == ssch[1])) de chiottes qui montre, en plus, que tu ne connais même pas les priorités élémentaires (le "==" sur le "&&" qui fait que les parenthèses sont inutiles).

    Citation Envoyé par ilyas2812 Voir le message
    Ni les fonctions de la bibliothèque string
    Et alors ? Ca t'empêche de lire la doc ? Et de faire un test rapide ?

    Citation Envoyé par ilyas2812 Voir le message
    Et concernant l'exercice, je l'ai presque fini, il tourne sur Xcode mais ne me donne pas ce que je veux !
    Ben oui. Peut-être parce que tu cherches "xat" (3 octets) mais que ton indice de lecture n'augmente que de 2.
    Sinon pourquoi une première saisie dans le main() et une autre séparée dans une fonction qui n'est utilisée qu'une fois ? Je sais pas moi, une saisie ça reste une saisie. Si tu as pensé à faire une fonction pour la sous-chaine, tu aurais pu alors l'adapter pour pouvoir l'utiliser pour les deux !!!

    Par exemple ton programme corrigé de l'erreur et réécrit en utilisant des outils adaptés
    Code c : 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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define N 128
     
    void saisieChaine(char[], char[], size_t, char);
    size_t supprimeSousChaineAvecIndices(char [], char[]);
     
    int main(int argc, char *argv[]) {
    	char ch1[N];
    	char sousChaine[3];
    	size_t nb;
     
    	saisieChaine("Entrez la chaine originale", ch1, N, 0);
    	saisieChaine("Entrez la chaine à supprimer", sousChaine, 2, 1);
     
    	nb=supprimeSousChaineAvecIndices(ch1, sousChaine);
     
    	printf("Nombre de remplacements : %lu\n", nb);
    	printf("Chaine modifiee : [%s]\n", ch1);
     
    	system("PAUSE");
    	return 0;
    }
     
    void saisieChaine(char prompt[], char s[], size_t size, char flag_fixe) {
    	while (1) {
    		printf("%s\n", prompt);
    		printf("Attention, %s %lu caractères\n", flag_fixe ?"obligatoirement" :"pas plus de", size);
     
    		fgets(s, size+1, stdin);
    		char *pt;
    		if ((pt=strchr(s, '\n')) != NULL) *pt='\0';
    		else {
    			int c;
    			while ((c=fgetc(stdin)) != '\n' && c != EOF);
    		}
    		if (flag_fixe == 0 || strlen(s) == size) break;
    		printf("Saisie incorrecte - Recommencez !!!\n");
    	}
    }
     
    size_t supprimeSousChaineAvecIndices(char s[], char ssch[]) {
    	size_t compteurDeSuppression = 0, indiceLecture = 0, indiceEcriture = 0;
    	char motif[4];
    	sprintf(motif, "x%s", ssch);
     
    	while (1) {
    		printf("\nIndex actuel : %lu, %lu\n", indiceLecture, indiceEcriture);
    		if (strncmp(&s[indiceLecture], motif, strlen(motif)) == 0) {
    			// La sous chaine est bien dedans
    			printf("On a trouve, on supprime la sous chaine.\n");
    			indiceLecture = indiceLecture + strlen(motif);
    			compteurDeSuppression++;
    		}
    		else {
    			printf("On garde %c dans la chaine.\n", s[indiceLecture]);
    			s[indiceEcriture] = s[indiceLecture];
    			if (s[indiceLecture] == '\0') break;
    			indiceEcriture++;
    			indiceLecture++;
    		}
    	}
     
    	return compteurDeSuppression;
    }
    C'est pas plus élégant ??? Surtout en supprimant le strlen(s) appelé à chaque itération et en ne mettant le test de sortie que dans le cas où on a copié le caractère (car il n'y a que là que ça peut arriver) ce qui élimine des opérations inutiles. Et en dissociant "travail utile" (exécuté dans la fonction qui supprime la sous-chaine) de "affichage du résultat" (qui, lui, se fait dans la fonction qui demande ce travail). Cela permet ensuite d'entrer dans le monde de la programmation professionnelle qui sépare le modèle (stockage des données), la vue (saisie/affichage) et le controleur (calcul des données) => programmation MVC

    Et dernière chose, on n'utilise pas gets() (normalement ton compilo doit te le dire) mais fgets() qui permet de limiter la saisie. Sauf qu'il enregistre aussi le '\n' symbolisant le <return> que tu tapes pour valider. D'où la petite manip interne pour le supprimer s'il a été lu ou pour le purger du clavier s'il y est encore.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

Discussions similaires

  1. [XL-2010] Suppression de caractères dans une chaine
    Par BLZ007 dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 26/07/2014, 19h53
  2. suppression caractère dans une chaine
    Par courson dans le forum Débuter
    Réponses: 1
    Dernier message: 03/04/2009, 20h36
  3. Suppression de caractères dans une chaine
    Par mouhammed dans le forum C
    Réponses: 19
    Dernier message: 01/11/2008, 17h34
  4. Suppression de certains caractères dans une chaine
    Par Tchupacabra dans le forum Langage
    Réponses: 2
    Dernier message: 05/12/2007, 12h08
  5. Réponses: 8
    Dernier message: 08/06/2004, 01h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo