OVH Cloud OVH Cloud

[Basique] Passage/modification de tableau dans une fonction

20 réponses
Avatar
Morgan Sangeux
Bonjour,
Malgres mes lectures et recherche sur le langage C je ne comprend pas le
fonctionnement du passage/modification d'un tableau dans une focntion.
Voici un exemple ci-après de ce que je voudrais faire et qui ne marche pas.

"
#include <stdio.h>
#include <stdlib.h>

int test(double *);

int test(double * Coord, int taille)
{ int i;
Coord = (double *)realloc(Coord,taille * 3 * sizeof(double));
for(i=3;i<6;++i) {Coord[i]=2.0;printf("Coord[%d] =
%f\n",i+1,Coord[i]);}
return 0;
}

int main()
{
int taille, i,j, retour;
double * Coord;

taille =1;
Coord = (double *)malloc(3*sizeof(double));
for (i =0 ;i<3;++i) {Coord[i]=1.0;printf("Coord[%d] =
%f\n",i+1,Coord[i]);}
taille++;
retour = test(Coord,taille);
for(i = 3 ;i<6;++i) printf("Coord[%d] = %f\n",i+1,Coord[i]);
return 0;
}
"
la fonction modifie bien la taille de mon tableau Coord mais pas le
contenu,pourquoi?

10 réponses

1 2
Avatar
Morgan Sangeux
Morgan Sangeux writes:



Devrait oui... Seulement l'exterieur ne connait pas la nouvelle valeur de
Coord, il ne connait que l'ancienne. Il faut donc qu'il sache où est le
tableau maintenant.
Pour que ca fonctionne, il faut passer un pointeur sur Coord :
int test(double** Coord, int taille)
{
int i;
taille++;
*Coord = (double *)realloc(*Coord,taille * 3 * sizeof(double));
...
Avec cela ca devrait fonctionner un peu mieux.



ça fonctionne oui mais le comportement est 'étrange'.
Lorsque j'utilise ça:

int test(double **Coord, int taille)
{ int i;
double *bis;

*Coord = (double *)realloc(*Coord,6 * sizeof(double));
bis = *Coord;
for(i=0;i<6;++i) {bis[i] = 2.0;}

pas de probleme ça roule (dans le principal aussi).

Par contre si je fais ça:

int test(double **Coord, int taille)
{ int i;
double *bis;

*Coord = (double *)realloc(*Coord,6 * sizeof(double));
for(i=0;i<6;++i) {*Coord[i] = 2.0;}
Je me fait ejecter sauvagement.

Moi pas comprendre.



*Coord[i] se lit *(Coord[i]) pas (*Coord)[i]

A+

Les deux m'ejecte de la même façon.




Avatar
Morgan Sangeux
[...]

*Coord = (double *)realloc(*Coord,6 * sizeof(double));
for(i=0;i<6;++i) {*Coord[i] = 2.0;}


Pas le temps de vérifier, mais faites peut-être (*Coord)[i].

And the winner is mister maurette. Merci beaucoup pour votre aide.



Avatar
Emmanuel Delahaye
Malgres mes lectures et recherche sur le langage C je ne comprend pas le
fonctionnement du passage/modification d'un tableau dans une focntion.
Voici un exemple ci-après de ce que je voudrais faire et qui ne marche pas.

"
#include <stdio.h>
#include <stdlib.h>

int test(double *);

int test(double * Coord, int taille)


Pourquoi définir un prototype séparé si il n'est pas conforme à la
définition ? Autant ne rien faire...

{ int i;
Coord = (double *)realloc(Coord,taille * 3 * sizeof(double));


Transtypage inutile. Syntaxe compliquée. C'est quoi ce 3 ?

http://mapage.noos.fr/emdel/notes.htm#malloc

realloc() peut échouer. Il manque un test.

http://mapage.noos.fr/emdel/notes.htm#realloc

for(i=3;i<6;++i) {Coord[i]=2.0;printf("Coord[%d] =


C'est quoi ce 6 ?

%fn",i+1,Coord[i]);}
return 0;
}

int main()
{
int taille, i,j, retour;


j n'est pas utilisé.

double * Coord;

taille =1;
Coord = (double *)malloc(3*sizeof(double));


Si taille vaut 1, c'est quoi ce 3 ? Pourquoi c'est pas 'taille' ? C'est
drôlement tordu comme raisonnement...

for (i =0 ;i<3;++i) {Coord[i]=1.0;printf("Coord[%d] =
%fn",i+1,Coord[i]);}
taille++;


Maintenant taille vaut 2...

retour = test(Coord,taille);


Le tableau faisait 3, maintenant il va faire 2 ?

for(i = 3 ;i<6;++i) printf("Coord[%d] = %fn",i+1,Coord[i]);


Je te conseille de commencer par maîtriser les tableaux et les pointeurs
avant d'aller plus loin. Tu cherches à mettre en oeuvre trop de notions
non maîtrisées en même temps. Tu vas trop vite.

1 - tableau fixe
2 - tableau dynamique (malloc())
3 - agrandissement d'un tableau dynamique (realloc())
4 - fonction

return 0;
}
"
la fonction modifie bien la taille de mon tableau Coord mais pas le
contenu,pourquoi?


De plus il y a une fuite mémoire :

FRMWRK.DBG_SYSALLOC=1
SYSALLOC Overload (85 rec)
SYSALLOC Successful initialization: 85 records available
Coord[1] = 1.000000
Coord[2] = 1.000000
Coord[3] = 1.000000
Coord[4] = 2.000000
Coord[5] = 2.000000
Coord[6] = 2.000000
Coord[4] = 2.000000
Coord[5] = 2.000000
Coord[6] = 2.000000
SYSALLOC minB94967295 maxB94967295 delta=0
SYSALLOC Err: Not-matched list:
SYSALLOC Bloc 003D24E8 (48 bytes) realloc'ed at line 6 of 'main.c' not freed
SYSALLOC Released Memory
FRMWRK.Terminated

Press ENTER to continue.

Si tu veux qu'une fonction modifie une variable extérieure, il faut soit
passer l'adresse de cette variable à la fonction :

int x = 1;

/* x vaut 1 */
inc (&x);
/* x vaut 2 */

avec

void inc (int *pi)
{
(*p)++;
}

soit retourner la nouvelle valeur :

int x = 1;

/* x vaut 1 */
x = inc (x);
/* x vaut 2 */

avec

int inc (int i)
{
return i + 1;
}

Maintenant, il suffit d'extrapoler ce principe à ton application.

--
C is a sharp tool

Avatar
Morgan Sangeux
snip

Maintenant, il suffit d'extrapoler ce principe à ton application.

Merci mais pb resolu.


Avatar
Harpo
Morgan Sangeux wrote:

snip

Maintenant, il suffit d'extrapoler ce principe à ton application.

Merci mais pb resolu.



Les pb résolus sont plus rares que les mauvaises test-suites.

--
http://harpo.free.fr/


Avatar
Emmanuel Delahaye
snip

Maintenant, il suffit d'extrapoler ce principe à ton application.

Merci mais pb resolu.



On a pas vu ton code qui le prouve...

--
C is a sharp tool


Avatar
Stephane Legras-Decussy
"Morgan Sangeux" a écrit dans le message de news:
dtfo53$so8$
Merci mais pb resolu.


si tu ne dois apprendre qu'une chose de ce
fil, c'est qu'un problème est rarement résolu
même si ça marche.

corrige tous les points qu'a cité Emmanuel.

Avatar
Morgan Sangeux

Merci mais pb resolu.



On a pas vu ton code qui le prouve...

Homme de peu de foi :) !


Enfin disons que ça fait ce que je veux... à peu près. (je sens que je
vais me faire tancer!)

#include <stdio.h>
#include <stdlib.h>

int test(double**, int);

int test(double** Coord, int taille)
{
int i;
taille++;

*Coord = (double *)realloc(*Coord,taille * 3 * sizeof(double));
if (*Coord == NULL) return 0;

for(i=3;i<6;++i) {(*Coord)[i]=2.0;printf("Fonction / Coord[%d] =
%fn",i+1,(*Coord)[i]);}
return taille;
}

int main()
{
int taille, i;
double* Coord = NULL;

taille = 1;
Coord = (double *)malloc(3*sizeof(double));
for (i =0 ;i<3;++i) {Coord[i]=1.0;printf("Main 1 / Coord[%d] =
%fn",i+1,Coord[i]);}

taille = test(&Coord,taille);
if (taille == 0) return 1;

for(i = 3 ;i<6;++i) printf("Main 2 / Coord[%d] = %fn",i+1,Coord[i]);

/* free? */
return 0;
}

Alors effectivement j'ai toujours une 'fuite mémoire', genre je lui
demande Coord[18] il me le donne !? Le malloc et realloc doivent etre
comme ça parce que j'utilise un compilateur C++ (et c'est pas bien mais
c'est comme ça, si vous avez un - ide - qui fait que du C gratuit je
suis preneur). Le 3 dans malloc et realloc c'est parce que j'en ai
envie, et accessoirement se sont les (Coord[])onnées de mes points dans
l'espace, test visant à être une fonction de lecture de fichier
comportant des points.


Avatar
Emmanuel Delahaye
On a pas vu ton code qui le prouve...

Homme de peu de foi :) !


Enfin disons que ça fait ce que je veux... à peu près. (je sens que je
vais me faire tancer!)

#include <stdio.h>
#include <stdlib.h>

int test(double**, int);


Inutile

int test(double** Coord, int taille)
{
int i;
taille++;

*Coord = (double *)realloc(*Coord,taille * 3 * sizeof(double));


J'ai toujours pas compris la logique de ce taille, de ce 3...

Quand aux casts, on te l'a déjà dit, ils sont inutiles...

if (*Coord == NULL) return 0;

for(i=3;i<6;++i) {(*Coord)[i]=2.0;printf("Fonction / Coord[%d] =
%fn",i+1,(*Coord)[i]);}
return taille;
}

int main()
{
int taille, i;
double* Coord = NULL;

taille = 1;
Coord = (double *)malloc(3*sizeof(double));
for (i =0 ;i<3;++i) {Coord[i]=1.0;printf("Main 1 / Coord[%d] =
%fn",i+1,Coord[i]);}

taille = test(&Coord,taille);
if (taille == 0) return 1;

for(i = 3 ;i<6;++i) printf("Main 2 / Coord[%d] = %fn",i+1,Coord[i]);

/* free? */


Ben oui, ça mord pas...

return 0;
}


Désolé pour le refactoring, mais là, je ne vois pas d'autre moyen...

#include <stdio.h>
#include <stdlib.h>

static int grow (double** const ppCoord
, int const taille
, int const delta
, double value)
{
int new_size = taille + delta;

if (ppCoord != NULL)
{
double *tmp = realloc (*ppCoord, new_size * sizeof * tmp);

if (tmp != NULL)
{
int i;

for (i = taille;i < new_size;++i)
{
tmp[i] = value + i;
}

*ppCoord = tmp;
}
else
{
new_size = 0;
}
}
return new_size ;
}

static void fill(double*Coord, int taille, double value)
{
int i;
for (i = 0 ;i < taille; i++)
{
Coord[i] = value + i;
}
}

static void display(double const *const Coord, int const taille)
{
int i;
for (i = 0 ;i < taille; i++)
{
printf("Coord[%d] = %fn", i + 1, Coord[i]);
}
printf ("n");
}

int main(void)
{
int ret = EXIT_SUCCESS;
int taille = 2;
double* Coord = malloc(taille * sizeof * Coord);

fill(Coord, taille, 10.0);
display(Coord, taille);

taille = grow(&Coord, taille, 3, 20.0);
if (taille == 0)
{
ret = EXIT_FAILURE;
}
else
{
display(Coord, taille);
}

free(Coord), Coord = NULL;
return ret;
}


Le malloc et realloc doivent etre
comme ça parce que j'utilise un compilateur C++


Caÿ mal !

(et c'est pas bien mais
c'est comme ça, si vous avez un - ide - qui fait que du C gratuit je
suis preneur).


Code::Blocks (Windows, Linux...)

Le 3 dans malloc et realloc c'est parce que j'en ai
envie, et accessoirement se sont les (Coord[])onnées de mes points dans
l'espace, test visant à être une fonction de lecture de fichier
comportant des points.


Alors définis un tableau de structure, ce sera plus sûr..

struct coord
{
double x;
double y;
double z;
};

...
{
struct coord* Coord = malloc(taille * sizeof * Coord);
...
}

Et remarque au passage la quasi-absence de maintenance... Seul le type a
été modifié.

--
C is a sharp tool


Avatar
Morgan Sangeux


Désolé pour le refactoring,


faut pas, et merci pour ça.

mais là, je ne vois pas d'autre moyen...


Caÿ mal !

(et c'est pas bien mais c'est comme ça, si vous avez un - ide - qui
fait que du C gratuit je suis preneur).



Code::Blocks (Windows, Linux...)
En fait Dev-c++ fait la même chose que celui-ci, c'est moi qui ne sait

pas m'en servir alors toute mes excuses.


Alors définis un tableau de structure, ce sera plus sûr..
Ah oui, pas bête :) ! Je sais pas pourquoi c'est plus sûr mais en tout

cas c'est nettement plus élegant.

struct coord
{
double x;
double y;
double z;
};

...
{
struct coord* Coord = malloc(taille * sizeof * Coord);
...
}




1 2