IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Comment faire sortir un tableau d'une sous-fonction ?


Sujet :

C

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 2
    Par défaut Comment faire sortir un tableau d'une sous-fonction ?
    Bonjour tout le monde. Je me présente, Roger_bobby, nouveau sur le forum et aussi, apprenti programmeur en C très très très débutant. Donc, si je répète une question précédente, je m'en excuse. Pour tenter d'aléger mon programme, j'ai écrit deux sous-fonctions. Une me permettant de générer des nombres aléatoires et l'autre me permettant de les placer dans un tableau de données. Pour le générateur aléatoire, ça va. Mais je n'arrive pas à retourner comme valeur de sortie mon tableau généré pour l'utiliser dans le main. Est-ce possible de le faire ou devrais-je passer par un chemin dont je n'ai même pas encore idée ? Merci d'avance pour la réponse.

    Voici ma partie de code test qui coince.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    #define TAILLE 10
    #define ORDRE 100
     
     
    int aleatoire(void)
    {
      int w;
     
      w=1+(int) (ORDRE*rand()/(RAND_MAX+1.0));
     
      return w;
     
    }
     
    int editer_tableau(TAILLE)
    {
        int i;
        int tab[TAILLE];
     
     
        for(i=0; i < TAILLE; ++i)
        {
                 tab[i]= aleatoire();
        }      
     
     
        /* Voilà l'endroit ou je sèche */
     
        return tab[];
    }

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 38
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    int editer_tableau(TAILLE) { /* ton code */ }
    Il y a un problème de syntaxe. TAILLE est une macro, que vient-elle faire comme paramètre de ta fonction ? Tu peux la supprimer.
    De plus, le type de retour de editer_tableau n'est pas bon.

    Il y a plusieurs manières de renvoyer un tableau en C. La méthode la plus proche de ton code actuel consiste à renvoyer l'adresse d'un tableau d'entiers, donc un int *.

    Déclare ta fonction comme :
    A partir de là, il y a deux lignes à modifier dans le code de ta fonction.

    D'abord,
    est incorrect. Il faut écrire :
    Cela renvoie l'adresse du tableau tab.

    Ensuite, cela ne marchera pas car tu vas renvoyer l'adresse d'une variable automatique (le tableau tab), dont la durée de vie est logiquement limitée à la durée de l'appel de la fonction.

    Il est donc nécessaire de déclarer le tableau tab comme persistent, et cela s'obtient en déclarant le tableau static :

    static int tab[TAILLE];

    Dans ces conditions, tu pourras renvoyer (et utiliser) l'adresse de tab.

    Voilà. J'espère que j'ai répondu à ton problème.

    Bonne nuit.

  3. #3
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par défaut
    Bonjour,

    Citation Envoyé par Corentor
    Il est donc nécessaire de déclarer le tableau tab comme persistent, et cela s'obtient en déclarant le tableau static :

    static int tab[TAILLE];

    Dans ces conditions, tu pourras renvoyer (et utiliser) l'adresse de tab.
    C'est une solution mais surement pas la meilleur ! A chaque appel de cette fonction, le contenu sera modifié. Le mieux est d'utiliser l'allocation dynamique et de retourner cette adresse (qui sera différentes à chaque appel de la fonction) et suretout ne pas oublier de libérer la mémoire !

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 38
    Par défaut
    Citation Envoyé par gege2061
    C'est une solution mais surement pas la meilleur ! A chaque appel de cette fonction, le contenu sera modifié.
    Je n'ai jamais prétendu que cette solution était la meilleure.
    Les variables statiques peuvent être très utiles, l'allocation dynamique aussi.

    Par contre, j'ai péché en ne précisant pas que mal compris, un code utilisant des variables statiques peut donner des résultats surprenants.

    Par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int *resultat;
    resultat = editer_tableau(); // avec le tableau statique
    editer_tableau();
    // ici, les valeurs du tableau pointé par resultat correspondent au 2e appel, pas au premier !

  5. #5
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par défaut
    Citation Envoyé par Corentor
    Les variables statiques peuvent être très utiles
    Dans ce cas là, j'ai des doutes. Même les fonctions de la bibliothèque standard qui utilisent ce principe (ex : ctime), ont été revues :
    http://www.open-std.org/jtc1/sc22/wg...docs/n1146.pdf
    http://www.open-std.org/jtc1/sc22/wg...docs/n1147.pdf

  6. #6
    Membre Expert Avatar de zooro
    Homme Profil pro
    Développeur Java
    Inscrit en
    Avril 2006
    Messages
    921
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Avril 2006
    Messages : 921
    Par défaut
    Citation Envoyé par Roger_bobby
    Comment faire sortir un tableau d'une sous-fonction ?
    ...
    Voici ma partie de code test qui coince.
    Un bon coup de pied au c** devrait décoincer le tableau...
    Désolé, j'ai pas pu m'en empêcher !

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 38
    Par défaut
    Citation Envoyé par zooro
    Un bon coup de pied au c** devrait décoincer le tableau...


    Citation Envoyé par gege2061
    Même les fonctions de la bibliothèque standard qui utilisent ce principe (ex : ctime), ont été revues
    Oui, le problème des fonctions utilisant ce type de variables est qu'elles ne sont pas réentrantes (gênant dans un contexte multithread pour des fonctions de la bibliothèque standard, mais on s'en fiche ici). Par contre, le fait qu'elles aient des effets de bord du type de mon exemple précédent, est beaucoup plus problématique lorsqu'on débute.

    Je reconnais donc que pour un code d'initiation, ce n'était peut-être pas le bon exemple à donner . gege2061, je te laisse donner la solution avec malloc et free ?

  8. #8
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par défaut
    Citation Envoyé par Corentor
    gege2061, je te laisse donner la solution avec malloc et free ?
    Euh nan, j'ai pas envi Et ça ne m'apporterai pas grand chose, ça serait bien plus interessant si Roger_bobby nous proposait sa solution

    Un peu de lecture :
    Allocation dynamique de mémoire en C
    man malloc


  9. #9
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par Corentor
    Il est donc nécessaire de déclarer le tableau tab comme persistent, et cela s'obtient en déclarant le tableau static :

    static int tab[TAILLE];
    Je suis étonné que tu propose cette solution, tu nous avais habitués à de meilleures réponses...

    C'est une solution, mais tu n'ignores pas que c'est probablement la pire (la fonction n'est plus ré-entrante). Les solutions industrielles sont plutôt :
    • Le passage de l'adresse du premier élément d'un tableau de destination, avec sa taille en nombre d'éléments (comme fgets(), fread() etc.)
    • Le retour de l'adresse d'un bloc alloué dynamiquement (comme et avec malloc()...).

  10. #10
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par gege2061
    Dans ce cas là, j'ai des doutes. Même les fonctions de la bibliothèque standard qui utilisent ce principe (ex : ctime), ont été revues :
    http://www.open-std.org/jtc1/sc22/wg...docs/n1146.pdf
    http://www.open-std.org/jtc1/sc22/wg...docs/n1147.pdf
    Ces textes sont des voeux pieux ! Mais il est exact qu'ils soulignent des défauts de la bibliothèque standard.

    Espérons qu'ils soient un jour pris en comptes, mais j'en doute, le comité, qui était étant en 'maintenance', ayant, a ma connaissance, terminé ses travaux de maintenance avec n1124 considéré comme l'ultime version du langage C.

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 38
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    Je suis étonné que tu propose cette solution, tu nous avais habitués à de meilleures réponses...

    C'est une solution, mais tu n'ignores pas que c'est probablement la pire (la fonction n'est plus ré-entrante). Les solutions industrielles sont plutôt :
    Le passage de l'adresse du premier élément d'un tableau de destination, avec sa taille en nombre d'éléments (comme fgets(), fread() etc.)
    Le retour de l'adresse d'un bloc alloué dynamiquement (comme et avec malloc()...).
    Pour être honnête, je l'ai un peu cherché, et plutôt que de donner d'emblée une "bonne" solution (quel intérêt ?), j'espérais bien susciter quelques réactions .

    Avec tous ses défauts (effets de bord, non réentrance...), le mécanisme des variables statiques existe et ne me semble pas devoir être ignoré, en particulier parce que tant de fonctions de la bibliothèque standard (et indirectement ou non, énormément d'autres codes "industriels") l'utilisent encore (jusqu'à ce que les principes édictés dans les documents mentionnés par gege2061 soient mis en oeuvre). D'où les nombreux pièges dont sont truffées les fonctions de la bibliothèque standard.

    Un exemple que j'affectionne particulièrement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    void weird_function() {
      char *t0, *t1;
      t0 = asctime(localtime(time(0)));
      sleep(10); // on attend un peu
      t1 = asctime(localtime(time(0)));
      printf("%s\n%s\n", t0, t1); // resultat surprenant pour qui n'a jamais entendu parler du mecanisme des variables statiques !
    }
    Il est bon de connaître ces techniques (ce qui signifie les avoir pratiquées), pour pouvoir s'en prémunir.

    Maintenant, je suis d'accord, place aux "vraies solutions".

  12. #12
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 38
    Par défaut
    En attendant, on n'a pas de retour de Roger_bobby .

    Dommage, car à titre d'exercice, il aurait été instructif qu'il tente d'implémenter au moins l'une des deux solutions proposées par ED (cf par exemple les liens sur malloc donnés par gege2061) et de nous retourner sa solution.

  13. #13
    Candidat au Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 2
    Par défaut
    Voici enfin ma tentative de code test. Pour avoir un tableau qui sort, j'en ai un qui sort. Toujours le même à chaque éxécution toutefois. Moi qui voulais un tableau aléatoire. Je suis encore dans le champ. Je n'ai pas utilisé les trucs comme fread() ou malloc() car à vrai dire, je crains ne pas être encore mur pour une utilisation confortable des fonctions de pointeurs. En passant, est-ce que ces fonctions sont standards pour tous les compilateurs. Car, je dois vous avouer que j'ai eu le commentaire que l'utilisation de la fonction getch() n'était pas transportable. En passant, Merci à ED et à gege pour m'avoir trouvé de la lecture pour le weekend.

    P.S. Désolé pour le retard, je programme une ligne l'heure pour l'instant. Je me casse encore la gueule sur les points virgules et sur la tabulation.

    #define TAILLE 10
    #define ORDRE 1000000


    int aleatoire(void)
    {
    int w;
    w=1+(int) (ORDRE*rand()/(RAND_MAX+1.0));
    return w;

    }

    int *editer_tableau(void)
    {
    int i;
    static int tab[TAILLE];

    for(i=0; i < TAILLE; ++i)
    {
    tab[i]= aleatoire();
    }
    return tab;

    }


    int main(void)
    {
    int *resultat;
    int i;

    resultat = editer_tableau();

    for(i=0; i < TAILLE; ++i)
    {
    printf("%i\n", resultat[i]);
    }

    getch();

    return EXIT_SUCCESS;
    }

  14. #14
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 38
    Par défaut
    Citation Envoyé par Roger_bobby
    Pour avoir un tableau qui sort, j'en ai un qui sort. Toujours le même à chaque éxécution toutefois. Moi qui voulais un tableau aléatoire.
    Relis bien la page de rand, c'est normal.
    Il y a juste une petite ligne à rajouter pour corriger ce problème. Le problème est très classique, je te propose une petite recherche sur avant que quelqu'un te donne la solution ici.

    En ce qui concerne la solution par malloc/free (qui au passage appartiennent bien à la bibliothèque standard), elle est très proche de ta solution actuelle, un petit effort ! Voir les faq et les autres posts, par exemple malloc avec strings (les chaînes de caractères sont un cas particulier de tableaux).

  15. #15
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    w=1+(int) (ORDRE*rand()/(RAND_MAX+1.0));
    a un problème: ORDRE*rand() va dépasser la capacité des int sur certaines implémentations et donc le résultat va être bizarre...

  16. #16
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    Ces textes sont des voeux pieux ! Mais il est exact qu'ils soulignent des défauts de la bibliothèque standard.

    Espérons qu'ils soient un jour pris en comptes, mais j'en doute, le comité, qui était étant en 'maintenance', ayant, a ma connaissance, terminé ses travaux de maintenance avec n1124 considéré comme l'ultime version du langage C.
    Pourtant j'ai cru comprendre que les développeurs de lcc étaient dessus

    C'est dommage, c'était plutot bien pensé, pour une fois

  17. #17
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par gege2061
    Pourtant j'ai cru comprendre que les développeurs de lcc étaient dessus

    C'est dommage, c'était plutot bien pensé, pour une fois
    Je suis d'accord (c'est sans doute une réaction aux tives ou moins heureuses de Microsoft avec sa dernière version de Visual C++ pour le C).

    Tout celà reste très hypothétique, et je ne fréquente plus les forums 'officiels' depuis un moment...

Discussions similaires

  1. Comment faire déconnecter les utilisateurs d'une base
    Par ENIT-Info dans le forum Access
    Réponses: 23
    Dernier message: 28/02/2017, 14h57
  2. Réponses: 4
    Dernier message: 21/09/2008, 01h24
  3. [CSS] Comment faire apparaitre l'ascenceur dans une <div&
    Par vampyrx dans le forum Mise en page CSS
    Réponses: 3
    Dernier message: 08/09/2005, 10h06
  4. Réponses: 3
    Dernier message: 23/02/2005, 14h34
  5. comment faire fonctionner l'exe sur une autre machine
    Par brian79 dans le forum C++Builder
    Réponses: 8
    Dernier message: 28/05/2004, 14h00

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo