在ostream函数中使用递归函数作为输出

时间:2016-03-29 18:59:32

标签: c++ recursion

我重载了ostream运算符<<能够打印或写下我的ojbects。在其中一个中,我实际上是在file.txt中编写我的整个结构。结构对象实际上是一个二叉树,为了确保我从中获取每个元素,我需要一个递归函数。这是我尝试做的基本代码。

out << parcour(tree); // recursive function

Parcour假设返回anoter结构,其中我有输入文件中的信息。我的递归函数的内部是这样的:

node* parcour(node* node){
      if (node) {
         parcour(childnode(0));
         parcour(childnode(1));
         return node;
      }
   return nullptr;
}

具有我想要的信息的所有节点都由此函数返回。所以我认为问题是多次返回单个std :: cout实际上并没有工作。我想知道是否有一个带有多个返回函数(一个递归函数)的函数可以作为输出,每次只返回一个返回值。

请不要注意语法合成错误,因为我的代码运行完全,除了我无法解决的单一概念。

编辑:有些人一直要求我提供更多代码,所以基本上我只是复制粘贴下面的原始代码(注意:一切都是法语:S):

这是Arbres.h

 #ifndef ARBRES_H
#define ARBRES_H
#pragma once
#include <iostream>
#include <vector>
using namespace std;

// noeud pour un arbre binaire contenant des informations de type T
template <class T>
class Noeud
{
private:
    T* element; // élément du noeud
    Noeud<T> *parent; // Pointeur vers le parent
    Noeud<T> *gauche; // Pointeur vers le fils gauche
    Noeud<T> *droit; // Pointeur vers le fils droit

public:

//constructeur du noeud
    Noeud()
    {
        element = nullptr;
        parent = nullptr;
        gauche = nullptr;
        droit = nullptr;
    }

// destructeur du noeud
    ~Noeud ()
    {

    }

// retourne l'enfant où "i" represente la position de l'enfant (droit ou gauche)
    Noeud<T> * Enfant(int i) const
    {
        if (i == 0)
            if (!gauche)
                return nullptr;
            else
                return gauche;
        else if (i == 1)
            if (!droit)
                return nullptr;
            else
                return droit;
        else
            return nullptr;
    }

// retourne le parent du noeud
    Noeud<T> *Parent () const
    {
        return parent;
    }

// retourne un pointeur vers l'élément du noeud (les infos)
    T *Element() const
    {
        return element;
    }

// modifie la valeur de l'élément
    void RemplacerElement( T *ele )
    {
        element = ele;
    }

//retourne vrai si le noeud est une feuille
    bool EstUneFeuille () const
    {
        return (!gauche) && (!droit);
    }

//retourne vrai si le noeud est une racine
    bool EstUneRacine () const
    {
        return (!parent);
    }

// détache l'enfant du noeud et retourne un pointeur vers ce noeud
    Noeud<T> *Detacher (Noeud<T>* Enfant)
    {
        Noeud<T> *temp;

        if (Enfant->parent->gauche == Enfant) {
            temp = Enfant->parent->gauche;
            Enfant->parent->gauche = nullptr;
        } else if (Enfant->parent->droit == Enfant) {
            temp = Enfant->parent->droit;
            Enfant->parent->droit = nullptr;
        } else
            return nullptr;
        return temp;
    }

// attache le noeud à l'enfant. Retourne vrai si l'opération est réussie
    bool Attacher(Noeud<T>* nouvelEnfant)
    {
        if (!gauche)
            gauche = nouvelEnfant;
        else if(!droit)
            droit = nouvelEnfant;
        else
            return 0;
        return 1;
    }

// attache les enfants au noeud. Retourne vrai si l'opération est réussie
    bool Attache(Noeud<T>* noeudCourant)
    {
        if (!gauche->parent)
            gauche->parent = noeudCourant;
        else if (!droit->parent)
            droit->parent = noeudCourant;
        else
            return 0;
        return 1;
    }

// Fonction Récursive qui crée un nouveau noeud et le place correctement dans l'arbre
    void CreerNouveauNoeud(istream& in, Noeud<T>* noeudCourant, int val) {
        if (val == 1) {
            if (!noeudCourant->Enfant(0)) {
                noeudCourant->Attacher(new Noeud<T>());
                noeudCourant->Attache(noeudCourant);
                noeudCourant = noeudCourant->Enfant(0);
                noeudCourant->RemplacerElement(new T());
                in >> *(noeudCourant->Element());
                return;
            }
            else if (!noeudCourant->Enfant(1)) {
                noeudCourant->Attacher(new Noeud<T>());
                noeudCourant->Attache(noeudCourant);
                noeudCourant = noeudCourant->Enfant(1);
                noeudCourant->RemplacerElement(new T());
                in >> *(noeudCourant->Element());
                return;
            }
            else {
                cout << "\nERROR: Structure dans le fichier texte incorrect (limite de 2 sous-noeuds par noeud)" << endl;
                return;
            }
        }
        else {
            if (!noeudCourant->Enfant(1)) // S'il existe un noeud à droite s'est qu'on est rendu à ajouter la, sinon on va à gauche
                CreerNouveauNoeud(in, noeudCourant->Enfant(0), val - 1);
            else
                CreerNouveauNoeud(in, noeudCourant->Enfant(1), val - 1);
        }
        return;
    }

// le mot clé "friend" indique que la fonction peut utiliser les membres privés de la classe Noeud
    template<class U>
    friend istream& operator>> (istream& in, Noeud<U>& n);

