[C] une fonction qui renvoie un tableau de 3 doubles ??

une fonction qui renvoie un tableau de 3 doubles ?? [C] - Programmation

Marsh Posté le 30-03-2001 à 00:57:04    

je veux faire une fonction qui prend en parametre un tableau de 3 doubles
 
double coord[3]
 
j aimerais bien que ma fonction me le renvoie une fois modifié
 
j ai essayé ça :
 
double    *fonction(double  coord[3], int angle)
{
...
return (coord);
}
 
mais ca fais un joli error code
 
et ça aussi :
 
void    fonction(double *coord[3], int angle)
{
...
}
mais la il n est pas modifié
 
 
 
je pourrais le mettre dans une structure mais cette fonction ne sert pas qu a un seul endroit et j aimerais pouvoir lui passer n importe quel tableau de trois double

Reply

Marsh Posté le 30-03-2001 à 00:57:04   

Reply

Marsh Posté le 30-03-2001 à 02:55:52    

il faut faire par exemple
void func(double * mod, double angle)
{
 mod[0]=cos(angle);
 mod[1]=sin(angle);
 mod[2]=tan(angle);
}

Reply

Marsh Posté le 30-03-2001 à 08:46:59    

Salut
Je te rappelle que tu ne peux pas passer des tableaux mais des pointeurs.
 
Tu dois donc passer un pointeur(ou référence) sur ton tableau. Pas d'autre solution, surtout si tu veux le resortir.
 
Si tu as d'autres questions, mail-moi.
@+

Reply

Marsh Posté le 30-03-2001 à 13:31:20    

typedef struct {
 double x,y,z;
} coord;
 
coord fonction (coord mescoord, int angle) {
 ..
 return mesnouvellescoord;
}
 
Ca marche pas ca?
Ou encore en C++:
 
coord fonction (const coord &mescoord, int angle) {
 ..
 return mesnouvellescoord;
}
 
Sinon la solution du pointeur ca marche aussi
meme si parfois on voudrait etre sur d'obtenir
un nouvel objet et pas modifier les donnees sur place.
(ca depend ce que tu veux)
 
Legreg

Reply

Marsh Posté le 30-03-2001 à 13:41:56    

Si tu programmes en C, la deuxieme version devient:
 
coord fonction (const coord *mescoord, int angle) {
  coord mesnouvellescoord;
  mesnouvellescoord.x = f(mescoord->x, mescoord->y, mescoord->z);  
  ...
  return mesnouvellescoord;  
}  
 
Legreg

Reply

Marsh Posté le 30-03-2001 à 21:17:32    

passage de variables :
3 doubles -> 3*4 = 12 octets
 
passage de pointeurs :
4 octets
 
en admettant que ton tableau n'est pas dynamique et que son adresse ne change pas.
 
void fct(double* tab,int angle)
{
   for(int i=0;i<3;i++)
     tab[i] += angle;
}
 
ca fonctionne ca prend que 4 octets en parametre.
 
double* fct(double* tab,int angle) -> aucun interet car la fonction renvoie exactmeent la meme adresse que celle qui est entrée en paramettre .. puisque l'adresse du tableau ne change pas.

Reply

Marsh Posté le 31-03-2001 à 06:19:08    

En C ANSI tu peut aussi passer une référence de structure:
struct t {
double  tab[3]; /* ou double x,y,z; */
};
 
/* Version où le tableau retourné est passé en paramètre */
function f(struct t &t) {
  t.tab[0] = ...; /* ou t.x = ... */
  t.tab[1] = ...; /* ou t.y = ... */
  t.tab[2] = ...; /* ou t.z = ... */
}
main() {
  struct t ret;
  f(ret);
  printf("%lf %lf %lf", ret.tab[0], ret.tab[1], ret.tab[2]);
/* ou printf("%lf %lf %lf", ret.x, ret.y, ret.z); */
}
 
/* Version en passant 3 références aux variables à retourner */
function f (double &x, double &y, double &z) {
  x = ...;
  y = ...;
  z = ...;
}
main() {
  double x, y, z;
  f(x, y, z);
  printf("%lf %lf %lf", x, y, z);
}
 
Tu peux aussi utiliser directement une déclaration de tableau:
 
f(double tab[3]) {
  tab[0] = ...;
  tab[1] = ...;
  tab[2] = ...;
}
main() {
  double ret[3];
  f(ret);
  printf("%lf %lf %lf", ret[0], ret[1], ret[2]);
}
 
Maintenant si on suppose que le tableau n'est pas déclaré par l'appelant et n'est pas passé en paramètre, mais retourné à l'appelant, la seule façon est de l'allouer dynamiquement dans f:
 
