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 :

Structures à utiliser pour un exercice


Sujet :

C

  1. #21
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 483
    Points : 13 681
    Points
    13 681
    Billets dans le blog
    1
    Par défaut
    Les fonctions de la famille de scanf() sont très caprieuses, car elles tolèrent assez mal les chaines qui ne répondent pas au format attendu (le f à la fin de scanf, c'est pour "format" ). Pour un code débutant, en connaissant ces limites, on peut se servir du fait que scanf() renvoie le nombre d'éléments convertis. Tu peux donc faire un code comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int main() {
    	int a = 0;
    	int b = 0;
    	int c = 0;
     
    	char buffer[1024];
    	fgets(buffer, 1024, stdin);
     
    	int n = sscanf(buffer, "%d %d %d", &a, &b, &c);
     
    	printf("Elements convertis %d\n", n);
    	printf("%d %d %d", a, b, c);
    }
    Avec la valeur de n, tu peux adapter ton code.

    Par contre, clairement ce code n'accepte que des lignes comme "12 56 89", "12 56" ou "12". Cela correspond bien au format "%d %d %d" qui cherche 3 entiers.

  2. #22
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Octobre 2020
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2020
    Messages : 10
    Points : 2
    Points
    2
    Par défaut
    Merci pour votre réponse !

    Grâce à ce que vous m'avez proposé, j'ai adapté pour le besoin :

    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
    printf("Obligatoire : ports, debit, prix \n");
      printf("Facultatif : constructeur, énergie \n");
     
    	char buffer[1024];
    	fgets(buffer, 1024, stdin);
     
      int n = sscanf(buffer, "%d %f %f %d %f" , &port, &debit, &prix, &constr, &eng);
     
      if ( n == 3)
      {
        printf("ports = %d, débit = %f et prix = %f \n", port, debit, prix);
      }
      else if (n == 4)
      {
        printf("ports = %d, débit = %f, prix = %f et constructeur = %d\n", port, debit, prix, constr);
      }
      else if (n == 5)
      {
        printf("ports = %d, débit = %f, prix = %f, constructeur = %d et énergie = %f\n", port, debit, prix, constr, eng);
      }
      else
      {
        printf("Le nombre d'informations renseignées n'est pas correct \n");
      }
    Ce n'est certes pas très optimisé mais ça fait ce qu'il faut, à un détail près. Si n est inférieur à 3, ça renvoie bien le message d'erreur mais s'il est supérieur à 5, ça ignore ce qui a été écrit et ça n'affiche que les 5 premiers paramètres. Je pense que c'est lié au scanf() qui ne prend en compte que les 5 informations rentrées, mais comment faire alors ?

    EDIT :
    En faisant ça, ça me donne le résultat voulu, mais je trouve pas bof comme alternative :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      int n = sscanf(buffer, "%d %f %f %d %f %c" , &port, &debit, &prix, &constr, &eng, &buffer);
    Des idées ?

  3. #23
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 721
    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 721
    Points : 31 044
    Points
    31 044
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par IdiCoda Voir le message
    Pour la suite de l'exercice, j'ai besoin d'ajouter la possibilité à l'utilisateur de soumettre sa propre commande, avec trois paramètres obligatoires : le nombre de ports, le débit et le prix. Le constructeur et l'énergie sont facultatifs, il peut les soumettre mais cela ne crée pas d'erreur si ce n'est pas le cas.

    Si le nombre de paramètres est soit 3, 4 ou 5, la commande est valide; sinon un message d'erreur est renvoyé.

    Auriez-vous des idées ?
    En C, la notion "paramètre facultatif" n'existe pas. Une fonction qui attend 5 paramètre doit recevoir 5 paramètres. Il te faut donc ruser. Et là, il y a plusieurs possibilités
    • certains paramètres pourront recevoir une valeur spéciale (ex 0 ou -1) signifiant "ne pas tenir compte". Ensuite dans ta fonction, tu testes et si 0 (ou -1 parce que "0" pouvant signifier "j'en veux spécifiquement aucun") alors tu gères le cas
    • tu stockes les commandes dans un tableau de strings terminé par un NULL et tu passes ce tableau à ta fonction qui pourra alors compter combien de strings il y a avant le NULL et gérer selon le cas 3 ou 4 ou 5 strings. L'avantage de cette façon de faire c'est que tu n'as pas à créer de valeur spécifique comme le -1 de la solution précédente (c'est ce qu'on nomme une "valeur magique" et toute valeur magique doit ensuite être maintenue, c'est à dire la commenter et la suivre quand le code évolue) mais l'inconvénient, c'est que tu ne pourras pas commander de l'énergie sans spécifier aussi un constructeur car s'il n'y a que 4 strings, la 4° est obligatoirement celle du constructeur. Ou alors tu spécifies une syntaxe précise pour les strings (ex "constructeur=toto", "ports=18", ...) que tu peux ensuite analyser intelligement dans la fonction

  4. #24
    Membre expérimenté
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    657
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 94
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 657
    Points : 1 434
    Points
    1 434
    Par défaut
    Bonjour,

    Citation Envoyé par IdiCoda Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    {34215637, 8, 001, 256, 1.8, 123.59, 12},
    {34215641, 64, 001, 512, 4.2, 223.59, 45},
    {34215117, 8, 010, 256, 2.1, 93.59, 116},
    {34215118, 2, 001, 64, 0.8, 23.59, 2},
    {34200007, 24, 001, 256, 1.8, 123.59, 212},
    {34214637, 8, 012, 256, 1.8, 49.99, 342},
    {34200017, 32, 100, 256, 2.58, 183.49, 89} ,
    {34225637, 4, 101, 256, 1, 33.59, 62} ,
    {14215637, 16, 101, 256, 1.4, 89.49, 592}
    Il y a des valeurs octales dans ces structures, est-ce normal ?

  5. #25
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 721
    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 721
    Points : 31 044
    Points
    31 044
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par kaitlyn Voir le message
    Il y a des valeurs octales dans ces structures, est-ce normal ?
    Je pencherais plutôt pour des valeurs décimales affichées sur 3 digits. Certes en C l'instruction int i=012 remplit "i" avec une valeur codée en octal, mais là il nous a présenté des valeurs "brutes" (comme si elles venaient d'un fichier ou d'une liste) donc sans lien avec une quelconque convention C et donc présumées être écrites en décimal.
    De fait, si tu lis un fichier contenant une string "012" et que tu convertis cette string en int sans spécifier quoi que ce soit à la fonction de conversion, tu obtiens la valeur 12 et non 10.

  6. #26
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Octobre 2020
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2020
    Messages : 10
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par kaitlyn Voir le message
    Bonjour,



    Il y a des valeurs octales dans ces structures, est-ce normal ?
    Oui. Certains champs ont des tailles spécifiques, notamment 3 chiffres pour le constructeur.

  7. #27
    Membre expérimenté
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    657
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 94
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 657
    Points : 1 434
    Points
    1 434
    Par défaut
    Suite aux second et troisième messages de la discussion, tu sembles utiliser une source dans laquelle un tableau a été initialisé avec ces valeurs, d'où ma remarque.
    Si tu affiches par exemple list_elements[2].constr (éventuellement avec un printf), tu comprendras.

  8. #28
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Octobre 2020
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2020
    Messages : 10
    Points : 2
    Points
    2
    Par défaut
    Les 00 situés devant disparaissent. Comment les forcer à rester ?

  9. #29
    Membre expérimenté
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    657
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 94
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 657
    Points : 1 434
    Points
    1 434
    Par défaut
    Non c'est pire que ça, et ton modèle de structure étant imposé (int constr; ) tu ne peux remettre tes 0 qu'à l’affichage, par contre, pour une initialisation, il faut les enlever.
    C'est là qu'est toute la différence entre la gestion en interne de données et leur présentation (à l'utilisateur). C'était peut-être un piège.

    petite illustration
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    struct {int x, y;} 
        s= {  010, 10};
     
    printf("s.x: %03d (!)\ns.y: %03d", s.x, s.y);

  10. #30
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 669
    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 669
    Points : 10 674
    Points
    10 674
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    En C, la notion "paramètre facultatif" n'existe pas. Une fonction qui attend 5 paramètre doit recevoir 5 paramètres
    si cela existe. Ce sont les ellipses, utiliser notamment par les fonctions printf, scanf, ...

    Documentation en anglais sur l'entête stdarg.h


    Édit : Attention, ce n'est pas compliqué à utiliser mais cela peut être assez plantogène
    Il faut soit passer le nombre d'arguments avant l'ellipse, soit mettre 1 valeur sentinelle. Si tu as le temps tu peux test

    Et tous les arguments doivent avoir le même type ... même si je pense qu'on peut bricoler

  11. #31
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Octobre 2020
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2020
    Messages : 10
    Points : 2
    Points
    2
    Par défaut
    Oh, merci pour cette information ! Je ne le savais pas du tout.

  12. #32
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 721
    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 721
    Points : 31 044
    Points
    31 044
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par foetus Voir le message
    si cela existe. Ce sont les ellipses, utiliser notamment par les fonctions printf, scanf, ...

    Documentation en anglais sur l'entête stdarg.h
    Arf en plus je les connaissais mais j'y ai pas pensé sur le coup !!! J'étais focalisé sur un truc type int fct(int x, int y=0) du C++ mais qu'on n'a pas en C

  13. #33
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 483
    Points : 13 681
    Points
    13 681
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par IdiCoda Voir le message
    Si n est inférieur à 3, ça renvoie bien le message d'erreur mais s'il est supérieur à 5, ça ignore ce qui a été écrit et ça n'affiche que les 5 premiers paramètres. Je pense que c'est lié au scanf() qui ne prend en compte que les 5 informations rentrées, mais comment faire alors ?
    Tu viens de toucher les limites de scanf()

    Citation Envoyé par IdiCoda Voir le message
    En faisant ça, ça me donne le résultat voulu, mais je trouve pas bof comme alternative :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      int n = sscanf(buffer, "%d %f %f %d %f %c" , &port, &debit, &prix, &constr, &eng, &buffer);
    SI ça fonctionne et que c'est suffisant pour ton usage, tu peux t'en contenter

    J'ai pas d'idée simple et efficace à te proposer là, désolé.

  14. #34
    Membre expérimenté
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    657
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 94
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 657
    Points : 1 434
    Points
    1 434
    Par défaut
    Le scanf, écrit tel quel, on ne peut pas s'y fier. A l'inverse, la capture en chaines est moins faillible.
    Dès lors, il est possible d'ajouter une étape et précompter les champs avant de tenter leurs conversions avec un second scanf.
    Si ce dernier ne retourne pas le même nombre, c'est qu'il y a eu une erreur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    char buff[]= "12345 2.0 xxxx 3.999 xxx xxxx";
    char tmp[79+1]= {0};
    int nb_fields= 
        sscanf(buff
            , "%79s %79s %79s %79s %79s %79s"
            , tmp, tmp, tmp, tmp, tmp, tmp
            );
    printf("%s: %d\n", buff, nb_fields);
        //switch(nb_fields) {

  15. #35
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 721
    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 721
    Points : 31 044
    Points
    31 044
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par kaitlyn Voir le message
    Dès lors, il est possible d'ajouter une étape et précompter les champs avant de tenter leurs conversions avec un second scanf.
    Si ce dernier ne retourne pas le même nombre, c'est qu'il y a eu une erreur.
    Quel est l'avantage d'un second scanf par rapport à la méthode de Bktero ?
    Si tu sais que tu dois avoir 6 nombres dès le départ, tu regardes si le scanf() t'en retourne 6 et ça devrait suffire non ?

  16. #36
    Membre expérimenté
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    657
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 94
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 657
    Points : 1 434
    Points
    1 434
    Par défaut
    C'est parce que l'utilisateur peut saisir 3, 4 ou 5 données et que sscanf ne retourne que le nombre d'items correctement affectés.

  17. #37
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 483
    Points : 13 681
    Points
    13 681
    Billets dans le blog
    1
    Par défaut
    Et donc scanf renverra 3, 4 ou 5, et tu te rends compte que ça ne fait pas 6 nombres comme attendu...

  18. #38
    Membre expérimenté
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    657
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 94
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 657
    Points : 1 434
    Points
    1 434
    Par défaut
    Le problème est que ce qui est attendu n'est pas 6, mais 3, 4 ou 5. Cf #20 sqq.

  19. #39
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 483
    Points : 13 681
    Points
    13 681
    Billets dans le blog
    1
    Par défaut
    Le posteur original est étudiant d'après son profil. On peut en déduire qu'il s'agit donc ici d'un exercice. Utiliser scanf() en supposant que la chaine est du format attendu (c'est ce que je mettais en prérequis dans mon message plus haut, c'était peut-être pas clair) est suffisant. Tu fais la convertion, tu regardes combien ça te renvoie, et tu sais quoi faire (3, 4 ou 5).

    En revanche, tu as raison si on souhaite maintenant vérifier que la chaine est bien formattée, et rejeter par exemple "12 13 toto", appeler directement scanf() ne suffit pas.

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Quelle structure utiliser pour manier ces données
    Par marcelin88 dans le forum Débuter
    Réponses: 8
    Dernier message: 26/03/2014, 15h12
  2. Réponses: 4
    Dernier message: 24/09/2010, 00h13
  3. Structure utilisée pour la gestion de graphes
    Par SandyF dans le forum VB.NET
    Réponses: 10
    Dernier message: 05/08/2010, 12h46
  4. Quelle Structure utiliser pour un tri croissant
    Par sunp dans le forum Langage
    Réponses: 6
    Dernier message: 30/04/2008, 14h19
  5. Réponses: 1
    Dernier message: 28/10/2006, 13h05

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