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

  1. #1
    Nouveau membre du Club

    Homme Profil pro
    rien
    Inscrit en
    décembre 2018
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : rien

    Informations forums :
    Inscription : décembre 2018
    Messages : 8
    Points : 31
    Points
    31
    Billets dans le blog
    1

    Par défaut saisie : conseils d'amélioration bienvenus

    Bonjour,

    Dans le cadre d'un cours d'initiation à la programmation en C, je me suis rendu compte que les entrées sorties en C, c'est une montagne pour les débutants. Pour éviter de dépenser trop d'énergie sur le sujet, je me suis mis à écrire une petite API sans prétention, que j'ai appelée saisie.

    Elle permet de saisir (sans se poser de questions) :
    • une chaîne de caractères (longueur maxi 1024 caractères je crois)
    • un nombre entier court
    • un nombre entier
    • un nombre réel
    • un nombre en notation scientifique

    Comme ça, quand ce problème est réglé avec les débutants (utilisation d'une fonction, après avoir compris ce qu'est une signature), on peut se concentrer sur les algorithmes de base.

    Pour information, nous ne travaillons que sous Linux dans mon cours. Après plusieurs années de tests, ça fonctionne très bien, et le fonctionnement est parfaitement adapté à Linux, en mode console. Mais ce serait bien si on pouvait (peut-être) la rendre portable sur Windows, car j'ai beaucoup d'élèves qui utilisent Windows sur leur machine.

    ET comme au royaume des aveugles, les borgnes sont rois, je souhaiterais que quelqu'un qui a plus de connaissances que moi, puisse me donner des conseils pour l'améliorer, en partie sur les points suivants :

    • est-ce qu'il y a des gros problèmes à résoudre rapidement ? (sécurité, etc)
    • comment l'adapter à Windows ? (si c'est possible, pas sûr ...)


    Liens: à l'origine, j'utilisais github, mais je vais tout migrer progressivement sur framagit.

    Lien direct sur github: https://github.com/ebachard/saisie

    Lien sur framagit:https://framagit.org/ericb/some_litt.../master/saisie


    Merci d'avance pour votre aide et vos conseils, et excellentes fêtes de fin d'année !



    --
    qɔᴉɹə

    L'association EducOOo : http://www.educoo.org

    https://framagit.org/ericb

    https://github.com/ebachard

  2. #2
    Membre à l'essai
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    avril 2012
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : avril 2012
    Messages : 5
    Points : 17
    Points
    17

    Par défaut

    Il est plus facile de rendre portable un programme de type "console" que graphique.
    Pour la fonction efface_ecran, elle peut être constituée de la seule ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #ifdef _WIN32
       system("cls");
    #else
      Linux code...
    #endif
    Il y a bien sûr beaucoup plus compliqué (voir https://support.microsoft.com/en-us/...le-application )

    Il y a une erreur dans la fonction initialize_string. Le paramètre est de type pointeur sur char. Donc l'opération sizeof(aString) donnera toujours 4 pour un système 32 bits ou 8 avec un compilateur 64 bits.
    Pour moi la fonction devrait être:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void initialize_string (char * aString, size_t aSize)
    {
       memset(aString, '\0', aSize);
    }
    La fonction calcule_signe utilisée dans plusieurs fonctions me semble inutile au vue des fonctions que vous utilisez telles strtod, strtol et strtoll.
    Ces fonctions font tout le travail, signe compris. Et en utilisant correctement leur 2ème paramètre de type pointeur sur pointeur, vous pouvez savoir si la chaîne est correcte ou non.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    long long int nbTemp;
    char *finTransformation;
     
    nbTemp = strtoll("-12345687", &finTransformation, 10);
     
    if (*finTransformation == '\0')
       bString_Is_OK = true;
    else
    {
       bString_Is_OK = false;
       printf("Le nombre est invalide a partir de %s\n", finTransformation);
    }
    La fonction saisie_chaine_de_caracteres retourne toujours EXIT_SUCCESS, quelle utilité?
    Lors des printf, ne pas mettre de caractères accentués.
    Dans le fichier saisie.h, seules les fonctions de l'api devraient y figurer. Les autres devraient être en static dans le fichier saisie.c

  3. #3
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    7 193
    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 : 7 193
    Points : 20 496
    Points
    20 496
    Billets dans le blog
    1

    Par défaut

    Bonjour

    Moi j'ai un doute sur le but de cette fonction
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void clean_string(const char *g_buf, FILE *aStream)
    {
      char * aChar = strchr(g_buf,'\n');
     
      if (aChar != NULL)
        *aChar = 0;
      else
      {
        int aCharValue;
        while ((aCharValue = fgetc(aStream)) != '\n' && aCharValue != EOF);
      }
    }
    Elle se nomme "clean_string" donc "nettoyage de chaine". Mais elle ne nettoie pas vraiment la chaine !!!
    Soit on l'appelle avec une chaine contenant "\n" (ex "toto\n" ou même "toto\ntiti") et dans ce cas elle le remplace par un \0 ce qui donne alors dans tous les cas "toto" (car ce qui est après le '\0' sera ignoré par toutes les fonctions de type "str"). Mais ça ce n'est pas vraiment un "nettoyage" (bon évidemment ça dépend de ce qu'on associe au mot "nettoyage").
    Et soit on l'appelle avec une chaine ne contenant pas de '\n' et dans ce cas, elle lit le buffer jusqu'à trouver un '\n' ou qu'il soit vide. Mais la chaine passée n'est pas du tout nettoyée de quoi que ce soit (et là, on peut mettre ce qu'on veut comme définition de "nettoyage" de toute façon rien ne se fait dans la chaine).
    J'ai un peu l'impression que tu as voulu faire une espèce de fonction "multi-usage" destinée selon ce qu'on lui passe, soit à supprimer le '\n' d'une chaine (chaine ayant probablement récupérée une ligne de fichier via fgets() ce qui explique alors le '\n' présent), soit à vider une ligne de buffer incompètement lue. Bref deux actions complètement disparates tout en n'étant pas forcément exclusives (je peux, moi, avoir envie de supprimer le '\n' et aussi avoir envie de purger mon tampon => dois-je alors l'appeler 2 fois ???)

    Ce n'est pas forcément interdit de vouloir faire un truc un peu "multi". Plus lourd à coder et à maintenir que coder les actions diverses dans des fonctions indépendantes mais pas interdit. Mais dans ce cas, moi je l'aurais écrit ainsi
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void clean_string(const char *g_buf, FILE *aStream) {
      if (g_buf != NULL) {
        char *aChar = strchr(g_buf, '\n');
        if (aChar != NULL) *aChar = 0;
      }
      if (aStream != NULL) {
        int aCharValue;
        while ((aCharValue = fgetc(aStream)) != '\n' && aCharValue != EOF);
      }
    }
    Ainsi je peux l'appeler avec une chaine et NULL pour stream (la fonction ne s'occupe que de la chaine), ou bien NULL pour la chaine et un flux quelconque (la fonction ne s'occupe que du flux) ou bien tout rempli et la fonction s'occupe des deux...
    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

Discussions similaires

  1. Réponses: 7
    Dernier message: 12/05/2003, 22h50
  2. Réponses: 3
    Dernier message: 19/03/2003, 15h19
  3. [debutant]Limiter le temps de saisi
    Par Nasky dans le forum C
    Réponses: 5
    Dernier message: 17/03/2003, 15h47
  4. [Kylix] saisie d'@ IP kylix2 OE
    Par sdoura2 dans le forum EDI
    Réponses: 1
    Dernier message: 10/11/2002, 01h54
  5. [Kylix] crypter la saisie sous kylix
    Par nahmsath dans le forum EDI
    Réponses: 2
    Dernier message: 15/10/2002, 13h16

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