Comment qu'est-ce qu'on fait pour faire... "struct"

Répondre
Partager Rechercher
Ca faisait longtemps que je n'avait pas lancé ma rubrique "Comment qu'est-ce qu'on fait pour faire...", et comme là je coince sur le "sctruct", je vais lancer ce petit appel aux personnes connaissant cet animal étrange.

Parce que je n'ai toujours rien compris même avec les bouquins sur le C, parce qu'avec MSN 'y a pas de balises PHP et que j'ai rien compris à ce qu'on me disait quand même, je d'mande là d'abord.


... Bah voila : Comment qu'est-ce qu'on peut donc bien faire pour faire un "struct", s'il vous plaît ?


Pitié, quoi... Enfin, à l'aide, quoi...
Pour l'utilisation c'est assez simple en fait c'est comme en C
http://www.nwnlexicon.com/compiled/primer.struct.html

L'interet par contre en NWScript est assez limite en fait. Un des principaux interet des structures c'est que cela te permet de creer un nouveau type et de l'utiliser dans des tableaux ou autre. Comme en NWscript tu n'as pas de tableau, forcement ca limite beaucoup l'interet des struct . Et la 2eme limitation c'est que tu ne peux pas passer les structures en locale, et comme au final, les GetLocalXX, SetLocalXX sont tres utilisés ben du coup ca limite l'utilisation des structs