    template<class U>
    friend ostream& operator<< (ostream& out, Noeud<U>& n);

};

// surcharge de l'opérateur >> pour un noeud
template <class T>
istream& operator>> (istream& in, Noeud<T>& n)
{
    in >> *n.element;
    return in;
}

// surcharge de l'opérateur << pour un noeud
template <class T>
ostream& operator<< (ostream& out, Noeud<T>& n)
{
    out << *n.element;
    return out;
}


// Patron de classe définissant la classe "Arbres"
// contenant des informations de type T
template <class T>
class Arbres
{
// Patron de classe définissant la classe "Arbres"
private:
    vector<Noeud<T>*> racines;
    Noeud<T>* noeudCourant;

public:

//constructeur d'une classe Arbres
    Arbres()
    {
        noeudCourant = nullptr;
    }

// destructeur d'une classe Arbres
    ~Arbres ()
    {
        supprimeArbre();
    }

    // ajoute un arbre de niveau 0 (un noeud) à la liste des racines
    int NouveauNoeud(Noeud<T>* n)
    {
        n->RemplacerElement(new T());
        racines.push_back(n);
        return racines.size() - 1;
    }

    // positionne le noeud courant sur le noeud racine d'indice i
    void SetCourant(int i)
    {
        if(i<racines.size())
            noeudCourant = racines[i];
    }

    // Déplace le noeud courant vers son enfant i
    void NaviguerVersEnfant(int i)
    {
        noeudCourant = noeudCourant->Enfant(i);
    }

    // Déplace le noeud courant vers son parent
    void NaviguerVersParent()
    {
        noeudCourant = noeudCourant->Parent();
    }

    // mets le noeud en position i de la liste racine comme enfant du noeud courant
    void joindreCourant(int i)
    {
        if (!noeudCourant->Enfant(0) || !noeudCourant->Enfant(1)) {
            noeudCourant->Attacher(racines[i]);
            racines[i] = nullptr;
            racines.erase(racines.begin()+i);
        }
        else {
            cout << "/nERROR: Aucun Enfant disponible sur le noeud Courant " << endl;
        }
    }

    // Détache le noeud courant de son parent
    void DetacherCourant()
    {
        if (noeudCourant->Parent()->Enfant(0) == noeudCourant) {
            noeudCourant->Detacher(noeudCourant->Enfant(0));
        }
        else
            noeudCourant->Detacher(noeudCourant->Parent()->Enfant(1));
    }

    // supprime le noeud courant
    void SupprimerCourant()
    {
        supprimeArbre(noeudCourant);
    }

    // retourne la liste des noeuds racines
    const vector<Noeud<T>*>* getRacine() const
    {
        return &racines;
    }

    // retourne le noeud courant
    const Noeud<T>* getCourant() const
    {
        return noeudCourant;
    }

    // fonction récursive qui parcours l'arbre et retourne chacun d'entre eux
    void parcourir(ostream& out, Noeud<T>* racine) {
        if (racine) {
            parcourir(out, racine->Enfant(0));
            parcourir(out, racine->Enfant(1));
            out << *racine;
        }
        return;
    }

    void supprimeArbre(Noeud<T>* racine) { // fonction récursive qui parcours l'arbre et supprime chaque noeud que l'on rencontre
        if (racine) {
            supprimeArbre(racine->Enfant(0));
            supprimeArbre(racine->Enfant(1));
            delete racine->Element();
            delete racine;
        }
        return;
    }

// le mot clé "friend" indique que la fonction peut utiliser les membres privés d'une classe Arbres
    template<class U>
    friend istream& operator>> (istream& in, Arbres<U>& n);

    template<class U>
    friend ostream& operator<< (ostream& out, Arbres<U>& n);

};

