Ci dessous vous trouverez les fonctions demandées dans le sujet (questions 2 et 3), mais également toutes les fonctions utiles dans le domaine (en particulier la gestion complète des torseurs et des listes de torseurs). J'ai de plus rajouté quelques fonctions utiles pour les tests (saisie, affichage...). Seules les fonctions dont l'entête est en gras correspondent aux questions demandées, toutes les autres ne sont placées ici que pour vous donner des exemples supplémentaires (ces rajouts sont présentés en bleu).
Une solution plus simple est d'utiliser des tableaux (de structures). On gèrera certainement des nombres pas trop importants de pièces. Choisissons un tableau pour les pièces, un autre pour les liaisons. Dans chaque pièce on prévoit un nombre maximal de liaisons, qui sont simplement leur numéro (puisqu'on untilise un tableau, on les numérotera à partir de 0). Si l'on choisit des tableaux statiques, on devra estimer une dimension maximale des tableaux, ce qui ne serait pas le cas pour des tableaux dynamiques.
#include <conio.h> #include <stdio.h> #include <ctype.h> /* pour toupper */ #include <stdlib.h> /* pour malloc, NULL,... */ /******************************************************************/ /* Partie spécifique aux vecteurs (fonctions de base) */ /******************************************************************/ #define DIM 3 typedef float vecteur[DIM]; void v_zero(vecteur res) /* met toutes les composantes du vecteur res à 0 */ { int i; for(i=0;i<DIM;i++)res[i]=0; } void v_copi(vecteur src,vecteur res) /* copie le vecteur src dans le vecteur res */ { int i; for(i=0;i<DIM;i++)res[i]=src[i]; } void v_addi(vecteur v1,vecteur v2,vecteur res) /* additionne v1+v2, résultat dans res */ { int i; for(i=0;i<DIM;i++)res[i]=v1[i]+v2[i]; } void v_sous(vecteur v1,vecteur v2,vecteur res) /* soustrait v1-v2, résultat dans res */ { int i; for(i=0;i<DIM;i++)res[i]=v1[i]-v2[i]; } void v_vect(vecteur v1,vecteur v2,vecteur res) /* produit vectoriel v1^v2, résultat dans res */ { int i; for(i=0;i<DIM;i++)res[i]=v1[(i+1)%3]*v2[(i+2)%3]-v2[(i+1)%3]*v1[(i+2)%3]; /* la formule sans boucle convenait aussi */ } float v_scal(vecteur v1,vecteur v2) /* produit scalaire, résultat (flottant) retourné par la fonction */ { int i; float res=0; for(i=0;i<DIM;i++)res+=v1[i]*v2[i]; return(res); } int v_egal(vecteur v1,vecteur v2) /* dit si les deux vecteurs sont égaux (retour 1) ou non (retour 0)*/ { int i; for(i=0;i<DIM;i++)if(v1[i]!=v2[i])return(0); /* ou mieux : if(fabs(v1[i]-v2[i]<1.e-6) pour éliminer les problèmes d'erreur */ return(1); } void v_mult(float lambda,vecteur v,vecteur res) /* multiplie v par le scalaire lambda, résultat dans res */ { int i; for(i=0;i<DIM;i++)res[i]=lambda*v[i]; } /* fonctions non demandées, pour pouvoir tester */ void v_sais(vecteur v) /* saisie d'un vecteur */ { int i; char axe[]="XYZ"; for(i=0;i<DIM;i++) { printf("entrez la coordonnée suivant %c : ",axe[i]); scanf("%f",v+i); } } void v_affi(vecteur v) /* affichage d'un vecteur */ { int i; char axe[]="XYZ"; printf("["); for(i=0;i<DIM;i++) printf(" %c=%f",axe[i],v[i]); printf(" ]\n"); } /******************************************************************/ /* */ /* test des fonctions de base sur les vecteurs */ /* */ /******************************************************************/ int ieme(int max) /* demande le combien-t-ième, rend ce nombre-1 (entre 0 et max-1)*/ { int i; do { printf("le combien-t-ième (entre 1 et %d) ? ",max); scanf("%d",&i); } while(i<1||i>max); return(i-1); } #define nbmax 5 void v_test(void) /* test de toutes les fonctions sur les vecteurs */ { vecteur t[nbmax]; char c; int i; float f; do { printf("Zero,Sais,Copi,+,-,Vect,scAl,Egal,Mult,Quit\n"); c=tolower(getch()); switch (c) { case 'z':v_zero(t[ieme(nbmax)]);break; case 's':v_sais(t[ieme(nbmax)]);break; case 'c':puts("donnez destination puis source"); v_copi(t[ieme(nbmax)],t[ieme(nbmax)]);break; case '+':puts("donnez destination puis source2 puis source1"); v_addi(t[ieme(nbmax)],t[ieme(nbmax)],t[ieme(nbmax)]);break; case '-':puts("donnez destination puis source2 puis source1"); v_sous(t[ieme(nbmax)],t[ieme(nbmax)],t[ieme(nbmax)]);break; case 'v':puts("donnez destination puis source2 puis source1"); v_vect(t[ieme(nbmax)],t[ieme(nbmax)],t[ieme(nbmax)]);break; case 'a':puts("donnez source2 puis source1"); printf("Résultat du produit scalaire : %f\n", v_scal(t[ieme(nbmax)],t[ieme(nbmax)]));break; case 'e':puts("donnez source2 puis source1"); printf("ils sont égaux ou non : %d\n", v_egal(t[ieme(nbmax)],t[ieme(nbmax)]));break; case 'm':puts("valeur puis vecteur resultat puis source ?"); scanf("%f",&f); v_mult(f,t[ieme(nbmax)],t[ieme(nbmax)]);break; } puts("état des vecteurs :"); for(i=0;i<nbmax;i++)v_affi(t[i]); } while (c!='q'); } /******************************************************************/ /* */ /* Passons aux torseurs (on en revient aux questions posées) */ /* */ /******************************************************************/ typedef struct { vecteur F; vecteur M; }torseur; typedef torseur * adr_t; void t_zero(adr_t z) /* met à 0 les six composantes du torseur Z */ { v_zero(z->F); v_zero(z->M); } void t_copi(adr_t ini,adr_t fin) /* recopie le torseur "ini", dans "fin" */ { v_copi(ini->F,fin->F); v_copi(ini->M,fin->M); } void t_addi(adr_t t1,adr_t t2,adr_t res) /* additionne les composantes de T1 et T2, résultat dans res. Ceci correspond à l'addition de deux torseurs, s'ils sont donnés AU MEME POINT */ { v_addi(t1->F,t2->F,res->F); v_addi(t1->M,t2->M,res->M); } void t_depl(vecteur pos_ini,adr_t ini,vecteur pos_fin,adr_t fin) /* déplace le torseur "ini", donné en "pos_ini", en position "pos_fin". Le torseur résultat est "fin" */ { vecteur pi_pf,v; v_copi(ini->F,fin->F); v_sous(pos_ini,pos_fin,pi_pf); v_vect(pi_pf,ini->F,v); v_addi(v,ini->M,fin->M); } /* fonctions non demandées dans le sujet */ void t_sais(adr_t v) /* saisie d'un torseur */ { printf("Résultante : "); v_sais(v->F); printf("Moment : "); v_sais(v->M); } void t_affi(adr_t v) /* affichage d'un torseur */ { printf("Résultante : "); v_affi(v->F); printf("Moment : "); v_affi(v->M); } /************************************************/ /* */ /* test des fonctions de base sur les torseurs */ /* */ /************************************************/ void t_test(void) /* test de toutes les fonctions sur les torseurs */ { torseur t[nbmax]; char c; int i; vecteur pi,pf; do { printf("Zero,Sais,Copi,+,Dépl,Quit\n"); c=tolower(getch()); switch (c) { case 'z':t_zero(t+ieme(nbmax));break; case 's':t_sais(t+ieme(nbmax));break; case 'c':puts("donnez destination puis source"); t_copi(t+ieme(nbmax),t+ieme(nbmax));break; case '+':puts("donnez destination puis source2 puis source1"); t_addi(t+ieme(nbmax),t+ieme(nbmax),t+ieme(nbmax));break; case 'd':printf("position d'arrivée :");v_sais(pf); printf("position initiale :");v_sais(pi); puts("donnez destination puis source"); t_depl(pi,t+ieme(nbmax),pf,t+ieme(nbmax));break; } puts("état des torseurs :"); for(i=0;i<nbmax;i++)t_affi(t+i); } while (c!='q'); } /******************************************************************/ /* */ /* fonctions de base sur les torseurs généraux (non utilisé ici) */ /* */ /******************************************************************/ typedef struct { torseur T; vecteur pos; }global; typedef global * adr_g; void g_zero(adr_g z) /* met à 0 toutes composantes du torseur Z, au point 0,0,0 */ { t_zero(&(z->T)); v_zero(z->pos); } void g_copi(adr_g ini,adr_g fin) /* recopie le torseur "ini", dans "fin" */ { t_copi(&(ini->T),&(fin->T)); v_copi(ini->pos,fin->pos); } void g_addi(adr_g t1,adr_g t2,adr_g res) /* additionne les torseurs T1 et T2, en transportant si nécessaire T2 à la position de T1, résultat dans res (à la position de T1).*/ { if(v_egal(t1->pos,t2->pos)) t_addi(&(t1->T),&(t2->T),&(res->T)); else /* on aurait pu utiliser g_depl ou même déplacer dans tous les cas */ { torseur translat; t_depl(t2->pos,&(t2->T),t1->pos,&translat); t_addi(&(t1->T),&translat,&(res->T)); } v_copi(t1->pos,res->pos); } void g_depl(adr_g T,vecteur pos_fin) /* déplace le torseur "T", en position "pos_fin". */ { if(!v_egal(T->pos,pos_fin)) { torseur translat; t_depl(T->pos,&(T->T),pos_fin,&translat); t_copi(&translat,&(T->T)); v_copi(pos_fin,T->pos); } } void g_sais(adr_g v) /* saisie d'un torseur */ { t_sais(&(v->T)); printf("point d'application : "); v_sais(v->pos); } void g_affi(adr_g v) /* affichage d'un torseur */ { t_affi(&(v->T)); printf("point d'application : "); v_affi(v->pos); } /******************************************************************/ /* */ /* test des fonctions de base sur les torseurs généraux */ /* */ /******************************************************************/ void g_test(void) /* test de toutes les fonctions sur les torseurs */ { global t[nbmax]; char c; int i; vecteur pf; do { printf("Zero,Sais,Copi,+,Dépl,Quit\n"); c=tolower(getch()); switch (c) { case 'z':g_zero(t+ieme(nbmax));break; case 's':g_sais(t+ieme(nbmax));break; case 'c':puts("donnez destination puis source"); g_copi(t+ieme(nbmax),t+ieme(nbmax));break; case '+':puts("donnez destination puis source2 puis source1"); g_addi(t+ieme(nbmax),t+ieme(nbmax),t+ieme(nbmax));break; case 'd':printf("position d'arrivée :");v_sais(pf); puts("choisissez le torseur source"); g_depl(t+ieme(nbmax),pf);break; } puts("état des torseurs généralisés :"); for(i=0;i<nbmax;i++)g_affi(t+i); } while (c!='q'); } /******************************************************************/ /* */ /* fonctions de base sur les listes de torseurs généralisés */ /* (on est désormais complètement hors sujet) */ /******************************************************************/ typedef struct boite { torseur T; vecteur pos; struct boite * suiv; }boite; /*une boite est un torseur avec sa position */ typedef boite * adr_b; void b_zero(adr_b z) /* met à 0 toutes composantes du torseur Z, au point 0,0,0 */ { t_zero(&(z->T)); v_zero(z->pos); z->suiv=NULL; /*pour l'instant il n'a pas de suivant*/ } void b_copi(adr_b ini,adr_b fin) /* recopie le torseur "ini", dans "fin" mais sans changer les liens */ { t_copi(&(ini->T),&(fin->T)); v_copi(ini->pos,fin->pos); } void b_addi(adr_b t1,adr_b t2,adr_b res) /* additionne les torseurs T1 et T2, en transportant si nécessaire T2 à la position de T1 (sans modifier T2), résultat dans res (à la position de T1). Les liens ne sont pas modifiés. */ { if(v_egal(t1->pos,t2->pos)) t_addi(&(t1->T),&(t2->T),&(res->T)); else /* on aurait pu utiliser g_depl ou même déplacer dans tous les cas */ { torseur translat; t_depl(t2->pos,&(t2->T),t1->pos,&translat); t_addi(&(t1->T),&translat,&(res->T)); } v_copi(t1->pos,res->pos); } void b_ajou(adr_t t,adr_b b,vecteur pos) /* ajoute au torseurs T le torseur B, en transportant si nécessaire B à la position pos (sans modifier B), résultat dans T */ { if(v_egal(b->pos,pos)) t_addi(t,&(b->T),t); else /* on aurait pu utiliser g_depl ou même déplacer dans tous les cas */ { torseur translat; t_depl(b->pos,&(b->T),pos,&translat); t_addi(t,&translat,t); } } void b_depl(adr_b T,vecteur pos_fin) /* déplace le torseur "T", en position "pos_fin", mais sans changer les liens. */ { if(!v_egal(T->pos,pos_fin)) { torseur translat; t_depl(T->pos,&(T->T),pos_fin,&translat); t_copi(&translat,&(T->T)); v_copi(pos_fin,T->pos); } } adr_b b_sais(void) /* saisie d'une liste de torseurs. retourne l'adresse du premier créé. */ /* cette fonction est récursive */ { adr_b nouveau; nouveau=malloc(sizeof(boite)); t_sais(&(nouveau->T)); printf("point d'application : "); v_sais(nouveau->pos); puts("encore (O/N) ? "); nouveau->suiv=(toupper(getch())=='O')?b_sais():NULL; return(nouveau); } void b_affi(adr_b v) /* affichage d'une liste de torseurs */ { while(v!=NULL) { t_affi(&(v->T)); printf("point d'application : "); v_affi(v->pos); v=v->suiv; } } /******************************************************************/ /* */ /* test des fonctions de base sur les listes de torseurs */ /* */ /******************************************************************/ void b_test(void) /* test de toutes les fonctions sur les torseurs */ { adr_b actu,prem=NULL; char c; torseur res; vecteur pdc; prem=b_sais(); puts("vérification : "); b_affi(prem); do { printf("Veuillez me donner un point de calcul : "); v_sais(pdc); t_zero(&res); actu=prem; while(actu!=NULL) { b_ajou(&res,actu,pdc); actu=actu->suiv; } puts("Résultat : "); t_affi(&res); puts("nouveau calcul (O/N) ?"); c=toupper(getch()); } while (c!='N'); } void main(void) { b_test(); }