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

  1. #1
    Nouveau membre du Club
    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
    Points : 39
    Points
    39
    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 éclairé
    Inscrit en
    Décembre 2010
    Messages
    290
    Détails du profil
    Informations forums :
    Inscription : Décembre 2010
    Messages : 290
    Points : 719
    Points
    719
    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
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    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 689
    Points : 30 983
    Points
    30 983
    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 averti
    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
    Points : 411
    Points
    411
    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
    Nouveau membre du Club
    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
    Points : 39
    Points
    39
    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
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    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 689
    Points : 30 983
    Points
    30 983
    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 averti
    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
    Points : 411
    Points
    411
    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

  8. #8
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    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 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par -Eks- Voir le message
    C'est tromper l'étudiant que d'enseigner autre chose, qu'il devra désapprendre ensuite.
    Mais le cerveau humain ne fonctionne que comme cela: en apprenant des choses fausses mais permettant d'avoir une "représentation grossière" de la réalité lui permettant de comprendre puis, une fois compris, il doit alors désapprendre pour réapprendre plus en détail...

    Prends le petit garçon qui regarde le soleil: on commencera par lui apprendre qu'il tourne autour de la Terre. Ensuite, il apprendra que ce n'était pas exact mais aura alors eu le cerveau assez formé pour comprendre la réalité. Ensuite on lui apprend la mécanique de Newton permettant d'approximer les mouvements des planètes. Si ensuite il se spécialise en astronomie il "déapprendra" ces formules pour apprendre celles d'Einstein bien plus précises (et permettant ainsi d'expliquer l'orbite de Mercure que les formules de Newton n'expliquent pas). Puis on apprend que la Terre est ronde. Mais le cartographe devra, lui, rectifier cette information pour pouvoir modéliser la Terre telle qu'elle est réellement (une géoïde).

    Et en C c'est pareil. Au début on enseigne printf/scanf permettant d'afficher/saisir mais la saisie est assez foireuse. Ensuite, on apprend les flux, les pointeurs et on peut alors améliorer la saisie en remplaçant scanf par fgets+sscanf (ce qui a en plus l'avantage de ne pas vider artificiellement le buffer permettant alors à un programme de venir se placer en sortie de pipe et de pouvoir vérifier que la saisie s'est bien passée).
    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]

  9. #9
    Nouveau membre du Club
    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
    Points : 39
    Points
    39
    Par défaut
    c'est a dire si j'enlève la partie de code avec la boucle While et je met scanf("%s",&ch1) est faux ?

  10. #10
    Membre averti
    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
    Points : 411
    Points
    411
    Par défaut
    Citation Envoyé par alias2015_29 Voir le message
    c'est a dire si j'enlève la partie de code avec la boucle While et je met scanf("%s",&ch1) est faux??
    Le & devant &ch1 est inutile, comme indiqué par Sve@r "Le nom de ta chaine ch1 étant déjà une adresse, pas besoin de mettre "&" dans le scanf()."

    Si tu mets "%s" en description de format, tu arrêtes la capture du flux au premier caractère blanc, comme je te l'ai indiqué.

    Quant à savoir si ton code sera juste ou pas, il produira des résultats exacts ou pas selon les données qui lui seront fournies.

    Essaye de taper : "un deux trois" pour ch1 puis "deux" pour ch2 pour t'en convaincre, avec scanf("%s",ch1) et sans vider le flux.

    Citation Envoyé par Sve@r Voir le message
    Prends le petit garçon qui regarde le soleil: on commencera par lui apprendre qu'il tourne autour de la Terre. Ensuite, il apprendra que (...)
    C'est là qu'on diffère.

    Lui dire que le soleil tourne autour de la Terre est faux.

    Lui dire que le soleil se lève toujours du même côté et qu'au cours de la journée il parcours le ciel pour se coucher du côté opposé n'est pas faux. On est seulement sur un niveau de compréhension différent.

    Je suis bien sûr d'accord sur le fait qu'on procède par des "représentations grossières", comme tu le dis, mais pas des déclarations fausses ou induisant en erreur.


    Eks

  11. #11
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    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 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par alias2015_29 Voir le message
    c'est a dire si j'enlève la partie de code avec la boucle While et je met scanf("%s",&ch1) est faux??
    Ce n'est pas "faux" (même le "&" inutile est automatiquement enlevé par ton compilo) mais tu devras ne pas rentrer n'importe quoi (en fait pas d'espace).

    Mais ce n'est pas le but du TP que de t'apprendre à gérer stdin. Déjà trouve si ch2 est ou n'est pas dans ch1, le reste viendra en son temps...
    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]

  12. #12
    Nouveau membre du Club
    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
    Points : 39
    Points
    39
    Par défaut
    Comme résumé,

    est ce que la solution que j'ai fait est juste ou non ? ou y a une autre plus correcte ?

    Deuxième exemple :
    Écrire un programme C permettant de saisir les valeurs d'un tableau comportant 10 entiers en n'utilisant que le formalisme pointeur du tableau
    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>
    #define N 10
    int main()
    {
        int *T[N];
        int i;
     
        for(i=0;i<N;i++)
        {
            printf("Donner la valeur de Case %d ",i+1);
            scanf("%d",*(T+i));
        }
        printf("Les éléments du tableau sont: \n");
        for(i=0;i<N;i++)
        {
            printf(" %d |",*(T+i));
        }
        return 0;
    }
    il se bloque à la premiere itération de boucle pour

  13. #13
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Fais attention à ta déclaration de variable.

    Ici, tu indiques que tu vas créer un tableau de N cases contenant des pointeurs d'entier. Ce n'est pas ce que tu souhaites, je pense.

    Pour plus de précision, un tableau est avant tout une adresse de départ. Si tu utilises directement le nom de la variable T, il est considéré comme un pointeur pointant sur la première case de ton tableau.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int tab[N];
     
    *tab = 5;
    printf("tab[0] : %d \n",tab[0]); // affichera 5
     
    tab[0] = 10;
    printf("tab[0] : %d \n",*tab); // affichera 10
    Pour naviguer dans un tableau en utilisant un pointeur, il suffit de prendre le nom de la variable (qui contient l'adresse de la première case, donc) et de l'incrémenter.

    Au passage, aussi : l'équivalent de l'écriture *tab est tab[0]. Par extension, tab est équivalent à &tab[0].

    Un peux plus d'information ici.

  14. #14
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    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 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par alias2015_29 Voir le message
    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
    #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;
    }
    est ce que la solution que j'ai fait est juste ou non ? ou y a une autre plus correcte ?
    Déjà rien que question "indentation" c'est pas terrible. Je t'invite à ce propos à aller lire la remarque de ce post. Sinon est-ce que ta solution fonctionne ?

    Citation Envoyé par alias2015_29 Voir le message
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
            scanf("%d",*(T+i));
            printf(" %d |",*(T+i));
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int i;
    scanf("%d", &i);
    printf("%d", i);

    Pour une variable simple, le scanf() et le printf() n'ont pas tout à fait la même syntaxe. Et là tu écris de la même façon ton scanf() et ton printf() pour un élément de ton tableau qui est sensé être un simple entier (hé oui, un tableau de 10 entiers implique que chaque élément du tableau soit un entier)...

    Sinon voir la remarque de archMqx. Si on te dit que tu as un tableau de 10 entiers (10 "int"), alors ce ne sont pas 10 pointeurs (10 "int étoile")...
    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]

  15. #15
    Nouveau membre du Club
    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
    Points : 39
    Points
    39
    Par défaut
    Merci ArchMqx

    j'ai corrigé et et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     printf(" %d |",*(T+i));
    et ca marche mais ici j'ai pas utilisé le p donc inutile le p??

  16. #16
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    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 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par alias2015_29 Voir le message
    et ca marche mais ici j'ai pas utilisé le p donc inutile le p??
    Inutile si tu ne l'utilises pas !!!
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    for(i=0, p=T; i<N; i++, p++)
    {
        printf("Donner la valeur de Case %d ",i+1);
        scanf("%d", p);
    }
    printf("Les éléments du tableau sont: \n");
    for(i=0, p=T; i<N; i++, p++)
        printf(" %d |",*p);
    Et c'est plus rapide d'utiliser *p (p ayant la bonne adresse) que *(T+I) (qui est d'ailleurs complètement équivalent à T[i]) car dans le premier cas, le processeur va taper direct à la bonne adresse alors que dans le second il est obligé d'effectuer un calcul...
    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]

  17. #17
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for(i=0, p=T; i<N; i++, p++)
        printf(" %d |",*p);
    Et c'est plus rapide d'utiliser *p (p ayant la bonne adresse) que *(T+I) (qui est d'ailleurs complètement équivalent à T[i]) car dans le premier cas, le processeur va taper direct à la bonne adresse alors que dans le second il est obligé d'effectuer un calcul...
    Ouille!
    On dirait du code des années 80, gouverné par les croyances de "la vitesse et les micro-optimisations avant tout" et "le compilateur n'optimise jamais donc plus le code est concis, plus il est rapide" (et encore, le p++ n'est pas dans le déréférencement, ce qui aurait tenu en une seule instruction sur un 68k).

    Si l'on n'est pas dans de l'embarqué time-critical dans lequel le profileur aurait ciblé la lenteur sur la boucle, la version intuitive suffit:
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for(i=0 ; i<N ; i++)
    	printf(" %d |", T[i]);

    C'est quand même plus lisible et plus explicite.

    Edit: Bon, j'ai oublié la consigne pédagogique "En n'utilisant que le formalisme pointeur du tableau."
    Donc on traduit en *(T+i)
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for(i=0 ; i<N ; i++)
    	printf(" %d |", *(T+i));
    Ce qui reste systématique et moins porteur de confusion qu'une boucle for transbahutant deux variables plutôt qu'une.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  18. #18
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    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 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    On dirait du code des années 80, gouverné par les croyances de "la vitesse et les micro-optimisations avant tout" et "le compilateur n'optimise jamais donc plus le code est concis, plus il est rapide" (et encore, le p++ n'est pas dans le déréférencement, ce qui aurait tenu en une seule instruction sur un 68k)....
    Bon, j'ai oublié la consigne pédagogique "En n'utilisant que le formalisme pointeur du tableau."
    Donc on traduit en *(T+i)
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for(i=0 ; i<N ; i++)
    	printf(" %d |", *(T+i));
    Tu remarqueras que tu as juste recopié le code d'origine. Mais penses-tu que le compilo ira jusqu'à optimiser ce genre d'instruction ???

    Citation Envoyé par Médinoc Voir le message
    Ce qui reste systématique et moins porteur de confusion qu'une boucle for transbahutant deux variables plutôt qu'une.
    Quand-même, ne va pas exagérer non plus la difficulté à relire ce type de boucle...
    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]

  19. #19
    Nouveau membre du Club
    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
    Points : 39
    Points
    39
    Par défaut Tableau et pointeur
    Bonjour à tous,

    Pour saisir les valeurs d'un tableau comportant 10 entiers en n'utilisant que le formalisme pointeur.
    * première version : tableau est statique
    * deuxième version : tableau alloué dynamiquement.

    voici mon c :
    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
    /**
    **  TAF-CH2 Pointeurs et Fichiers
    **  Exercice 1: Tableau statique
    **/
    #include <stdio.h>
    # define N 10
    int main()
    {   //déclaration des variables
        int T[N];
        int *p;
        int i;
     
        for(i=0,p=T;i<N;i++,p++)
        {
        printf("Donner valeur de case %d :",i+1);
        scanf("%d",p);
        }
        printf("\n Les elements du tableau sont : ");
        for(i=0,p=T;i<N;i++,p++)
        {
        printf("%d |",*p);
        }
        return 0;
    }
    deuxieme version
    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
    /**
    **  TAF-CH2 Pointeurs et Fichiers
    **  Exercice 1: Tableau Dynamique
    **/
    #include <stdio.h>
    # define N 10
    int main()
    {   //déclaration des variables
        int *T;
        int i;
     
        T = malloc(N * sizeof(int));
     
        if(T== NULL)
            printf("Echec d'allocation dynamique de la mémoire");
        else
        {
            for(i=0;i<N;i++)
            {
            printf("Donner valeur de case %d :",i+1);
            scanf("%d",(T+i));
            }
            printf("\n Les elements du tableau sont : ");
            for(i=0;i<N;i++)
            printf("%d |",*(T+i));
        }
        free(T) ;
        return 0;
    }
    Les deux programmes s’exécutent bien et correcte mais est ce que côté résolution est juste ou non?

  20. #20
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    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 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par alias2015_29 Voir le message
    Les deux programmes s’exécutent bien et correcte mais est ce que côté résolution est juste ou non?
    Pourquoi, dans le second, tu n'as pas utilisé un pointeur pour la saisie et l'affichage tout comme dans le premier ? C'est quand-même navrant que tu n'y ai pas songé de toi-même !!!

    Dans le second tu as le droit de quittter ton main() (via return) si T est NULL ce qui t'évite le else et de devoir tout décaler ton code. Mais certains profs n'aiment pas donc laisse-le tel quel mais retiens-le pour plus tard. Par ailleurs le free() n'est utile que si T a bien été alloué mais laissé tel quel ça ne provoque pas d'erreur car free(NULL) est autorisé (sauf que ça l'appelle pour rien).

    PS: tu as le droit d'indenter correctement aussi tes boucles !!!
    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. 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