double[3] f() {
  double tab[] = (double[])calloc(sizeof double, 3);
/* et aussi, en C++ seulement: double tab[] = new double[3]; */
  tab[0]=...;
  tab[1]=...;
  tab[2]=...;
  return tab;
}
main() {
  double ret[];
  ret = f();
  printf("%lf %lf %lf", ret[0], ret[1], ret[2]);
  free((void*)ret); /* en C++: delete[] ret; */
}
 
/* version avec un typedef de tableau */
typedef double tableau[3];
tableau *f() {
  tableau *tab = (tableau *)malloc(sizeof tableau);
  /* et aussi, en C++ seulement: tableau *tab = new tableau; */
  (*tab)[0] = ...;
  (*tab)[1] = ...;
  (*tab)[2] = ...;
  return tab;
}
main() {
  tableau *ret;
  ret = f();
  printf("%lf %lf %lf", (*ret)[0], (*ret)[1], (*ret)[2]);
  free((void*)ret); /* en C++: delete ret; */
}
 
/* version avec une structure ou classe C++ */
typedef struct t {
  double tab[3]; /* ou double x,y,z; */
} tableau;
tableau *f() {
  tableau *val;
  val = (tableau*)calloc(sizeof tableau);
  /* et aussi, en C++ seulement: tab = new tableau;
  val->tab[0] = ...; /* ou tab->x = ...; */
  val->tab[1] = ...; /* ou tab->y = ...; */
  val->tab[2] = ...; /* ou tab->z = ...; */
  return val;
}
main() {
  tableau *ret;
  ret = f();
  printf("%lf %lf %lf", ret->tab[0], ret->tab[1], ret->tab[2]);
/* ou printf("%lf %lf %lf", ret->x, ret->y, ret->z); */
  free((void*)ret); /* ou en C++: delete ret; */
}
 
Le principal ennui avec les versions dynamiques où la fonction alloue la place pour le résultat est qu'elle confie la désallocation à l'appelant, et que cela peut générer non seulement des lenteurs (trop de new ou de malloc ou calloc), mais en plus il est plus difficile de maintenir le programme car des oublis de désallocation ou le problème des désallocations différées ou des références multiples à gérer pour savoir quand on peut libérer l'objet peuvent survenir.
Dans ce cas, il vaut mieux conceptuellement considérer que la fonction agit tel un constructeur C++, et qu'à tout constructeur (appel de f() dans un contexte local de variables ou scope) doit être associé un destructeur dans le même scope.
Aussi les solutions où c'est l'appelant qui s'occupe de gérer l'allocation de la valeur de retour d'une fonction sont en général plus propres (c'est le même cas ici quand une fonction doit retourner une chaine de caractères, qui est aussi un tableau de caractères): l'appelant précise à la fonction l'adresse ou la référence de la structure ou du tableau à retourné complété, accompagné d'indication telle que la longueur maximale du tableau, pour que la fonction adopte un comportement approprié en cas d'insuffisance de taille, par exemple retourner au programme client une indication d'erreur.

 

[edit]--Message édité par verdy_p--[/edit]

Reply

Marsh Posté le 31-03-2001 à 15:55:00    

comment reinventer le monde à partir d'une fonction bete ?
 
faut aller au plus simple ! on a jamais dit qu'on devait passer par de la gestion de memoire dynamique ... tant qu'on y est autant refaire le compilateur et windows dans la même foulée !!

Reply

Marsh Posté le 31-03-2001 à 16:23:43    

Euh 95% des données d'un programme sont en mémoire dynamique, dès que le programme devient un peu important.

Reply

Marsh Posté le 31-03-2001 à 21:58:08    

euh ouhai mais là c'est loin d'être important ! ...  
un tableau de 3 doubles ... tout est fixé et le prog tient en 3 ligne .. basta .

Reply

Marsh Posté le 31-03-2001 à 21:58:08   

Reply

Marsh Posté le 01-04-2001 à 09:45:37    

la viper a écrit a écrit :

euh ouhai mais là c'est loin d'être important ! ...  
un tableau de 3 doubles ... tout est fixé et le prog tient en 3 ligne .. basta .




Ce n'est pas une question de principe:
en fait tout dépend de la durée de vie des trois variables retournées. Mais à priori, une fonction qui ne retourne que 3 valeurs devrait se passer d'allouer de la mémoire: c'est à l'appelant d'allouer la mémoire si nécessaire, et seulement si ces données s'inscrivent dans une structure plus complexe dont la durée de vie dépasse la fonction ou si il y a de nombreuses cellules (à priori en nombre indéterminé) à manipuler dans la fonction appelante... Sinon effectivement, l'appelant a tout intérer à allouer ces variables dans la pile en les déclarant localement (variables auto)

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed