problème de macro ou define

tabliertablier Membre
octobre 2010 modifié dans Objective-C, Swift, C, C++ #1
j'ai besoin d'initialiser des blocs de NSMutableString. J'ai donc écrit:
#define placeString(Xyz) Xyz=[NSMutableString stringWithCapacity:50];[Xyz setString:@";"];[Xyz retain]
#define multiStrings(xa, xb, xc, xd, xe, xf, xg, xh, xi, xj) placeString(xa);placeString(xb);\
placeString(xc);placeString(xd);placeString(xe);placeString(xf);\
placeString(xg);placeString(xh);placeString(xi);placeString(xj);
les strings sont déclarés dans une interface et j'ai programmé:
multiStrings(string0, string1, string2, string3, string4, string5, string6, string7, string8, string9 )
ça marche, mais je ne trouve pas cela très élégant ni très pratique. Notamment je ne peux faire varier le nombre de string-paramètres. Si vous êtes familier de ce genre de chose, comment feriez vous?

Réponses

  • LeeroyLeeroy Membre
    11:30 modifié #2
    un truc dans le genre
    void fillString(NSMUtableString** tab,int count)<br />{<br />&nbsp; &nbsp; tab = ( NSMUtableString** ) malloc(count*sizeof(NSMUtableString*));<br />&nbsp; &nbsp; for(int i=0;i&lt;count;i++)<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; tab[i] = [NSMutableString stringWithCapacity:50];<br />&nbsp; &nbsp; &nbsp; &nbsp; [tab[i] setString:@&quot;&quot;];<br />&nbsp; &nbsp; &nbsp; &nbsp; [tab[i] retain];<br />&nbsp; &nbsp; }<br />}
    


    Bien sur tu peux en faire une fonction à  nombre de paramètre variable si tu ne veux pas du NSMUtableString**, ou tu peux aussi utiliser un NSArray.
  • AliGatorAliGator Membre, Modérateur
    11:30 modifié #3
    Je ne pense pas qu'il soit possible de faire des macro reccursives, qui remplacent genre multiStrings(a,b,c,d) par placeString(a) multiStrings(b,c,d) (d'ailleurs faudrait une condition d'arrêt).

    Il y a bien la possibilité de faire des macros à  nombre variable d'argument, mais pour réutiliser ces arguments directement dans l'expansion dans la macro. Par exemple :
    #define MyLog(format,...) NSLog(@&quot;===&gt; %@&quot; , [NSString stringWithFormat:format , ##__VA_ARGS__])
    
    que tu peux utiliser avec autant d'arguments que tu veux derrière l'argument format... mais cette liste au nombre arbitraire d'arguments ne sera que réutilisée telle quel dans stringWithFormat (les ## devant __VA_ARGS__ servant à  enlever la virgule si cette liste n'est pas spécifiée, cf la doc ici) Mais de là  à  appliquer reccurrsivement une macro placeString sur chacun de tes arguments... ça par contre ça m'étonnerait que ce soit jouable.

    La seule solution que je connaisse (enfin que j'ai pu voir pratiquer) c'est de définir des trucs du genre
    #define multiStrings2(a,b) placeString(a) placeString(b)<br />#define multiStrings3(a,b,c) multiStrings2(a,b) placeString(c)<br />#define multiStrings4(a,b,c,d) multiStrings3(a,b,c) placeString(d)<br />#define multiStrings5(a,b,c,d,e) multiStrings4(a,b,c,d) placeString(e)<br />...
    
    Ou alors faut passer par une fonction et pas par une macro, ou un NSArray (ou tableau C, etc...) bien sûr sinon ([EDIT] Ah ben comme a proposé Leeroy)
  • devulderdevulder Membre
    11:30 modifié #4
    Salut,

    Tu peux faire une méthode avec des paramètres multiples

    CocoaWithLove en parle ici

    A+
  • tabliertablier Membre
    11:30 modifié #5
    Ok merci  pour les avis, je vais lire et essayer les choses conseillées ici.

    Le problème est que je veux appliquer 4 macros à  des séries de trois NSMutableString. Ma solution actuelle est:
    les définitions
    #define enleveStrng(Xyz) [Xyz release]
    #define sauverStrng(Xyz) [deffo setObject:(Xyz)  forKey:@#Xyz]
    #define remetString(Xyz) if ([deffo stringForKey:@#Xyz] != nil) [Xyz setString:[deffo stringForKey:@#Xyz]]
    #define placeString(Xyz) Xyz=[NSMutableString stringWithCapacity:50];[Xyz setString:@";"];[Xyz retain]
    #define multDefine(base, xa, xb, xc)  base((xa)); base((xb)); base((xc));
    et les exemples d'applications sur un groupe de trois:
    multDefine(placeString ,S2a_dic,D2a_dic,P2a_dic) ;
    multDefine(enleveStrng,S2a_dic,D2a_dic,P2a_dic) ;
    multDefine(sauverStrng,S2a_dic,D2a_dic,P2a_dic) ;
    multDefine(remetString,S2a_dic,D2a_dic,P2a_dic) ;
    ça marche et ça réduit le nombre de lignes par trois ce qui n'ai déjà  pas si mal.
  • LeeroyLeeroy Membre
    11:30 modifié #6
    Utilise des pointeurs et passe à  des fonctions c'est beaucoup plus propre. Sans parler que les macro sont dangereuse, la détection d'erreur est beaucoup plus dur.

    Je vais pas de te faire ton code mais toutes tes macro sont écrivable en C standard (en passant pas des pointeurs), en plus tu y gagne avec un nombre de paramètre variable.
  • devulderdevulder Membre
    11:30 modifié #7
    Salut,

    #define placeString(Xyz)  Xyz=[NSMutableString stringWithCapacity:50];[Xyz setString:@";"];[Xyz retain]

    Tu peux gagner un peu d'octets en faisant :

    #define placeString(Xyz)  Xyz=[NSMutableString stringWithCapacity:0];[Xyz retain]

    Normalement l'allocation met la chaine à  @";";

  • AliGatorAliGator Membre, Modérateur
    11:30 modifié #8
    Oui et quitte à  gagner des octets,
    #define placeString(x) x=[[NSMutableString alloc] initWithCapacity:50];
    
    mais bon là  n'était pas la question je pense ^^ :)
  • tabliertablier Membre
    11:30 modifié #9
    Ouf, j'ai un peu de temps pour y revenir!

    @ devulder
    Très bien l'article sur CocoaWithLove

    @Leeroy
    Bien sur tu peux en faire une fonction à  nombre de paramètre variable si tu ne veux pas du NSMUtableString**, ou tu peux aussi utiliser un NSArray
    NSMUtableString**  ne me gène pas et c'est la seule solution pour initialiser les NSMUtableString car on ne peut faire un NSArray avec des objets inexistants (j'ai bêtement essayé, mais à  ma décharge je ne suis qu'un amateur).
  • LeeroyLeeroy Membre
    11:30 modifié #10
    D'ailleurs au passage ma fonction doit être fausse, Faudrait sûrement rajouter un étoile et déréférencer tab qui doit indiquer l'adresse du tableau de NSMutableString*.

    void fillString(NSMUtableString*** tab,int count)<br />{<br />&nbsp;  (*tab) = ( NSMUtableString** ) malloc(count*sizeof(NSMUtableString*));<br />&nbsp; &nbsp; for(int i=0;i&lt;count;i++)<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; (*tab)[i] = [NSMutableString stringWithCapacity:50];<br />&nbsp; &nbsp; &nbsp; &nbsp; [(*tab)[i] setString:@&quot;&quot;];<br />&nbsp; &nbsp; &nbsp; &nbsp; [(*tab)[i] retain];<br />&nbsp; &nbsp; }<br />}
    

    Pour t'en servir tu passe l'adresse d'un NSMutableString** que tu viens de créer. Tu peux aussi mettre le code dans un fichier .mm (obj-C++) pour tirer partie des références du C++ et ainsi simplifier la fonction.
Connectez-vous ou Inscrivez-vous pour répondre.