Probleme de pile e C++

Fermé
lailaloli Messages postés 1 Date d'inscription mercredi 6 mai 2015 Statut Membre Dernière intervention 6 mai 2015 - Modifié par mamiemando le 7/05/2015 à 23:32
mamiemando Messages postés 33595 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 mars 2025 - 7 mai 2015 à 23:56
l'objectif est de déplacer les entiers de P1 vers P2 de facon à avoir das P2 tous les nombres pairs au-dessous des nombres impairs

voici le programme mais le probleme que ca marche pas

#include <iostream>
#include<stdlib.h>
#include<conio.h>

using namespace std;
struct cellulepile {
int valeur;
struct cellulepile *precedent;
};

typedef struct cellulepile cellulepile, *pile;

pile inisialise ( pile p ) {
return p = NULL;
}

pile empiler ( pile p, int val ) {
pile pn;
pn = new ( cellulepile );
pn->valeur = val;

if ( p == NULL ) {
pn->precedent = NULL;
return pn;
} else {
pn->precedent = p;
p = pn;
return p;
}
}

void afficher ( pile p ) {
while ( p != NULL ) {
cout << p->valeur << endl;
p = p->precedent;
}

cout << " NULL \n" << endl;
}

pile traitement ( pile p1 ) {
pile p2 = NULL, p3 = NULL;

while ( p1 != NULL ) {
if ( p1->valeur % 2 == 0 )
empiler ( p2, p1->valeur );
else
empiler ( p3, p1->valeur );

p1 = p1->precedent;
}

while ( p3 != NULL ) {
empiler ( p2, p3->valeur );
p3 = p3->precedent;
}

return p2;
}

pile Construirepile() {
pile p = NULL;
int a, c, rep, val;

do {
do {
cout << "Ajouter un element a la pile Oui=1 Non=0 --> " << endl;
cin >> rep;
} while ( rep != 0 && rep != 1 );

if ( rep == 1 ) {
cout << "donner la valeur a empiler : " << endl;
cin >> a;
p = empiler ( p, val );
}
} while ( rep != 0 );

return p;
}

main() {
pile p1, p2 = NULL, p3 = NULL;
int b;
p1 = new ( cellulepile );
p2 = new ( cellulepile );
p3 = new ( cellulepile );
p1 = Construirepile();
afficher ( p1 );
cout << "la nouvelle pile avec les nombres paires au desous des nombres impaires\n" << endl;
p2 = traitement ( p1 );
afficher ( p2 );
}

1 réponse

mamiemando Messages postés 33595 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 mars 2025 7 834
Modifié par mamiemando le 8/05/2015 à 00:13
Bonjour,

Malheureusement beaucoup de choses ne vont pas dans ce code.

1) Sur la forme :

- la fonction main est sensée retourner un int (0 si tout va bien, une valeur non nulle sinon)
- <conio.h> n'est pas un header standard et n'a aucune raison d'être inclu ici
- <stdlib.h> est un header C et tu devrais inclure à la place ctdlib

2) Sur le fond :

- les objets alloués dynamiquement (new) ne sont jamais désalloués
- la structure du code fait penser à du C codé avec les opérateurs du C++, mais pour autant le design de ce code n'est pas orienté objet : pourquoi pas, mais dans ce cas autant faire du C :-)
- plutôt que de créer ta propre pile, tu pourrais utiliser une classe telle que std::stack
http://www.cplusplus.com/reference/stack/stack/
- ta structure de pile est plutôt une structure de liste chaînée

3) Une solution

Voici comment tu peux écrire beaucoup plus simplement ton programme. Nous allons utiliser le container std::stack fourni par la STL qui est en théorie installé de base sur tout système digne de ce nom :
http://www.cplusplus.com/reference/stack/stack/stack/

#include <stack>    // std::stack
#include <ostream>  // std::ostream
#include <iostream> // std::cout

template <typename T, typename C>
void print_and_empty_stack(
    std::ostream & os,
    std::stack<T, C> & stack
) {
    std::cout << "------------" << std::endl;
    while (!stack.empty()) {
        os << stack.top() << std::endl;
        stack.pop();
    }
}

int main () {
    typedef std::stack<int> my_stack;
    my_stack p1, p2, p3;

    p1.push(1);
    p1.push(4);
    p1.push(3);
    p1.push(2);
    p1.push(7);

    while (!p1.empty()) {
        const int & x = p1.top();
        std::cout << "p1: pop " << x << std::endl;
        p1.pop();

        my_stack & modified_stack = x % 2 ? p2 : p3;
        modified_stack.push(x);
    }

    print_and_empty_stack(std::cout, p2);
    print_and_empty_stack(std::cout, p3);

    return 0;
}


Ce qui donnera :

p1: pop 7
p1: pop 2
p1: pop 3
p1: pop 4
p1: pop 1
------------
1
3
7
------------
4
2


Quelques explications sur le code :

Pour afficher une stack, il faut la dépiler. C'est ici réalisé par la fonction
print_and_empty_stack
. La fonction est template pour ne pas dépendre du type des éléments empilés (type que j'ai noté T) ou du container sous-jacent (type que j'ai noté C).
https://stackoverflow.com/questions/4523178/how-to-print-out-all-elements-in-a-stdstack-or-stdqueue-conveniently

Pour rester générique sur le flux dans lequel on écrit (un fichier, la sortie standard, etc...) on utilise un
std::ostream&
. Pour éviter de recopier la pile qu'on veut afficher en mémoire lors de l'appel de cette fonction, on passe la pile par référence (
std::stack<T,C> &
). On pourrait aussi la passer par recopie si on ne veut pas modifier la pile à afficher (
 std::stack<T,C>
), mais ce sera plus coûteux en mémoire.

template <typename T, typename C>
void print_and_empty_stack(std::ostream & os, std::stack<T, C> stack) {
...
}


Dans le main on remplit la pile p1 avec des valeurs arbitraires mais on pourrait le faire avec la fonction que tu proposais. Ensuite on dépile chaque élément (pop) après l'avoir examiné (top) et mis sur la pile p2 ou p3 (push).

Note qu'ici aussi on joue sur les références (variable
modified_stack
) ce qui permet de parler au travers de la pile dans laquelle on empile. Ceci évite un
if ... else ...
qui contiendait deux fois le même code dans ses deux blocs au nom de la pile près, comme ici :

if (x % 2) {
   p2.push(x);
   std::cout << "size = " << p2.size() << std::endl;
} else {
   p3.push(x);
   std::cout << "size = " << p3.size() << std::endl;
}


Bonne chance
0