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 :

Recherche de sous-chaine


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Femme Profil pro
    Enseignant
    Inscrit en
    Octobre 2014
    Messages
    135
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2014
    Messages : 135
    Par défaut Recherche de sous-chaine
    Bonjour tous le monde,

    Je viens de lire le cour qui existe sur la plateforme et j'ai installé codeBlocks pour développer et apprendre comment fonctionne le langage C.

    Mais malheureusement je me suis bloqué dans cette petite application :

    Écrire un programme C permettant de vérifier l'existence d'une sous-chaîne dans une chaîne et renvoyer sa position ( sans utiliser strstr de C).

    Voici mon essai : est ce qu'il est juste ou faux ?

    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
    #include <stdio.h>
    #include <string.h>
    void main()
    {
       char ch1[20],ch2[20];
        int i;
     
        printf("Donner une chaîne de carcactère ");
        scanf("%s",&ch1);
        printf("Donner la sous chaîne que vous cherchez");
        scanf("%s",&ch2);
       for(i=0;i<strlen(ch1);i++)
       {
           if(ch1[i]=ch2[i])
           {
               printf("La chaine",ch2,"se trouve à la position",i);
           }
       }
    }

  2. #2
    Membre chevronné
    Inscrit en
    Décembre 2010
    Messages
    290
    Détails du profil
    Informations forums :
    Inscription : Décembre 2010
    Messages : 290
    Par défaut
    Bonjour !

    Voici mon essai : est ce qu'il est juste ou faux ?
    Une façon de le savoir c'est de l'essayer.

    Il se trouve qu'il est faux.
    Il y a deux raisons principales à ça:
    1. En C, on compare deux valeurs en utilisant l'opérateur "==", comme ceci :
    Et non pas comme cela :
    Ce que tu as fait là c'est une affectation: tu as dit "la case numéro i du tableau ch1 va contenir la valeur de la case i du tableau ch2".

    2. Tu ne compares qu'un seul caractère. Or, ton énoncé dit explicitement qu'il faut trouver une chaîne de caractères entière.
    Ce problème est un peu plus complexe à résoudre que le premier. Tu as deux tableaux de caractères, chacun terminé par un zéro, et il faut que tu trouves le premier dans le deuxième. Comment tu ferais ça ? Ne te préoccupe pas tout de suite du langage C, demande toi juste quelle serait la suite des opérations à accomplir pour faire cette recherche. Une fois que tu as ce plan, tu pourra l'implémenter en C facilement (et on t'aidera à le corriger).

    Ton programme a aussi un autre problème, plus subtil.
    scanf() va lire des caractères jusqu'à rencontrer une espace, et les placer dans les tableaux ch1 et ch2.
    Si l'utilisateur rentre un très long mot (comme supercalifragilistickexpialadocious), scanf() va dépasser la limite des 20 caractères de ton tableau, et ça va causer soit un crash, soit un fonctionnement incorrect.
    La FAQ C de developpez.net contient une entrée à ce sujet, je te laisse la lire ici: http://c.developpez.com/faq/?page=Ge...iere-securisee.

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 831
    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 831
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Un détail que phi1981 n'a pas relevé: Le nom de ta chaine ch1 étant déjà une adresse, pas besoin de mettre "&" dans le scanf().

    Et la fonction main() est de type int, pas void.

    Perso je pense toutefois que tu ne devrais pas aborder cet exercice sans avoir déjà bien étudié
    • les tableaux
    • les chaines
    • les pointeurs

    Et surtout les liens et analogies qui existent entre chacun de ces éléments...
    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]

  4. #4
    Membre chevronné
    Homme Profil pro
    très occupé
    Inscrit en
    Juillet 2014
    Messages
    137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : très occupé

    Informations forums :
    Inscription : Juillet 2014
    Messages : 137
    Par défaut
    Bonjour alias2015_29,

    autres problèmes :

    - avec scanf("%s", ... la lecture va s'arrêter au premier caractère "blanc" rencontré, par exemple un espace
    - ainsi, par exemple, si au premier scanf tu saisis "un deux trois quatre", le premier scanf ne va capturer que "un" et laisser " deux trois quatre" dans le flux d'entrée (stdin)
    - lorsque le second scanf("%s", ... arrive, il n'arrête pas l'exécution du programme, car stdin contient déjà des données, et le second scanf prend "deux" dans stdin, et laisse " trois quatre"

    Je ne pense pas que cela soit le comportement souhaité.

    Tu peux utiliser scanf pour qu'il ne s'arrête pas au premier espace venu et en même temps pour qu'il limite la capture de caractères à un maximum (ton maximum est 19, car il faut un caractère '\0' terminal pour finir la chaîne), en utilisant un spécificateur de longueur, et en demandant à scanf d'accepter tous caractères sauf le retour à la ligne ainsi : scanf("%19[^\n]", ....

    Même comme cela, il est possible que la personne tape plus de 19 caractères, qui resteront dans le flux stdin, et seront consommés au prochain appel de scanf.

    Comme tu veux ignorer les caractères excédentaires et demander une nouvelle saisie, tu dois purger stdin après l'appel de scanf.

    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
    #include <stdio.h>
     
    int main(void)
    {
        char ch1[20];
        char ch2[20];
        /* pour vider stdin */
        int c;
     
        printf("Donner une chaîne de caractères (max 19 caractères)\n");
        scanf("%19[^\n]",ch1);
        while ((c = getchar()) != '\n' && c != EOF)
            /* discard */ ;
        printf("Donner la sous chaîne que vous cherchez (max 19 caractères)\n");
        scanf("%19[^\n]",ch2);
        while ((c = getchar()) != '\n' && c != EOF)
            /* discard */ ;
        printf("Merci, vos saisies sont :\n%s\net\n%s\n", ch1, ch2);                
     
        return 0;
    }
    exemple de session :

    Donner une chaîne de caractères (max 19 caractères)
    "Colère et intolérance sont les ennemis d'une bonne compréhension." - Gandhi
    Donner la sous chaîne que vous cherchez (max 19 caractères)
    compréhension
    Merci, vos saisies sont :
    "Colère et intolé
    et
    compréhension

    Eks

  5. #5
    Membre confirmé
    Femme Profil pro
    Enseignant
    Inscrit en
    Octobre 2014
    Messages
    135
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2014
    Messages : 135
    Par défaut
    Merci pour vos réponses, Mais j'ai pas compris pourquoi on a utilisé la boucle while

    voici mon deuxième essai j’espère que c'est juste

    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
    #include <stdio.h>
    int main()
    {
       char ch1[50];
        char ch2[50];
        /* pour vider stdin */
        int c;
        printf("Donner une chaîne de caractères (max 19 caractères)\n");
        scanf("%19[^\n]",ch1);
        while ((c = getchar()) != '\n' && c != EOF)
            /* discard */ ;
        printf("Donner la sous chaîne que vous cherchez (max 19 caractères)\n");
        scanf("%19[^\n]",ch2);
        while ((c = getchar()) != '\n' && c != EOF)
            /* discard */ ;
        printf("Merci, vos saisies sont :\n%s\net\n%s\n", ch1, ch2);
    
    
        int i,j,k,trouve = 0;
    for(i=0; i<(strlen(ch1)-strlen(ch2)+1); i++)
    {
    trouve = 1;
    k = i;
    for(j=0; j<strlen(ch2); k++,j++)
    {
    if(ch1[k] != ch2[j])
    {
    trouve = 0;  printf("\n ch2 n'est pas une sous chaine de ch1\n");
    
    break;
    }
    }
    if(trouve == 1)
    {
    printf("\n ch2 est une sous chaine de ch1 a la position %02d\n", i);
    }
    }
    return 0;
    }
    si je met deux chaine différente il affiche le message n fois ch2 n'est pas une sous chaine de ch1;

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 831
    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 831
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par alias2015_29 Voir le message
    Mais j'ai pas compris pourquoi on a utilisé la boucle while
    Tu veux parler de ce while ((c = getchar()) != '\n' && c != EOF) ?
    C'est pas encore de ton niveau (perso je n'en aurais pas parlé). Il te faut d'abord apprendre le principe des entrées/sorties qui passent par un buffer (tampon) intermédiaire. Et le clavier étant lui-aussi une entrée/sortie, lui-aussi il a un tampon. Or ton scanf() ne récupère pas forcément tout ce qu'il y a dans le tampon (il peut s'arrêter pour certaines raisons évoquées par -Eks-). Et tout ce qu'il n'a pas récupéré reste dans le tampon. Et si un autre scanf() arrive après, ben au lieu de te demander de taper autre chose, il récupèrera ce qu'il reste dans le tampon.
    Cette boucle permet donc de vider le tampon.

    Mais comme je le dis, à ton niveau ce n'est absolument pas primordial ni le but du TP.

    Citation Envoyé par alias2015_29 Voir le message
    voici mon deuxième essai j’espère que c'est juste
    La programmation, ce n'est ni du hasard, ni de la chance. L'espoir est certes toujours permis mais en général on sait d'avance si c'est juste ou pas. Il y a parfois certes un petit écart entre le résultat recherché et le résultat obtenu mais c'est souvent dû à une erreur minime entre l'algo (qui lui est juste) et sa retranscription.

    Citation Envoyé par alias2015_29 Voir le message
    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
    #include <stdio.h>
    int main()
    {
       char ch1[50];
        char ch2[50];
        /* pour vider stdin */
        int c;
        printf("Donner une chaîne de caractères (max 19 caractères)\n");
        scanf("%19[^\n]",ch1);
        while ((c = getchar()) != '\n' && c != EOF)
            /* discard */ ;
        printf("Donner la sous chaîne que vous cherchez (max 19 caractères)\n");
        scanf("%19[^\n]",ch2);
        while ((c = getchar()) != '\n' && c != EOF)
            /* discard */ ;
        printf("Merci, vos saisies sont :\n%s\net\n%s\n", ch1, ch2);
    
    
        int i,j,k,trouve = 0;
    for(i=0; i<(strlen(ch1)-strlen(ch2)+1); i++)
    {
    trouve = 1;
    k = i;
    for(j=0; j<strlen(ch2); k++,j++)
    {
    if(ch1[k] != ch2[j])
    {
    trouve = 0;  printf("\n ch2 n'est pas une sous chaine de ch1\n");
    
    break;
    }
    }
    if(trouve == 1)
    {
    printf("\n ch2 est une sous chaine de ch1 a la position %02d\n", i);
    }
    }
    return 0;
    }
    si je met deux chaine différente il affiche le message n fois ch2 n'est pas une sous chaine de ch1;
    Désolé, commence par indenter ton code. Non seulement ça te donnera une meilleure vision des boucles et de leurs imbrication mais ça aidera les autres à mieux te lire (et toi à te relire). Là ton code est illisible.
    En tout état de cause, si le message est affiché "n" fois, c'est qu'il se trouve dans une boucle alors qu'il ne devrait pas...
    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]

  7. #7
    Membre chevronné
    Homme Profil pro
    très occupé
    Inscrit en
    Juillet 2014
    Messages
    137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : très occupé

    Informations forums :
    Inscription : Juillet 2014
    Messages : 137
    Par défaut
    @ alias2015_29:

    Citation Envoyé par alias2015_29 Voir le message
    Merci pour vos réponses, Mais j'ai pas compris pourquoi on a utilisé la boucle while
    (...)
    La boucle while permet de consommer les caractères restants dans le flux stdin et qui n'ont pas été capturés par scanf.

    A la fin de scanf("%19[^\n]", ..., deux cas sont possibles :

    - l'utilisateur est discipliné et n'a pas tapé une entrée excédant le nombre de caractères permis, alors scanf laisse seulement le caractère de retour à la ligne dans stdin ('\n' - ce qui n'est pas grave en temps normal, car scanf le considère comme un caractère "blanc", qu'il consommera lors du prochain appel de scanf même si tu ne vides pas stdin)
    - l'utilisateur est indiscipliné et a tapé plus de caractères que le nombre de caractères permis, alors scanf laisse les caractères excédentaires, jusqu'au caractère de retour à la ligne dans scanf ('\n', et y compris celui-ci)

    Cette boucle while est la façon standard de procéder pour vider stdin, en consommant tous les caractères qui y restent avec getchar(), pour s'assurer que le prochain scanf arrêtera bien l'exécution du programme en demandant une autre saisie.

    @Sve@r:

    Citation Envoyé par Sve@r Voir le message
    Tu veux parler de ce while ((c = getchar()) != '\n' && c != EOF) ?
    C'est pas encore de ton niveau (perso je n'en aurais pas parlé). Il te faut d'abord apprendre le principe des entrées/sorties qui passent par un buffer (tampon) intermédiaire. Et le clavier étant lui-aussi une entrée/sortie, lui-aussi il a un tampon. Or ton scanf() ne récupère pas forcément tout ce qu'il y a dans le tampon (il peut s'arrêter pour certaines raisons évoquées par -Eks-). Et tout ce qu'il n'a pas récupéré reste dans le tampon. Et si un autre scanf() arrive après, ben au lieu de te demander de taper autre chose, il récupèrera ce qu'il reste dans le tampon.
    Cette boucle permet donc de vider le tampon.

    Mais comme je le dis, à ton niveau ce n'est absolument pas primordial ni le but du TP.
    (...)
    Je ne suis pas d'accord sur le fait que "c'est n'est pas de [son] niveau", ou que les principes strictement nécessaires à la compréhension de cette mécanique soient complexes.

    Si au lieu d'enseigner que scanf permet de récupérer une saisie au clavier, on enseigne que scanf permet de consommer le contenu du flux d'entrée standard selon une description de format, on enseigne que :

    - scanf travaille sur un flux (stdin)
    - que scanf récupère ce qui correspond à la description de ce qu'il doit récupérer dans stdin
    - que le flux ne cesse pas d'exister parce qu'on n'en a récupéré qu'une partie

    on ne masque pas la réalité, et cela devient facile de comprendre que si on veut une nouvelle saisie en ignorant ce qui peut rester dans le flux, il faut vider ce flux préalablement.

    C'est tromper l'étudiant que d'enseigner autre chose, qu'il devra désapprendre ensuite.


    Eks

Discussions similaires

  1. rechercher une sous chaine dans une chaine
    Par id.prog dans le forum Débuter avec Java
    Réponses: 3
    Dernier message: 25/01/2009, 17h59
  2. Rechercher une sous chaine dans un chaine
    Par franck06 dans le forum Access
    Réponses: 2
    Dernier message: 20/09/2006, 14h53
  3. Recherche une sous-chaine dans un champ ?
    Par nerick dans le forum Requêtes
    Réponses: 3
    Dernier message: 06/03/2006, 13h46
  4. Rechercher une sous chaine dans une chaine
    Par annedjomo dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 04/02/2005, 10h36
  5. Rechercher une sous chaine dans une chaine
    Par Oluha dans le forum ASP
    Réponses: 4
    Dernier message: 03/02/2005, 14h39

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