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 :

Problème de saisie qui boucle


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de bosk1000
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    706
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 706
    Par défaut Problème de saisie qui boucle
    bonjour

    le code que j'ai à un bug,
    il boucle après la saisie du numéro de téléphone en répétant
    voulez-vous enregister cette fiche ? (oui/non)
    merci pour votre aide

    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
     
    #include <stdio.h>
    #include <conio.h>
    #include <string.h>
     
     
    struct enreg
    {
        char *nom[30];
        char *tel[10];
     
    };
     
    FILE *fd;
    #define NOM_FICHE "fiche"
     
    //sous programme de creation de fiche
    int creation ()
    {
        struct enreg en;
        char res[4];
        printf("Entrer le nom\n");
       scanf("%s",en.nom);
        printf("Entrer le numero de telephone");
        scanf("%s",en.tel);
        do
        {
            printf("voulez-vous enregister cette fiche ? (oui/non)");
            scanf("3%s",res);
        }
        while (strcmp(res,"non")&& strcmp(res,"oui"));
        if (res[0]=='o')
        {
            if (fseek(fd,0,SEEK_END)||
                    fprintf(fd,"%s\n%s\n",en.nom,en.tel)==-1)return-1;
        }
        return 0;
    }
     
    //sous programme de recherche de fiche
    int recherche ()
    {
        printf("sous-programme de recherche d'une fiche\n");
        printf("appuyer sur une touche...");
        getch();
        //on attent jusqu'à ce que la touche soit frapper
    }
     
     
    //programme d'affichage du menu
    int main()
    {
        //menu pour le choix de la selection
        int selection, res;
        fd=fopen(NOM_FICHE,"a+");
        if(!fd)
        {
            printf("impossible d'ouvrir le fichier!");
            return-1;
        }
        //faire tant que Fin de programmme n'est pas selectionner
        do
        {
            // faire tant que le choix 1 ou 2 n'est pas selectionner
            do
            {
                printf("Choisissez une option:\n"
                       "1. création d'une nouvelle fiche\n"
                       "2. Recherche d'une fiche\n"
                       "3. Fin de programmme\n");
                // lire la selection
                scanf("%d",&selection);
                if (selection <1||selection>3)printf ("selection non valide\nVeuillez saisir les valeur 1, 2 ou 3\n");
            }
            while (selection <1||selection>3);
            if (selection==1) res=creation();
            if (selection==2) res=recherche();
        }
        while (selection!=3 && res==0);
        fclose(fd);
        return 0;
    }

  2. #2
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 773
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 773
    Par défaut
    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
        char res[4];
     
        res[0] = '\0'; res[1] = '\0'; res[2] = '\0'; res[3] = '\0';
     
        do {
            printf("Voulez-vous enregistrer cette fiche ? (oui/non) ");
            scanf("%3s", res);
     
    #ifdef _DEBUG
            printf("\n-> Valeur: %s\n\n", res);
    #endif // _DEBUG
        }
    //  while (strcmp(res, "non") && strcmp(res, "oui"));
    //  while ((strcmp(res, "non") != 0) && (strcmp(res, "oui") != 0));
        while ((strncmp(res, "non", 3) != 0) && (strncmp(res, "oui", 3) != 0));

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 841
    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 841
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par bosk1000 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    struct enreg
    {
        char *nom[30];
        char *tel[10];
    };
    Bonjour

    En dehors de ton pb de saisie, tu as aussi un problème dans ces deux éléments de ta sturcture. Si, comme je le pense, ce sont des éléments dédiés au stockage d'un nom et d'un n° de téléphone, alors ce sont de simples tableaux de caractères qu'il te faut définir et non des tableaux de pointeurs.

    Si maintenant tu définis des tableaux de pointeurs, ça signifie alors qu'une structure "enreg" est dédiée à pouvoir stocker 30 noms et 10 n° de téléphones max. Mais dans ce cas, chaque pointeur stockant un nom (ou un tel) devra alors allouer de la mémoire pour pouvoir stocker réellement les caractères composant ce nom (ou ce tel). Faisable bien entendu mais moins évident.

    Accessoirement utiliser des variables globales est une très mauvaise idée. Ca évite des problèmes immédiats mais ça en provoque cent fois plus ensuite.

    Citation Envoyé par foetus Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        char res[4]; 
        res[0] = '\0'; res[1] = '\0'; res[2] = '\0'; res[3] = '\0';
    do {
            printf("Voulez-vous enregistrer cette fiche ? (oui/non) ");
            scanf("%3s", res);
    while (...)
    Mouais. On se demande pourquoi mettre des '\0' vu que scanf() mettra celui qu'il faut où il faut mais si c'est nécessaire, alors autant utiliser les bons outils...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char res[4]={'\0', '\0', '\0', '\0'};
    memset(res, '\0', 4);
    ...
    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
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 773
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 773
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Mouais. On se demande pourquoi mettre des '\0' vu que scanf() mettra celui qu'il faut où il faut mais si c'est nécessaire, alors autant utiliser les bons outils...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char res[4]={'\0', '\0', '\0', '\0'};
    memset(res, '\0', 4);
    ...
    Ce n'est pas ce que j'ai vu avec mon printf juste après la saisie , mais bon

    Et de plus je préfère utiliser ma notation sur des petits tableaux (pas plus de 10 éléments) parce que:
    • C'est plus facile pour moi. Parce pour un tableau de 10 éléments (par exemple), il ne faut pas en louper un avec la notation {'\0', '\0' /*, ...*/ }. Versus 10 copiés-collés que l'on peut suivre avec les indices.
    • Et je pense que la compilateur l'interprète comme la notation {'\0', '\0' /*, ...*/ } (ou vice et versa)
    • Un appel de fonction inutile, à moins que memset soit inline (quoique pour du C)

  5. #5
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    salut,

    Citation Envoyé par foetus Voir le message
    Ce n'est pas ce que j'ai vu avec mon printf juste après la saisie , mais bon
    Sve@r a pourtant raison, scanf() rajoute automatiquement le nulbyte à la fin

    Un appel de fonction inutile
    ça va pousser une trentaine d'octets sur la pile qui par défaut dispose de +8Mo, on parle même pas de compter les cycles cpu ça n'est pas pertinent du tout

    pour la petite info, char res[4] = { '\0', '\0', '\0', '\0' }; et char res[4]; res[0]=0; res[1]=0; res[2]=0; res[3]=0; génèrent tous les deux le même code machine avec 4 affectations byte par byte
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    movb   $0x0,-0x10(%rbp)
    movb   $0x0,-0xf(%rbp)
    movb   $0x0,-0xe(%rbp)
    movb   $0x0,-0xd(%rbp)
    tandis que char res[4] = {0}; génèrera un code plus optimisé en une seule instruction du style movl $0x0,-0x10(%rbp), soit l'équivalent d'un char res[4]; *(long *)&res = 0;
    memset() quant à lui fait sa sauce classique :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    mov    $0x4,%edx
    mov    $0x0,%esi
    mov    %rax,%rdi
    callq  0x400520 <memset@plt>
    en revanche sur un tableau plus grand (d'une centaine d'éléments) ce n'est plus pareil :
    la méthode de Sve@r
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char res[100] = {
       '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
       '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
       '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
       '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
       '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'};
    ainsi que la déclaration en char res[100] = {0}; vont toutes les deux générer un code machine optimisé par le compilateur (en tenant compte de l'architecture 32/64, en dépassant un peu si besoin pour aligner etc.), sorte de fast-copy en écrivant 13 qwords (13x8 en 64bits, 25x4 en 32bits) dans le buffer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    mov    $0x0,%eax
    mov    $0xc,%ecx
    mov    %rdx,%rdi
    rep stos %rax,%es:(%rdi)
    la méthode de foetus en revanche... fait rigoureusement ce qu'elle semble faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char res[100];
    res[0] = 0; res[1] = 0; res[2] = 0; res[3] = 0; res[4] = 0; res[5] = 0; res[6] = 0; res[7] = 0; res[8] = 0; res[9] = 0;
    res[10] = 0; res[11] = 0; res[12] = 0; res[13] = 0; res[14] = 0; res[15] = 0; res[16] = 0; res[17] = 0; res[18] = 0; res[19] = 0;
    (...)
    res[90] = 0; res[91] = 0; res[92] = 0; res[93] = 0; res[94] = 0; res[95] = 0; res[96] = 0; res[97] = 0; res[98] = 0; res[99] = 0;
    donne son équivalent en code machine avec une succession interminable de movb (affectation char après char donc)

  6. #6
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 773
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 773
    Par défaut
    @BufferBob: merci l'ami

    Et effectivement, avec un multiple de 4 (peut-être aussi de 8 ou de 2), le compilateur va insérer un int ou un long .

    Donc cela me rassure dans un sens : avec un petit tableau (pas plus de 10 éléments) on l'initialise complètement et le code ne génère pas trop d'instructions.

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 841
    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 841
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par BufferBob Voir le message
    ...tandis que char res[4] = {0}; génèrera un code plus optimisé en une seule instruction du style movl $0x0,-0x10(%rbp), soit l'équivalent d'un char res[4]; *(long *)&res = 0;
    J'ai failli aussi écrire dans cette syntaxe mais j'avais un petit doute à ce sujet: écrire char res[4] = {0}; va-t-il remplir tout le tableau de 0 ou seulement son premier élément ??? Me semble me souvenir que c'est tout le tableau (où pour être plus exact le premier élément est intialisé avec la valeur demandée et les autres sont mis à 0) mais je ne suis plus certain...
    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]

  8. #8
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Cette écriture initialise tout le tableau à 0.

    J'ai écrit un article à ce sujet : https://gradot.wordpress.com/2012/09...ructures-en-c/
    Voir vers "Allons maintenant à la partie 6.7.8 Initialization. On lit avec intérêt le point 10......"

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [XL-2013] Problème macro qui BOUCLE sans raison
    Par tyndare36 dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 10/11/2014, 14h36
  2. Réponses: 9
    Dernier message: 22/06/2011, 16h19
  3. Problème de script qui boucle
    Par numerodix dans le forum ActionScript 3
    Réponses: 3
    Dernier message: 23/11/2009, 13h58
  4. [scanf] problème de programme qui boucle
    Par dr4g0n dans le forum Bibliothèque standard
    Réponses: 5
    Dernier message: 22/01/2008, 10h48
  5. Problème actionscript qui boucle
    Par baleiney dans le forum Flash
    Réponses: 1
    Dernier message: 26/03/2007, 07h44

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