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 :

Je ne récupère pas mes tableaux en sortie de fonction récursive


Sujet :

C++

  1. #1
    Membre éclairé Avatar de ypcman
    Homme Profil pro
    Retraité codeur !
    Inscrit en
    Janvier 2011
    Messages
    595
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Retraité codeur !
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2011
    Messages : 595
    Points : 879
    Points
    879
    Par défaut Je ne récupère pas mes tableaux en sortie de fonction récursive
    Bonjour.

    A partir des valeurs d'un tableau initial d'entiers crée par une fonction generationTableau, je veux créer 2 tableaux comprenant respectivement les valeurs inférieures et supérieures à une valeur donnée. Pour cela, je veux utiliser une fonction récursive que j'appelle separation.
    Or, bien qu'utilisant les realloc pour conserver en mémoire mes tableaux après la fin de l'appel à la fonction, je ne retrouve plus les valeurs ensuite. Pourtant, ces valeurs existent à chaque appel récursif puisque je peux faire afficher l'indice 0 de l'un d'eux ...
    Voici mon petit code-source :
    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    #include <iostream>
    #include <cstdlib>
     
    int* generationTableau(int nbValeursAGenerer, int min, int max, int *tab,
    		int tailleTab) {
     
    	if (nbValeursAGenerer == 0) {
    		return tab;
    	} else {
    		int tailleCourante = tailleTab - nbValeursAGenerer + 1;
    		tab = (int*) realloc(tab, tailleCourante * sizeof(int));
    		tab[tailleCourante - 1] = rand() % max + min;
     
    		return generationTableau(nbValeursAGenerer - 1, min, max, tab,
    				tailleTab);
    	}
    }
     
    void separation(int nbValeursRestantATester, int p, int *T, int tailleT,
    		int *Tinf, int *tailleTinf, int *Tsup, int *tailleTsup) {
     
    	if (nbValeursRestantATester > 0) {
    		int indice = tailleT - nbValeursRestantATester;
    		std::cout << "nbValeursRestantATester : " << nbValeursRestantATester
    				<< std::endl;
    		std::cout << "T[" << indice << "] = " << T[indice] << std::endl;
    		if (T[indice] > p) {
    			*tailleTsup += 1;
    			Tsup = (int*) realloc(Tsup, *tailleTsup * sizeof(int));
    			Tsup[*tailleTsup - 1] = T[indice];
    			std::cout << "Tsup[" << *tailleTsup - 1 << "] = "
    					<< Tsup[*tailleTsup - 1] << std::endl;
    			std::cout << "Tsup[0] = " << Tsup[0] << std::endl;
    		} else if (T[indice] < p) {
    			*tailleTinf += 1;
    			Tinf = (int*) realloc(Tinf, *tailleTinf * sizeof(int));
    			Tinf[*tailleTinf - 1] = T[indice];
    			std::cout << "Tinf[" << *tailleTinf - 1 << "] = " << T[indice]
    					<< std::endl;
    		}
    		nbValeursRestantATester -= 1;
    		separation(nbValeursRestantATester, p, T, tailleT, Tinf, tailleTinf,
    				Tsup, tailleTsup);
    	}
    }
     
    void afficherTableau(int nbValeursAAfficher, int *tab, int tailleTab) {
    	if (nbValeursAAfficher > 0) {
    		std::cout << tab[tailleTab - nbValeursAAfficher] << std::endl;
    		afficherTableau(nbValeursAAfficher - 1, tab, tailleTab);
    	}
    }
     
    int main() {
     
    	int *tab = NULL;
    	int tailleTab = 20;
    	int p = 30;
     
    	int *Tinf = NULL;
    	int *Tsup = NULL;
    	int tailleTinf = 0, tailleTsup = 0;
     
    	std::cout << " ---- " << std::endl;
    	tab = generationTableau(tailleTab, 0, 100, tab, tailleTab);
    	afficherTableau(tailleTab, tab, tailleTab);
    	std::cout << " ---- " << std::endl;
    	separation(tailleTab, p, tab, tailleTab, Tinf, &tailleTinf, Tsup,
    			&tailleTsup);
     
    	std::cout << "tailleTinf  = " << tailleTinf << std::endl;
    	std::cout << "Tinf[0] = " << Tinf[0] << std::endl;
    	// afficherTableau(tailleTinf, Tinf, tailleTinf);
    	// std::cout << "Tsup " << *tailleTsup << std::endl;
    	// afficherTableau(*tailleTsup, Tsup, *tailleTsup);
     
    	return 0;
    }
    Je me plante ou ?
    Participez vous aussi !
    Message utile
    Discussion résolue

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Tu te trompes soit de forum soit de language parce que les tableaux en C++ ça s'apelle std::vector et ce que tu montres c'est du gros code C qui semble moyen avec std::cout pour remplacer printf.
    Et puis realloc sur un truc non alloué, c'est dans les premières lignes de la doc que c'est pas possible.
    Reallocates the given area of memory. It must be previously allocated by malloc(), calloc() or realloc() and not yet freed with a call to free or realloc. Otherwise, the results are undefined.
    FAUX, my bad, la doc contredit et indique en effet que c'est l'équivalent de malloc plus bas...
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Aie: Aie:

    Tu es entrain de coder en C++ avec des realloc qui techniquement n'existe pas ?
    Tu es entrain d'initialiser 1 tableau en récursif au lieu d'1 bonne boucle for ?
    À chaque recursion, tu réalloues ton tableau sans libérer le tableau d'avant [sans parler de la perte des données] ?
    Tu alloues 1 tableau d'entier (*) en le mettant dans 1 pointeur int* [sans parler du test de la validité du pointeur alloué] ?

    Tu es entrain de coder en C ?

    J'appelle 1 ami ce n'est pas possible , il faut revoir tes cours de C


    * donc int** parce que c'est 1 paramètre et on veut garder l'adresse

  4. #4
    Membre éclairé Avatar de ypcman
    Homme Profil pro
    Retraité codeur !
    Inscrit en
    Janvier 2011
    Messages
    595
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Retraité codeur !
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2011
    Messages : 595
    Points : 879
    Points
    879
    Par défaut
    Merci pour vos réponses.
    Effectivement, il s'agit de code C surcouché en C++ avec contraintes imposées de non emploi de std::array et std::vector et emploi de malloc/realloc dans des fonctions récursives.
    @Bousk, je n'ai pas trouvé le moyen de supprimer moi-même cette discussion. Merci de le faire si votre statut de modérateur le permet.
    Pour info, même si ce n'est pas "propre", realloc est tout à fait employable à la place de malloc :
    In case that ptr is a null pointer, the function realloc behaves like malloc, assigning a new block of size bytes and returning a pointer to its beginning.
    . La fonction genererTableau() utilise cette facilité.
    La solution consistait à faire retourner par la récursive un pointeur vers un tableau contenant les adresses des 2 tableaux générés ... bref, du pur C
    Participez vous aussi !
    Message utile
    Discussion résolue

  5. #5
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut correction de l'indentation
    Salut,
    Citation Envoyé par ypcman Voir le message
    Merci pour vos réponses.
    Effectivement, il s'agit de code C surcouché en C++ avec contraintes imposées de non emploi de std::array et std::vector et emploi de malloc/realloc dans des fonctions récursives.
    Mais d'où peuvent donc venir de telle contraintes aussi idiotes !?!?

    Soit, tu travailles en C, soit tu travailles en C++, mais il faut choisir!

    Ces contraintes reviennent à t'obliger à parler en français, mais uniquement avec les mots, la grammaire et les particularités propres au latin de Jules Cesar, sous prétexte que le français dérive du latin! Cela n'a absolument aucun sens!

    Oui, nous sommes bien d'accord: à la base, C++ a été nommé C with classes, parce que Stroutrup lui-même voulait juste ajouter une surcouche au C.

    Cependant, cela fait plus de trente ans que C++ est devenu un langage à part entière, au même titre que C# ou Python ou Java (qui n'existaient pas encore), avec ses propres capacités, sa propre syntaxe et même son propre standard (et son propre groupe dédié à la mise au point du standard au niveau ISO).

    Y a-t-il au moins la moindre raison à la non utilisation de std::vector ou de std::array

    Celui qui t'as donné de telles contraintes est-il au courant que std::array ne font au final absolument rien de plus que ce qu'il te demande de faire (moins bien que ce que ne font ces deux classes) à la main

    Et puis, surtout, la contrainte d'utiliser une fonction récursive n'a absolument aucun sens, la technique ne devant dans l'idéal être utilisée que lorsque les boucles habituelles montrent leurs limites (dans les tours de Hanoï, par exemple)

    Ce que cette personne devrait arriver à se mettre en tête, c'est que si C++ est effectivement capable de comprendre et de compiler du C, ce n'est désormais (et depuis bien longtemps, en fait) que pour faciliter l'intégration de bibliothèques qui auraient été développées en C, mais que du code purement C n'a même plus rien à faire dans un projet C++.

    Voici à quoi pourrait ressembler le code si on voulait le faire en vrai C++:
    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    /* NOTA: comme je ne savais pas si tu veux avoir un résultat trié ou non
     * j'ai fait une fonction avec un tri incorporé (mais gardant le tableau original 
     * "en l'état") et une fonction sans tri
     *
     * les deux fonctions renvoient une pair de tableaux, dont la valeur la plus proche de
     * limit tout en étant égale ou supérieure correspond au premier élément du  deuxième tableau
     */
     
    #include <vector>
    #include <algorithm>
    #include <iostream>
    std::pair<std::vector<int>, std::vector<int>> genSorted(std::vector<int> const & datas, int limit){
        std::vector<int> copy{datas};
        std::sort(std::begin(copy),std::end(copy));
     
        auto found =std::find_if(std::begin(copy), std::end(copy), [&](int i){return i>= limit;});
        std::vector<int> less{std::begin(copy), found};
        std::vector<int> more(found,std::end(copy));
        return std::make_pair(less,more);
    }
    std::pair<std::vector<int>, std::vector<int>> genNoSort(std::vector<int> const & data, int limit){
        std::vector<int> less;
        std::vector<int> more;
        for(auto it: data){
            if(it<limit)
                less.push_back(it);
            else
                more.push_back(it);
        }
        return std::make_pair(less, more);
    }
     
    int main(){
        std::vector<int> datas{3,7,5,9,42,37,6, 56,54};
        {
            auto[less, more]=genSorted(datas, 10 );
            std::cout<<"results for less when sorted:\n";
            for(auto it: less)
            std::cout<<it<<" ";
            std::cout<<"\n";
        }
        {
            auto [less, more] = genNoSort(datas, 10);
            std::cout<<"results for more when not sorted:\n";
            for(auto it: more)
                std::cout<<it<<" ";
        }
        return 0;
    }
    Pourquoi devrait-on se casser la tête à gérer la mémoire à la main, alors que la classe std::vector le fait gentiment pour nous
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #6
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Bonjour,

    Il faudrait que tu nous donnes tes contraintes, par exemple:
    - c'est du C++, mais il ne faut rien utiliser du C++.
    - il faut utiliser la récursivité de partout même si ç'en devient idiot.
    - il faut faire tout plein d'allocations et de réallocations
    - il faut brouiller les pistes pour que ça soit illisible.
    Est-ce bien cela?

    En fait ce que tu veux faire, ça s'appelle une partition et en C++ ça s'écrit en une ligne et un peu plus en C.
    En C:
    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
        int  tab[] = {3, 7, 5, 9, 42, 37, 6, 56, 54};
        int  value = 10;
        const int  size = sizeof tab/sizeof*tab;
     
        int  i = 0, j = size - 1;
        for (;;) {
            // reach next unordered point
            while ( i < size  &&  tab[i] < value )
                ++i;
            while ( j >= 0  &&  tab[j] >= value )
                --j;
            if ( i >= j )
                break;  // all is partitionned
            // else swap needed
            int tmp = tab[i];  tab[i]=tab[j];  tab[j] = tmp;
            ++i;
            --j;
        }
        // items before tab[i] are the lowests after are the highests, display the result
        printf("low values : ");
        for ( int a = 0 ;  a < i ; ++a )
            printf("%d ", tab[a] );
        printf( "\nhigh values : " );
        for ( int a = i; a < size; ++a )
            printf( "%d ", tab[a] );
    En C++:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        std::vector<int>  tab{3, 7, 5, 9, 42, 37, 6, 56, 54};
        int  value = 10;
        // do partition
        auto  middle = std::partition( begin(tab), end(tab), [value](int x){return x<value;} );
        // then display 
        std::cout << "low values : ";
        std::copy( begin(tab), middle, std::ostream_iterator<double>( std::cout, " " ) );
        std::cout << "\nhigh values : ";
        std::copy( middle, end(tab), std::ostream_iterator<double>( std::cout, " " ) );

  7. #7
    Membre éclairé Avatar de ypcman
    Homme Profil pro
    Retraité codeur !
    Inscrit en
    Janvier 2011
    Messages
    595
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Retraité codeur !
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2011
    Messages : 595
    Points : 879
    Points
    879
    Par défaut
    Merci pour tous ces codes sources brillants et exploitant toutes les ressources du C++ moderne (plus le code de dalfab en C).
    Je vais mettre du temps à les comprendre mais c'est très formateur.
    Participez vous aussi !
    Message utile
    Discussion résolue

  8. #8
    Membre chevronné Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 043
    Points : 2 234
    Points
    2 234
    Par défaut
    Contrairement à ce qui à été dit ( et que j'ai lu ), en c++ (depuis c++11) les tableaux à taille fixe sur la pile sont std::array et non pas std::vector, post c++11 (c++98) c'était les tableaux à la C. Donc non les tableaux à la C ne sont pas que du C, mais bonjour la gestion des constructeurs, copies, assignations etc... En fonction du type du tableau... ( Nota: C++ utilise les type traitss pour gérer ca)

    Par contre, si ton tableau à une taille non fixe ou/et qui n'est pas connue à la compilation dans ce cad, plutôt que d'utiliser malloc/free/realloc tu peux/doit utiliser std::vector qui encapsule malloc/free/realloc et la gestions des constructeurs, copies, assignations pour toi en fonction du type.
    Homer J. Simpson


+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Débutant] Pas de données de sortie à ma fonction
    Par DocDjul dans le forum MATLAB
    Réponses: 10
    Dernier message: 04/07/2012, 14h40
  2. class="none" ne s'applique pas à mes tableaux ?
    Par mikael2235 dans le forum Mise en page CSS
    Réponses: 6
    Dernier message: 08/08/2010, 18h59
  3. MemoryStream, je ne récupère pas mes données
    Par rvdth dans le forum Windows Forms
    Réponses: 2
    Dernier message: 24/05/2009, 13h05

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