// surcharge de l'opérateur >> pour un objet de type Arbres<T>
template <class T>
istream& operator>> (istream& in, Arbres<T>& n)
{
    string buffer;
    while (in >> buffer) {
        int a = count(buffer.begin(), buffer.end(), '-'); // Compte le nombre de tiret pour déterminer le niveau du noeud dans l'arbres
        if (a == 0) {
            n.SetCourant(n.NouveauNoeud(new Noeud<T>()));
            n.noeudCourant->RemplacerElement(new T());
            in >> *(n.noeudCourant);
        }
        else {
            n.noeudCourant->CreerNouveauNoeud(in, n.noeudCourant, (a / 2));
        }
    }
    return in;
}

// surcharge de l'opérateur << pour un objet de type Arbres<T>
template <class T>
ostream& operator<< (ostream& out, Arbres<T>& n) 
{
    for (int x = 0; x < n.racines.size(); x++) {
        n.parcourir(out, n.racines[x]);
    }
    return out;
}

#endif

这是TP2.h

#ifndef TP2_H
#define TP2_H
#pragma once
# include <string>
# include <iostream>
using namespace std;

class Personne
{
    private:
        string nom;
        string prenom;
        int age;
        string metier;
    public:
        Personne();
        Personne(string leNom, string lePrenom, int lAge, string leMetier);
        ~Personne();

        friend istream& operator>> (istream& in, Personne& n);
        friend ostream& operator<< (ostream& out, Personne& n);
};

#endif

这是TP2.cpp

#include "TP2.h"
#include "Arbres.h"
#include <fstream>
#include <algorithm>
using namespace std;

Personne::Personne() {
    return;
}

Personne::Personne(string leNom, string lePrenom, int lAge, string leMetier)
{
    nom = leNom;
    prenom = lePrenom;
    age = lAge;
    metier = leMetier;
    return;
}

Personne::~Personne()
{
    return;
}

istream& operator>> (istream& in, Personne& n)
{
    in >> n.nom >> n.prenom >> n.age >> n.metier;
    return in;
}

ostream& operator<< (ostream& out, Personne& n)
{
    out << "\tNom: " << n.nom << "\n\tPrenom: " << n.prenom << "\n\tAge: " << n.age << "\n\tMetier: " << n.metier << endl;
    return out;
}

int main(){
    ifstream Transaction;
    ifstream Data_input;
    ofstream Data_ouput;
    string transaction_fichier;
    string arbres_fichier;
    char op[1], FILENAME[50]; // Operateur, Nom d'un fichier
    int i; // Indice
    Arbres<Personne>* structure = nullptr;
    cout << "Entrer le nom du fichier transaction: ";
    cin >> transaction_fichier; // IMPORTANT : Le nom du fichier ne doit pas compoter d'espace!
    cout << endl;
    Transaction.open(transaction_fichier);
    if (Transaction.fail())
        cout << "\nError 404 : File not found\n";
    while (!Transaction.eof()) {
        Transaction >> op;
        switch (op[0]) {
        case '*':
            Transaction >> *(*(structure->getRacine()))[structure->NouveauNoeud(new Noeud<Personne>())];
            break;
        case '&':
            Transaction >> i;
            structure->SetCourant(i);
            break;
        case '>':
            Transaction >> i;
            structure->NaviguerVersEnfant(i);
            break;
        case '<':
            Transaction >> i;
            structure->NaviguerVersParent();
            break;
        case '+':
            Transaction >> i;
            structure->joindreCourant(i);
            break;
        case '-':
            structure->DetacherCourant();
            break;
        case '!':
            structure->SupprimerCourant();
            break;
        case '%':
            cout << "Informations des personnes dans les noeuds racines:" << endl;
            for (unsigned int x = 0; x < (*(structure->getRacine())).size(); x++) {
                cout << *(*(structure->getRacine()))[x] << endl;
            }
            break;
        case '?':
            cout << "Informations de la personne dans le noeud courant:" << endl;
            cout << *(structure->getCourant()->Element()) << endl;
            break;
        case '#':
            if (structure) {
                for (unsigned int x = 0; x < (*(structure->getRacine())).size(); x++) {
                    structure->supprimeArbre((*(structure->getRacine()))[x]);
                }
            }
            else {
                Transaction >> FILENAME;
                Data_input.open(FILENAME);
                if (Data_input.fail())
                    cout << "\nError 404 : File not found\n";
                structure = new Arbres<Personne>;
                Data_input >> *structure;
            }
            break;
        case '$':
            Transaction >> FILENAME;
            Data_ouput.open(FILENAME);
            Data_ouput << *structure;
            break;
        default:
            cout << "\nError420 Operator not supported: " << op << endl;
            break;
        }
    }
    // Fin du programme
    return 0;
}

1 个答案:

答案 0 :(得分:3)

整个递归调用无法正常运行。 离开的是从您的顶级parcour()调用返回的 return 值。由于内部递归调用似乎没有对返回值做出贡献,因此调用是否发生或者只是被跳过并不重要。

要实现您所描述的意图,您需要将输出对象传递给parcour()并在该函数中输出您需要的任何内容。