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 :

Votre avis sur un code de conversion


Sujet :

C

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Technicien réseau
    Inscrit en
    Janvier 2016
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : Belgique

    Informations professionnelles :
    Activité : Technicien réseau

    Informations forums :
    Inscription : Janvier 2016
    Messages : 1
    Points : 1
    Points
    1
    Par défaut Votre avis sur un code de conversion
    Bon(jour)/soir à tous,

    Afin d'éviter les "scanf" en C, et ne souhaitant pas absorber différents code du web, j'ai fais un petit quelque chose.
    Le code se divise en 2 parties :
    1. fonctions.h
    2. source.c


    Ceci afin de le rendre plus lisible.

    Je me permet alors de vous le publier ici, pour en obtenir des commentaires sur la logique, et vos conseils qui pourrait permettre de l'améliorer et moi aussi.

    Merci à vous.

    Fonctions.h
    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
    83
    84
    85
    86
    87
    88
    89
    #include <string.h>
    #include <stdio.h>
    #define TRUE 1
    #define FALSE 0
     
    void menu()
    {
    	char t0[] = ("********************************");   //Un Affichage basic me direz vous. 
    	char t1[] = ("*                              *");
    	char t2[] = ("*         Conversion           *");
    	char t3[] = ("*                              *");
    	char t4[] = ("********************************");
     
    	puts(t0); 
    	puts(t1); 
    	puts(t2); 
    	puts(t3);
    	puts(t4); 
    }
     
    short saisie(char *nb,int lgt)
    {
    	short i,j; 
    	short taille=0; 
    	char comp[] = { '0','1','2','3','4','5','6','7','8','9','/0' }; //Tableau de comparaison CHAINE de Char et nombre. 
     
    	for (i = 0; i < lgt; i++)  //lgt = longueur de la chaine original envoyée en 2nd paramètre. 
    	{
    		for (j = 0; j < 11; j++)
    		{
    			if (*(nb + i) == comp[j]) //nb = Chaine original envoyé en 1er paramétre. 
    			{
    				taille ++; //Si la comparaison est vraie, on incrémente la taille. ===> Cette variable permettra de vérifier si le nbre de caractère est bon. 
    				j = 11; //Et si Taille n'est pas bon, c'est qu'un caractère n'est pas un nombre.  
    			}
    		}
    	}
     
    	if (taille == lgt)
    		return TRUE;
    	else
    		return FALSE; 
    }
     
    int conversion(char *lg)
    {
    	int i, j, k, z;
    	int nbre = 0;
    	char comp[] = { '0','1','2','3','4','5','6','7','8','9' }; //Chaine de comparaison. 
     
    	for (i = 0; i < 10; i++)
    	{
     
    		for (j = 0; j < 10; j++)
    		{
    			if (comp[j] == *(lg + i)) // Nul besoin de commentaire ici. #Paradox
    			{
    				for (k = 0, z = 1; k < strlen(lg) - (i + 1); k++) z *= 10; // La variable z permet de bien placer les unité diziaine et centaine. 
    				nbre += j * z;
    				z = 1; //On le réinitialise a 1. 
    			}
    		}
     
    	}
     
    	return nbre; //On retourne la variable mais convertie en int. 
    }
     
    void EntrerNbre(char *lg)
    {
    	char clav[10];
    	short pass = 0;
    	short gardien, i;
     
    	printf("\nSaisissez un nombre > ");
    	do
    	{
    		if (pass)
    		{
    			printf("Vous n'avez pas ecris un nombre. vous avez entre %s \n", clav);
    		}
    		gets(clav);
    		gardien = saisie(&clav, strlen(clav));
    		pass++;
    	} while (!gardien);
     
    	strcpy(lg, clav);
     
    }
    Le source.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include "fonctions.h"
    #include <stdio.h>
    void main()
    {
    	char nbr[10];
    	int i;
    	menu();
    	EntrerNbre(&nbr);
    	i = conversion(&nbr);
    	printf("\n\n====> %d <======\n", i);
    }

  2. #2
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut


    Par où je commence ?

    gets, hein ? On est d'accord. Tu trouveras probablement dans la FAQ la raison pour laquelle cette fonction est à proscrire.

    Les alternatives à scanf existent ! Pour la simple et bonne raison que scanf n'est justement pas conçue pour faire de la saisie au clavier. On réalise en général une saisie portable via fgets. L'analyse de chaîne de caractères et la conversion en nombre se fait ensuite via sscanf ou strto*.

    En ce qui concerne la logique proprement dite : il n'y a aucune cohérence au sein de ton programme. Tu valides d'abord une conversion en tentant de l'effectuer, via saisie puis.. tu effectues à nouveau cette conversion à l'aide d'une autre fonction presque identique : conversion. Pourquoi ? Sans compter que la première demande la longueur de la chaîne passée en paramètre, qu'on lui fournit via strlen, alors que la seconde invoque directement strlen.

    Revois déjà ton programme et nous continuerons à partir de là.

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Normalement le but d'un découpage c'est de mettre les prototypes dans les .h à inclure et les implémentations dans les .c qui seront compilés et liés...
    Protège tes define pour éviter les surprises. Les valeurs devraient toujours être entres parenthèses.
    Quitte à définir true et false, autant allé au bout et définir bool.
    Tu n'as pas besoin de 5 variables pour afficher 5 lignes..
    saisie est sensé faire quoi ? Ce n'est pas une saisie en tous cas. Le code ressemble à une implémentation chelou de check qu'une chaîne est un nombre.
    conversion a au moins un nom qui semble être ce qu'elle fait. Mais l'implémentation est vraiment bof en plus de traiter arbitrairement 10 caractères...
    EntrerNbre fait de la saisie, de la vérification, de l'affichage de résultat, puis finit avec une copie inutile et inexplicable dans une variable locale
    nbr est déjà un pointeur, inutile de prendre prendre son adresse, je suis même un peu surpris que ça passe, ca devrait au moins émettre un warning. Les affiches-tu ?

    Il n'y a aucune homogénéité dans les nommages.


    http://c.developpez.com/faq/?page=Bo...aveur-de-fgets
    http://c.developpez.com/faq/?page=Bo...utiliser-scanf
    http://c.developpez.com/faq/?page=Ge...iere-securisee
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  4. #4
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Citation Envoyé par Bousk Voir le message
    nbr est déjà un pointeur, inutile de prendre prendre son adresse, je suis même un peu surpris que ça passe
    nbr est un tableau, du coup nbr et &nbr renvoient la même adresse. C'est un exotisme du langage, comme souvent avec ce qui touche aux tableaux en C. C'est mieux expliqué par cette réponse sur SO : https://stackoverflow.com/a/2528328 .

  5. #5
    Membre expérimenté Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    625
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 625
    Points : 1 559
    Points
    1 559
    Par défaut
    Hello,

    - apparemment, tu ne connais pas la fonction isdigit(), sinon tu l'aurais employée dans saisie(), qui se serait alors résumée à 4 lignes
    - tu ne connais pas non plus strtoul(), qui remplacerait avantageusement ta gymnastique avec i, j et z dans conversion()
    - et il existe en C, depuis 1999, soit depuis presque 20 ans, un type bool, que l'on trouve dans <stdbool.h>. Et, bien sur, true et false y sont définis
    - ça a été dit, mais: une fonction menu() qui ne propose aucun menu, une fonction saisie() qui ne saisit rien....
    On écrit "J'ai tort" ; "tord" est la conjugaison du verbre "tordre" à la 3ème personne de l'indicatif présent

  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
    Bonjour

    Le principal semble avoir été déjà dit. Surtout le fait qu'on ne met jamais de code C dans du .h
    Maintenant quelques détails. Par exemple perso je pense que ton
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if (taille == lgt)
    		return TRUE;
    	else
    		return FALSE;
    se remplace avantageusement par return taille == lgt ?TRUE :FALSE voire même return taille == lgt. Et tu peux remplacer ton char comp[] = { '0','1','2','3','4','5','6','7','8','9','/0' } par un élégant char comp[] = "0123456789" voire même directement char *comp = "0123456789" puisque tu ne modifies pas son contenu. Et ton j=11 (nombre magique) peut alors devenir j=strlen(comp) + 1 ou plus simmplement tu mets un bon vieux break bien efficace et bien explicite.

    De plus, ton *(nb + i) ne gagne absolument rien en vitesse par rapport à un nb[i] bien plus lisible.
    On a souvent l'habitude de dire qu'un pointeur va plus vite qu'un tableau. C'est vrai mais seulement si le pointeur est déjà placé à la bonne adresse. Par exemple char *pt=nb+i fera ensuite que tous les accès *pt seront plus rapide que nb[i]. En revanche, les instructions *(nb + i) et nb[i] prennent le même temps car dans les deux cas l'opération est la même (se placer au début et décaler de "i" cases).

    Donc finalement ta fonction devient ceci
    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
    short saisie(char *nb, size_t lgt)
    {
    	size_t i; 
    	size_t taille; 
    	char *pt1;
    	char *pt2;
     
    	char *comp="0123456789";
     
    	for (i = 0, pt1=nb, taille=0; i < lgt; i++, pt1++)
    	{
    		for (pt2=comp; *pt2 != '\0'; pt2++)
    		{
    			if (*pt1 == *pt2)	// Ici ça va effectivement plus vite car les pointeurs sont déjà à la bonne position
    			{
    				taille++;
    				break;
    			}
    		}
    	}
     
    	return taille == lgt;
    }

    Et sinon le plus gros (que personne n'a vu même pas moi car je viens éditer mon post pour le dire): main() n'est pas de type "void" !!!!!

    PS: z = 1; //On le réinitialise a 1. => un commentaire efficace et explicite...
    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
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    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 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    voire même directement char *comp = "0123456789"
    Tu voulais sans doute dire : const char *comp = "0123456789"

  8. #8
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    C'est équivalent, mais pour des raisons probablement historiques GCC n'émettra un warning si le const est absent qu'avec -Wwrite-strings .

  9. #9
    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 Bktero Voir le message
    Tu voulais sans doute dire : const char *comp = "0123456789"
    Ouais c'est vrai que je ne pense pas souvent aux "const". Mais si on veut alors vraiment y aller à fond, je pense alors que ce sera const char* const comp="0123456789" (mais j'ai dû faire des tests pour savoir quel "const" s'appliquait à quoi parce que sinon je m'y perdais un peu )

    Accessoirement je me suis aussi demandé si un "static" n'optimiserait pas en plus. Car dans ce cas, en cas d'appels multiples, seul le premier créerait la variable qui resterait ensuite disponible pour les autres...
    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]

  10. #10
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    @Matt_Houston, le const "semi conseillé" est un problème très ancien. C'est une erreur en C++ de l'oublier depuis des lustres, ça n'est toujours pas un vrai warning en C, pourtant les compilateurs C embarqués que j'utilise se comportent comme le C++ en indiquant une erreur. Ces textes sont 99% du temps à mettre en ROM donc un pointeur non const est une mauvaise initiative.

    @Sve@r, const char* const comp = "0123456789"; est totalement équivalent à static const char comp[] = "0123456789"; en terme d'optimisation. Dans les 2 cas on a une zone mémoire constante d'adresse fixe donc en embarqué elle serait dans la ROM ou la Flash. Seule différence sizeof(comp) retourne la taille d'un pointeur dans le premier cas et la longueur+1 de la chaîne dans le second.
    Par contre char comp[] = "0123456789"; ou const char comp[] = "0123456789"; sont non optimaux, car les 11 caractères constants doivent être copiés dans un tableau local à la fonction à chaque appel, comp étant un tableau non statique.

Discussions similaires

  1. Votre avis sur mes codes
    Par herzak dans le forum Langage
    Réponses: 2
    Dernier message: 28/01/2011, 11h41
  2. [XL-2003] Votre avis sur mon code en VBA ?
    Par [ZiP] dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 02/03/2010, 13h56
  3. MAX_CONNECTIONS: votre avis sur ce code
    Par Zartan dans le forum Administration
    Réponses: 2
    Dernier message: 31/01/2010, 04h34
  4. [FFT] Votre avis sur mon code
    Par deubelte dans le forum C++
    Réponses: 1
    Dernier message: 10/02/2007, 20h14
  5. [Code Prof]votre avis sur un code?
    Par granquet dans le forum Réseau
    Réponses: 6
    Dernier message: 11/04/2006, 20h41

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