Il y aurait un 1er interet pour les struct c'est par exemple de passer en parametre a une fonction une structure. L'interet du systeme c'est que ca limite les modifs de code si tu rajoutes des valeurs a passer en parametre car ta signature de fonction ne change pas.
(Bien sur faut changer ton code quand tu utilises ou pas la nouvelle donnee mais par tout ou tu as appel la fonction t'as rien a changer)
Le 3eme interet serait de renvoyer une structure en code retour. Ca par contre j'ai jamais essaye en NWScript. Mais là il y aurait un interet certain car comme NWNSCript ne fait que des passage de parametre par valeur, si tu veux modifier a l'interieure d'une fonction 2 variables et que les modifs soient visibles a l'exterieure, comme tu ne peux faire qu'un seul return, le seul moyen propre qui reste c'est les structs (le moyen sale etant les globales )
Pour faire simple et assez imagé :
-> tu prend admettons un classeur
-> tu lui ajoutes des Intercallaires ayant un type distinct. Genre : histoire, philo, math
Gros avantage, t'as besoin de ces cours dans la journée... tu sors ce classeur.

Les structures "struct" fonctionne pareillement. Tu définis une structure avec des variables (comme les matières ci dessus)
On aura donc :
Code PHP:

struct St_Classeur
  
{
     
string Vars1// pour l'histoire
     
string Vars2// pour la philo
     
int Vars3;      // pour les maths
  

C'est un petit exemple de définition de la structure. Il faud savoir que l'on peut y mettre ce que l'on veud dedans comme type de variable (pas tester pour les objets)...

Cette définition ce met le plus souvent en dehors des fonctions et avant celles-ci (comme le montre l'exemple donné par le lien de Garrath).

Après à chaque fois que tu as besoin de ce type de structure, il te suffit de créer une variable de ce type comme suit :
Code PHP:

struct St_Classeur St_ClasseurPerso
Et là boom, comme par magie tu obtiens ton classeur perso (St_ClasseurPerso) ayant pour structure celle définie par le classeur générique (St_Classeur).

Après côté utilisation, cela peut être vraiment utile lors de passage de paramètres dans certaines fonctions. Une fonction avec une disaine de paramètre, c'est assez contraignant à faire appel... alors qu'avec une structure contenant cette même disaine de paramètre cela donnerai un appel de ce genre :
Code PHP:

AfficheInfoClasseur(St_ClasseurPerso); 

ceci serait pour l'appel de la dite fonction. au passage cette dernière suit le même principe que les autres définitions de fonction mais avec comme type de variable en paramètre une structure.

Comme sur l'exemple fourni par garrath (cf lexicon), les appels de chaque variable contenue dans la structure doit ce faire comme suit pour mon histoire de classeur :
Code PHP:

St_ClasseurPerso.Vars1 "ce que tu souhaites"
On peut y appliquer des opérations dessus en fonction du type de la variable contenu dans la structure... un string reste un string, un int reste un int...
La structure ce contente simplement de les regrouper dans un seul lieu.

Les structures peuvent être très utiles pour l'implémentation de fonction et de bibliothèque... cependant, on ne peut les stockké nul part sous NWScript. On pourrait créer une petite bibliothèque de gestion de structure, mais je pense sincèrement qu'on ne gagnerai rien en terme de performance lors du stockkage et de la récupération.
Toutefois elle peut s'avérer très utiles pour des fonctions devenant complexe à cause d'un grand nombre de variable à traiter. On peut facilement l'utiliser lors de manipulation de base de données ou pour la récupération d'une ligne d'un tableau. Car il est plus agréable de travailler avec des variables qui nous parles.

Espère avoir été assez clair.
L'intérêt principal, comme le souligne Garrath, c'est d'utiliser ces struct dans les retours de fonction car ça permet de retourner plusieurs valeurs à la fois :

Par exemple avec un truc du genre :
Code PHP:

struct Exemple
    
{
    
int     pv;
    
int     niveau;
    
float   angle;
    };


struct Exemple InfosPC(object oPC)
    {
    
struct Exemple stInfos;

    
stInfos.pv GetCurrentHitPoints(oPC);
    
stInfos.niveau GetHitDice(oPC);
    
stInfos.angle GetFacing(oPC);

    return 
stInfos;
    } 
La fonction InfosPC te renvoie, avec un seul appel, à la fois les PV, le niveau et l'angle du PJ.

Là où il faut en avoir l'utilité, c'est que ça devient intéressant seulement dans les fonctions qui doivent renvoyer des données non triviales (non facilement récupérables en dehors de la fonction), par exemple des informations obtenues au cours d'un algorithme.

Pour ma part j'ai appris l'existence de ce type hier et j'en avais jamais croisé dans les scripts, ni d'ailleurs ressenti le besoin.
J'ai fait ça, tout à l'heure. Est-ce que c'est bon ? (mis à part oPlayer et oPlaceable qui ne sont pas définis, vu que ça relève du test) :
Code PHP:

struct strStruct
{
    
string sResRef;
    
string sTag;
    
int nValue1;
    
int nValue2;
};

void main()
{
    
object oPlaceable;
    
object oPlayer;
    
int bValid FALSE;

    
struct strStruct strBase,strItem;

    
strBase.sResRef GetLocalString(oPlaceable,"BASE_RESREF");
    
strBase.sTag GetLocalString(oPlaceable,"BASE_TAG");
    
strBase.nValue1 GetLocalInt(oPlaceable,"BASE_VALUE_1");
    
strBase.nValue2 GetLocalInt(oPlaceable,"BASE_VALUE_2");

    
object oItem GetFirstItemInInventory(oPlayer);
    while(
oItem!=OBJECT_INVALID)
    {
        
strItem.sResRef GetResRef(oItem);
        
strItem.sTag GetTag(oItem);
        
strItem.nValue1 GetLocalInt(oItem,"ITEM_VALUE_1");
        
strItem.nValue2 GetLocalInt(oItem,"ITEM_VALUE_2");

        if(
strItem == strBase)
        {
            
bValid TRUE;
            
SpeakString("L'item correspondant a ete trouve.");
            break;
        }
        
oItem GetNextItemInInventory(oPlayer);
    }

    if(
bValid == FALSE)
        
SpeakString("Aucun item ne correspond aux criteres.");

Dans le même ordre d'idée, j'ai fait ça...
Code PHP:

struct stStruct
{
    
string sResRef;
    
string sTag;
    
int nValue1;
    
int nValue2;
};

struct stStruct stBase(object oObject)
{
    
struct stStruct stReturn;

    
stReturn.sResRef GetLocalString(oObject,"BASE_RESREF");
    
stReturn.sTag GetLocalString(oObject,"BASE_TAG");
    
stReturn.nValue1 GetLocalInt(oObject,"BASE_VALUE_1");
    
stReturn.nValue2 GetLocalInt(oObject,"BASE_VALUE_2");

    return 
stReturn;
}

void main()
{
    
object oBase1,oBase2;
    
object oPlayer;
    
int bValid FALSE;

    
struct stStruct stCheck1,stCheck2,stItem;

    
stCheck1 stBase(oBase1);
    
stCheck2 stBase(oBase2);

    
object oItem GetFirstItemInInventory(oPlayer);
    while(
oItem!=OBJECT_INVALID)
    {
        
stItem.sResRef GetResRef(oItem);
        
stItem.sTag GetTag(oItem);
        
stItem.nValue1 GetLocalInt(oItem,"ITEM_VALUE_1");
        
stItem.nValue2 GetLocalInt(oItem,"ITEM_VALUE_2");

        if(
stItem == stCheck1)
        {
            
bValid 1;
            
SpeakString("L'item correspondant à la base 1 a été trouvé.");
            break;
        }
        else if(
stItem == stCheck2)
        {
            
bValid 2;
            
SpeakString("L'item correspondant à la base 2 a été trouvé.");
            break;
        }

        
oItem GetNextItemInInventory(oPlayer);
    }

    if(
bValid == FALSE)
        
SpeakString("Aucun item ne correspond aux critères.");

    else
    {
        
// tout plein de trucs qui se passent si ça correspond...
    
}

C'est bon aussi ?
Algorythmiquement parlant ouai...

Techniquement en NWNScript je pense pas...

Le probleme se situe la :
Code PHP:

if(strItem == strBase

Ce genre de truc meme en C ne fonctionnera pas (en tout cas pas avec certitude...ca dependra du pointeur etc...)
Pour que cela fonctionne il faut que tu crees une fonction test
Code PHP:

 struct strStruct
{
    
string sResRef;
    
string sTag;
    
int nValue1;
    
int nValue2;
}; 

int EgaliteStructstruct strStruc stsrcstruct strStruc stdest)
{
  
     return (  (
stsrc.sResRef == stdest.sResRef) &&
                  (
stsrc.sTag == stdest.sTag) &&
                  (
stsrc.nValue1 == stdest.nValue1) &&
                  (
stsrc.nValue2 == stdest.nValue2));

Une fois que tu as ecrits cela ton test devient donc
Code PHP:

if (EgaliteStruct(strItemstrBase)) 

et la ca marche

Ce genre d'ecriture pourrait marcher a tous les coups si on avait la surcharge d'operateur par exemple (c'est possible en C++ par exemple pas en Java )
Mais dans ce cas il faudrait de toutes façons redefinir la fonction == .
Est ce que 2 choses sont identiques car elles pointent sur le meme objet ou parce qu'elles ont la meme valeur?
Citation :
Publié par kermo
Oui on peut faire des tests d'égalité entre deux structures, ça renvoie TRUE si tous les éléments sont égaux deux à deux.
Tu en es sur?
Car ca meme en C, c'est pas le cas...
(j'ai mis un 2è test juste après le premier)

Pourtant mon bouquin sur le C (maintenant que grace un peu quand même à vous je viens un peu de comprendre), et ben il me dit qu'on peut faire une vérification de ce type :

if(stItem == stCheck1)

et qu'on peut même faire :

stCheck = stItem;


Enfin, en tout cas ça m'arrangerait. Au pire faire juste une fonction de vérification, ça ne demande pas énormément de ressources.
Citation :
Publié par Garrath
Tu en es sur?
Car ca meme en C, c'est pas le cas...
Oui j'ai fait un essai, par contre évidemment on ne peut pas faire de tests d'inégalités. Idem pour assigner la valeur d'une structure à une autre (stTruc = stBidule)
Typiquement quand tu testes une chaine de caractere, == ca veut dire quoi?
cad ca doit renvoyer vrai quand le texte uniquement est identique? ou vrai quand cela pointe sur la meme chose?
En C si on fait == pour lui on teste si on pointe sur la meme chose. Donc en gros la en C il te dira que c'est bon car c'est le meme pointeur. Donc tout depend si tu testes la valeur des champs ou les pointeurs...
En C pour une structure c'est pareil. A == B si A est B son la meme chose pas si ils ont la meme valeur.

Ex :
struct test { int x; int y;}

struct test A, B;

A.x = 5;
A.y = 2;

B.x = 5;
B.y = 2;

en C normalement
A == B te renvoi faux!

Par contre si tu as
A.x = 5
A.y = 2

et
B = A;

alors A==B te renvois vrai.

et c'est pareil pour une chaine de caractere en C...
A == B renvoie TRUE en nwnscript dans les deux cas.

D'ailleurs ça fait pareil pour les chaînes de caractères, peu importe la façon dont elles ont été définies, si "c'est écrit la même chose" alors les chaînes sont égales (en C je sais pas, mais dans d'autres langages de script que je connais ça fait pareil).
Franchement le struct en Nwscript c'est plus gadget qu'autre chose. ça te permet juste de grouper des variables, mais comme en général on travaille rarement avec des dizaines de variables dans une même fonction pour un même objet.... Personnellement j'ai utilisé une fois struct parce que j'avais besoin de récupérer 3 variables d'un coup. Mais là encore, j'aurais très bien pu faire 3 lignes au lieu d'une (sans compte qu'avec la déclaration, le struct en prend même plus ).
Sans oublier que comme il n'existe pas de "SetLocalStruct", ça devient encore plus useless si tu veux de la persistance.
Je ne sais pas si ce genre de fonction sera prévue pour NWN2, mais ça rendrait déjà l'utilisation des struct plus intéressante.
Bon j'ai refait mon code, mais ça coince quelque part au moment de la vérification, il ne trouve pas l'item...

J'ai revérifié le ResRef, le Tag, les deux variables un bon nombre de fois et tout colle :
Code PHP:

struct stStruct
{
    
string sResRef;
    
string sTag;
    
int nValue1;
    
int nValue2;
};

struct stStruct stBase(object oObject)
{
    
struct stStruct stReturn;

    
stReturn.sResRef GetLocalString(oObject,"BASE_RESREF");
    
stReturn.sTag GetLocalString(oObject,"BASE_TAG");
    
stReturn.nValue1 GetLocalInt(oObject,"BASE_VALUE_1");
    
stReturn.nValue2 GetLocalInt(oObject,"BASE_VALUE_2");

    return 
stReturn;
}

int CompareStructs(struct stStruct stSourcestruct stStruct stTarget)
{
    return(
stSource.sResRef==stTarget.sResRef && stSource.sTag==stTarget.sTag && stSource.nValue1==stTarget.nValue1 && stSource.nValue2==stTarget.nValue2);
}

void main()
{
    
object oPlaceable OBJECT_SELF;
    
object oPlayer GetLastUsedBy();
    
int bValid FALSE;

    
struct stStruct stItem,stCheck;

    
// Je crois que c'est ça qui coince, mais j'ai des doutes...
    
stCheck stBase(oPlaceable);

    
object oItem GetFirstItemInInventory(oPlayer);
    while(
oItem!=OBJECT_INVALID)
    {
        
stItem.sResRef GetResRef(oItem);
        
stItem.sTag GetTag(oItem);
        
stItem.nValue1 GetLocalInt(oItem,"ITEM_VALUE_1");
        
stItem.nValue2 GetLocalInt(oItem,"ITEM_VALUE_2");

        if(
CompareStructs(stItem,stCheck))
        {
            
bValid TRUE;
            
SpeakString("L'item correspondant a été trouvé.");
            break;
        }
        
oItem GetNextItemInInventory(oPlayer);
    }

    if(
bValid == FALSE)
        
SpeakString("Aucun item ne correspond aux critères.");

Citation :
Publié par kermo
A == B renvoie TRUE en nwnscript dans les deux cas.

D'ailleurs ça fait pareil pour les chaînes de caractères, peu importe la façon dont elles ont été définies, si "c'est écrit la même chose" alors les chaînes sont égales (en C je sais pas, mais dans d'autres langages de script que je connais ça fait pareil).
Oui pour les chaines de caracteres sur NWNScript ca marche ... Au final ca reste logique, il verifie bien les valeurs a chaque fois donc il fait pareil pour les structures...

Il n'y a que pour les object alors en NWNscript ou la il verifie que c'est le meme?
(j'ai jamais fait de test la dessus. faudrait creer 2 fois le meme objet et verifier si ils sont identiques... )

[HS]
Pour le C je te le confirme sans pb. En C pour comparer 2 chaines de caractere y a une fonction expres strcmp(...)
Le == compare le pointeur en fait (en C une chaine de caractere est un pointeur)
Donc effectivement ils ont obligatoirement la meme valeur mais dans ce cas tu ne pourrais jamais teste A == "titi"
[/HS]
Citation :
Publié par Deyonara
Bon j'ai refait mon code, mais ça coince quelque part au moment de la vérification, il ne trouve pas l'item...

J'ai revérifié le ResRef, le Tag, les deux variables un bon nombre de fois et tout colle :
Je vois pas ce qui cloche...
Mais bon souvent quand on commence a jouer avec des strutures on s'aperçoit qu'il manque un truc c'est l'affichage des valeurs de la struc
Et oui un entier, une chaine etc... quand tu trouves pas un pb dans ton programme tu fais un petit SendMessageToPC -ou speakstring ou ce que tu veux) (en C un printf... )Pour une structure tu peux pas le faire de base. Donc penser a ecrire directement une fonction d'affichage des valeurs de ta structure. Pour le Debuggage y a pas mieux
Alors, j'ai trouvé ma bourde, c'est dans la variable de l'item que j'ai raté un chiffre...

Sinon, ça marche dans les deux sens :
Code PHP:

int CompareStructs(struct stStruct stSourcestruct stStruct stTarget)
{
    return(
stSource.sResRef==stTarget.sResRef && stSource.sTag==stTarget.sTag && stSource.nValue1==stTarget.nValue1 && stSource.nValue2==stTarget.nValue2);
}

... ...

if(
CompareStructs(stItem,stCheck)) 
Peut être remplacé par :
Code PHP:

if(stItem == stCheck
Tests approved : Moi contente, ça marche ^^


Merci à vous en tout cas, j'ai compris comment marche un struct ^^
Répondre

Connectés sur ce fil

 
1 connecté (0 membre et 1 invité) Afficher la liste détaillée des connectés