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 :

define et tableau


Sujet :

C

  1. #1
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Juillet 2019
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juillet 2019
    Messages : 59
    Par défaut define et tableau
    Bonjour,
    je voulais savoir s'il était possible de définir un tableau grâce à un #define.

    Imaginons que je veuille, avec la sdl2, créer 4 textures contenant des textes.
    Pour cela, j'ai créé un tableau avec les 4 messages textes. Et je crée mes textures en faisant appel à chaque case l'une après l'autre.
    Voici ce que je fais et cela marche très bien
    Dans un fichier de déclaration
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    typedef struct Images Images;
    struct Images
    {
        SDL_Surface *Icone;
        SDL_Texture *Image[NbImagesMax];//tableau de NbImagesMax=4 images
        SDL_Texture *Message[NbMessagesMax];//tableau de NbMessagesMax=2 messages
        SDL_Rect DimensionImage[NbImagesMax]; //pour chaque image, dimensionner w et h
        SDL_Rect DimensionMessage[NbMessagesMax]; //pour chaque texte, dimensionner w et h
    };
    #define NbMessagesMax 4//car il y a 4 messages
    Dans un autre fichier, dans une fonction d'initialisation (en ayant definit Images Jeton)

    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
    InitialisationDesMessages(...)
    char *ListeMessage[] = {"message1","message2", "message3","message4"};//liste des textes a charger
    [...]
       for (i=0; i<NbMessagesMax; i++)// chargement des autres images + transparence
        {
            Jeton->Message[i]=ChargementMessages(Renderer,ListeMessage[i],i,police);
            if(Jeton->Message[i]==NULL)//si pb de chargement
            {
                [...gestion si erreur...]
            }
            else
            {
                SDL_QueryTexture(Jeton->Message[i], NULL, NULL, &(Jeton->DimensionMessage[i]).w, &(Jeton->DimensionMessage[i]).h);
            }
        }
        fprintf(fichierErreur, "Nombre de messages correctement chargés : %d \n", i);//il y en a i messages
    [...]
    }
    Comme j'aimerais garder et adapter les messages et le nombre de messages de cette fonction d'initialisation pour un autre projet, j'aimerai avoir quelque chose du type (histoire de ne pas à avoir à modifier l'adaptation à plusieurs endroits du prog) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #define NbMessagesMax 4//car il y a 4 messages
    #define ListeMessage[1] =message1;
    #define ListeMessage[2] =message2;
    #define ListeMessage[3] =message3;
    #define ListeMessage[4] =message4;
    Or ceci ne semble pas fonctionner.
    Quelqu'un aurait la gentillesse de m'aider?
    Cordialement

  2. #2
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 827
    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 827
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par chamludo Voir le message
    je voulais savoir s'il était possible de définir un tableau grâce à un #define.
    Ce n'est pas son but. Donc de même que tu peux parfaitement écraser un moustique avec un marteau, tu auras beaucoup de mal. Et de même qu'après ta lutte avec le moustique tu auras un mur horrible plein de de trous d'impacts ; après ton expérience avec le tableau tu auras un code horrible à lire et à modifier.
    Le #define ce n'est pas "le parchemin magique de Zambala qui va me permettre d'éviter de devoir écrire mon code"...

    Citation Envoyé par chamludo Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #define NbMessagesMax 4//car il y a 4 messages
    #define ListeMessage[1] =message1;
    #define ListeMessage[2] =message2;
    #define ListeMessage[3] =message3;
    #define ListeMessage[4] =message4;
    Or ceci ne semble pas fonctionner.
    Normal. Le #define est traité par le préprocesseur avant la compilation proprement dite. Le préprocesseur prend le code ".c", remplace tous les #define par leur valeur littérale et génère un nouveau code ".i" qui lui est ensuite compilé (on peut d'ailleurs demander au compilateur avec l'option "-E" de ne faire que le préprocesseur pour regarder ce que ça donne et ça vaut franchement le détour de faire ça au-moins une fois).
    Si tu écris #define CARRE(x) ((x)*(x)) puis printf("%d", CARRE(2+3)) ça donnera vraiment printf("%d", ((2+3)*(2+3))) (c'est d'ailleurs pour cette raison associée aux soucis de priorité qu"on met des parenthèses et au #define dans son ensemble et aux paramètres de la pseudo-fonction si elle en a).
    Plus cette notion d'indice (via les crochets) qui n'est certainement pas connue du préprocesseur donc voilà, tout à fait normal que cela échoue.
    Accessoirement les indices d'un tableau de 4 éléments vont de 0 à 3 mais bon, on n'est plus à ça près n'est-ce pas ?

    Citation Envoyé par chamludo Voir le message
    Quelqu'un aurait la gentillesse de m'aider?
    Il faut revenir aux fondamentaux. Ton souci est de ne pas dupliquer le code des message, et ça c'est tout à fait louable et tout à fait justifié. C'est en fait la seule bonne idée de tout ton topic.
    Maintenant, la question c'est "comment, en utilisant les possibilités naturelles du C, pouvoir y arriver".

    Première solution : tu définis ton tableau en global
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char *ListeMessage[] = {"message1", "message2", "message3", "message4"};
     
    void fct_qui_doit_utiliser_les_message() {
    	extern char *ListeMessage[];
    	...
    }
    C'est pas forcément ce qu'il y a de mieux mais ce n'est pas non plus à écarter d'office parce qu'on t'a dit que les globales c'était mal (en fait ce sont les globales créées par flemme qui sont mal). Et rajouter la ligne extern n'est pas obligatoire mais permet d'indiquer aux autres lecteurs que la fonction utilise ce tableau

    Seconde solution : tu écris une fonction qui retourne le tableau puis tu te sers ensuite de la fonction chaque fois que tu as besoin du tableau
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    char **messages() {
    	static char *xxx[] = {"message1", "message2", "message3", "message4"};
    	return xxx;
    }
     
    int main() {
    	char **m;
    	m=messages();
    	for (size_t i=0; i < 4; i++)
    		printf("i=%lu [%s]\n", i, m[i]);
    }
    Peut-être qu'on t'a dit que "static" c'était mal mais là encore c'est pareil, c'est mettre du static de façon irréfléchie qui est mal. Utiliser un static pour mémoriser une information changeante c'est mal (comme par exemple la fonction strtok() qui utilise un static pour mémoriser son travail en cours afin de pouvoir y revenir la fois suivante). Ici le static c'est pour ne pas perdre une information constante donc ça va (faudrait peut-être d'ailleurs rajouter un peu de "const" mais j'ai tapé ça vite fait).

    Troisième solution : tu définis ton tableau dans le main() et tu le passes à toutes les fonctions qui en ont besoin. C'est plus contraignant, mais ça fait partie de la programmation propre du C. Et vu que tu utilises la SDL, ça semble un truc un peu conséquent et par conséquent (oui humour de répétition) tu dois probablement avoir une espèce de configuration (pourquoi pas une structure). Donc dans cette structure dédiée à la configuration de ton projet, tu y rajoutes tes messages puis tu passes l'adresse de cette structure à toutes tes fonctions qui, dès lors, auront accès à la configuration de ton projet en général et aux messages en particulier. Ben oui, écrire un projet c'est réellement écrire un projet (bâtir les fondations etc).

    Et accessoirement, en rajoutant un flag de fin à ton tableau ça t'évite de te devoir te trimballer ce #define NbMessagesMax 4 un peu partout (tu dois connaitre ça le flag de fin vu que c'est une des premières choses qu'on apprend quand on apprend les chaines)...
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <stdio.h>
     
    char **messages() {
    	static char *xxx[] = {"message1", "message2", "message3", "message4", NULL};
    	return xxx;
    }
     
    int main() {
    	char **m;
    	size_t i;
    	for (m=messages(), i=0; *m != NULL; m++, i++)
    		printf("i=%lu [%s]\n", i, *m);
    }
    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]

  3. #3
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Juillet 2019
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juillet 2019
    Messages : 59
    Par défaut
    Merci beaucoup, je vais regarder ça de plus près.

  4. #4
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 759
    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 759
    Par défaut
    J'ai fait 1 solution 1 peu différente mais qui fonctionne 1 fonction tout simplement
    Exemple complet, que j'utilise pour transformer des identifiants (erreur par exemple) en chaîne de caractères
    Le préfixe "g_" n'est pas obligatoire, c'est pour dire "global"

    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
    typedef enum e_msg {
        g_MSG_message1 = 0,
        g_MSG_message2,
        g_MSG_message3,
        g_MSG_message4
    } t_msg;
     
     
    char* g_get_message(t_msg msg) {
        switch(msg) {
        case g_MSG_message1: return "message 1"; break;
        case g_MSG_message2: return "message 2"; break;
        case g_MSG_message3: return "message 3"; break;
        case g_MSG_message4: return "message 4"; break;
        // default: return "default";
        }
    }

    Édit: En regardant sur Internet, le break n'est pas nécessaire et apparemment certains compilateurs peuvent poser des problèmes en mettant 1 break après return.
    Pareillement, j'ai fait 1 énumération qui permet d'avoir 1 nombre fini de cas. Mais certains compilateurs peuvent te dire qu'il manque 1 return final.

    Et aussi la gestion du default: on peut fusionner le défaut et avec 1 identifiant, on peut l'ignorer, ou alors retourner 1 message spécifique et ainsi voir que l'appel "a été forcé" (+ simple pour trouver les erreurs)

  5. #5
    Membre chevronné
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Septembre 2015
    Messages
    213
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de système d'information

    Informations forums :
    Inscription : Septembre 2015
    Messages : 213
    Par défaut
    Bonjour

    je vais chipoter sur ça :
    Citation Envoyé par Sve@r
    Si tu écris #define CARRE(x) ((x)*(x)) puis printf("%d", CARRE(2+3)) ça donnera vraiment printf("%d", ((2+3)*(2+3)))
    #define CARRE(x) ((x)*(x)) puis printf("%d", CARRE(2+3)) ça donnera printf ("%d", 25) le calcul étant fait au moment de la compilation, il n'y a plus de traces de calcul dans l'exécutable

    par contre si tu as #define CARRE(x) ((x)*(x)) puis printf("%d", CARRE(a+b)) avec a et b valorisés avant, ça donnera vraiment printf("%d", ((a+b)*(a+b))) (le calcul étant fait au moment de l'exécution)

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 827
    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 827
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Xelland Voir le message
    #define CARRE(x) ((x)*(x)) puis printf("%d", CARRE(2+3)) ça donnera printf ("%d", 25) le calcul étant fait au moment de la compilation, il n'y a plus de traces de calcul dans l'exécutable
    Ah bien vu. Désolé de l'erreur, je voulais expliquer le fonctionnement du préprocesseur mais j'ai zappé ce détail
    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. Définition de tableau avec #define
    Par pegase.90 dans le forum Débuter
    Réponses: 2
    Dernier message: 08/03/2013, 16h52
  2. définir tableau dans <bean:define>
    Par kokumbo dans le forum Struts 1
    Réponses: 2
    Dernier message: 19/01/2008, 00h59
  3. # define et tableau
    Par sone47 dans le forum C
    Réponses: 9
    Dernier message: 01/12/2006, 19h21
  4. transmision de tableau en parametre
    Par Horus dans le forum C++Builder
    Réponses: 3
    Dernier message: 16/05/2002, 11h15
  5. Réponses: 4
    Dernier message: 13/05/2002, 16h43

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