Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Problème d'écriture avec ofstream

20 réponses
Avatar
Marc G
bonjour,
j'ai un problème (a priori simple mais je ne trouve pas la solution :-))

j'ai la fonction

std::ofstream& html_header(std::ofstream& flux)
{
flux<<"<html>\n<head>\n</head>\n<body>\n";
return flux;
}

ensuite quand je veux l'appeler :

std::ofstream fout("test.html",std::ios::out);
html_header(fout); // là ça marche
fout << html_header; // là j'ai des chiffres dans le fichier....
!

est-ce que quelqu'un sait pourquoi ?
Merci
Marc

10 réponses

1 2
Avatar
GHU
en ayant encore ouvert un seul oeil, je suppose que tu écris dans le fichier
l'adresse de la fonction

"Marc G" a écrit dans le message de news:
4536fc7d$0$25920$

bonjour,
j'ai un problème (a priori simple mais je ne trouve pas la solution :-))

j'ai la fonction

std::ofstream& html_header(std::ofstream& flux)
{
flux<<"<html>n<head>n</head>n<body>n";
return flux;
}

ensuite quand je veux l'appeler :

std::ofstream fout("test.html",std::ios::out);
html_header(fout); // là ça marche
fout << html_header; // là j'ai des chiffres dans le
fichier.... !

est-ce que quelqu'un sait pourquoi ?
Merci
Marc




Avatar
Marc G
"GHU" a écrit dans le message de news:
eh76fi$oht$

en ayant encore ouvert un seul oeil, je suppose que tu écris dans le
fichier l'adresse de la fonction


c'est probable,
mais je croyais que les classes de flux de la stl avaient un opérateur
d'insertion surchargé
std::ofstream& operator<<(std::ofstream& (*f)(std::ofstream&))
{ return (*f)(*this);}
ce qui par exemple permet d'écrire
fout<<endl; // là ça marche....
alors pourquoi pas avec ma fonction ?

Avatar
Sylvain Togni
Marc G wrote:
en ayant encore ouvert un seul oeil, je suppose que tu écris dans le
fichier l'adresse de la fonction


c'est probable,
mais je croyais que les classes de flux de la stl avaient un opérateur
d'insertion surchargé
std::ofstream& operator<<(std::ofstream& (*f)(std::ofstream&))
{ return (*f)(*this);}
ce qui par exemple permet d'écrire
fout<<endl; // là ça marche....
alors pourquoi pas avec ma fonction ?


La fonction doit utiliser std::ostream, pas std::ofstream.

(De manière générale, il est très rare qu'une fonction ait
besoin d'un argument de type std::ofstream).

--
Sylvain Togni


Avatar
Marc G
La fonction doit utiliser std::ostream, pas std::ofstream.
merci, ça marche impéccable


j'avais fini par écrire
class my_output : public std::ostringstream { /* par exemple */
public :
virtual my_output& operator<<(my_output& (*f)(my_output&))
{
return (*f)(*this);
}
};
my_output& html_header(my_output& flux)
{
flux << "<html>n<head>n</head>n<body>n";
return flux;
}
et là ça marchait,
sans même réfléchir à quel niveau était défini l'opérateur surchargé....
j'ai des progrès à faire...
Merci encore
Marc

Avatar
Marc G
une autre question, si ce n'est pas abuser...

j'ai une classe du style

class MonObjet {
//...
ostream& display(ostream&);
friend ostream& operator<<(ostream&,const MonObjet &);
};
ostream& operator<<(ostream&,const MonObjet &) { }

pour un flux, je peux écrire

MonObjet un_objet;
flux<<un_objet;

mais je voudrais écrire plutôt un truc du genre
flux<<un_objet.display;
(je peux avoir plusieurs méthodes d'affichage par exemple)
je crois que un_objet.display est malheureusement du type std::ostream&
(MonObjet::*)(std::ostream&), où un truc du genre :-)) (je doute de ce que
j'écris parfois)
Marc
Avatar
Sylvain Togni
Marc G wrote:
j'ai une classe du style

class MonObjet {
//...
ostream& display(ostream&);
friend ostream& operator<<(ostream&,const MonObjet &);
};
ostream& operator<<(ostream&,const MonObjet &) { }

pour un flux, je peux écrire

MonObjet un_objet;
flux<<un_objet;

mais je voudrais écrire plutôt un truc du genre
flux<<un_objet.display;
(je peux avoir plusieurs méthodes d'affichage par exemple)
je crois que un_objet.display est malheureusement du type std::ostream&
(MonObjet::*)(std::ostream&), où un truc du genre :-)) (je doute de ce que
j'écris parfois)


Oui, cela ne fonctionnera pas comme ça. Il y a une
possibilité de changer l'état du flux à l'aide d'un
manipulateur pour qu'ensuite il n'affiche pas la même
chose, je crois, mais je ne sais pas exactement comment
il faut faire.

Une autre solution est d'utiliser des classes différentes
pour chaque méthode d'affichage :

#include <iostream>
#include <string>

struct MonObjet
{
MonObjet(int i0, std::string const& s0) : i(i0), s(s0) {}

int i;
std::string s;
};

struct UneVueSurMonObjet
{
UneVueSurMonObjet(MonObjet const& o0) : o(o0) {}

friend std::ostream& operator<<(std::ostream& dst,
UneVueSurMonObjet const& v)
{
return dst << v.o.i;
}

MonObjet const& o;
};

struct UneAutreVueSurMonObjet
{
UneAutreVueSurMonObjet(MonObjet const& o0) : o(o0) {}

friend std::ostream& operator<<(std::ostream& dst,
UneAutreVueSurMonObjet const& v)
{
return dst << v.o.s;
}

MonObjet const& o;
};

int
main()
{
MonObjet monObjet(4, "abcd");
std::cout << UneVueSurMonObjet(monObjet) << 'n';
std::cout << UneAutreVueSurMonObjet(monObjet) << 'n';
return 0;
}

--
Sylvain Togni

Avatar
kanze
Marc G wrote:
une autre question, si ce n'est pas abuser...

j'ai une classe du style

class MonObjet {
//...
ostream& display(ostream&);
friend ostream& operator<<(ostream&,const MonObjet &);
};
ostream& operator<<(ostream&,const MonObjet &) { }

pour un flux, je peux écrire

MonObjet un_objet;
flux<<un_objet;

mais je voudrais écrire plutôt un truc du genre
flux<<un_objet.display;
(je peux avoir plusieurs méthodes d'affichage par exemple)


Ça ne marche pas directement comme ça, mais c'est assez simple à
arriver plus ou moins a la même fin au moyen des manipulateurs,
c-à-d :

class MonObject
{
public:
ostream& display1( ostream& ) const ;
ostream& display2( ostream& ) const ;
// ...

enum DisplayMode { disp1, disp2 /* ... */ } ;
ostream& display( ostream& dest ) const
{
static ostream& (MonObject::* const pf[])( ostream&) const
=
{
&MonObject::display1,
&MonObject::display2,
// ...
} ;
return (this->*pf[ dest.iword( getIWordIndex() ) ])( dest )
;
}

static int getIWordIndex()
{
static int iWordIndex = ostream::xalloc() ;
return iWordIndex ;
}
} ;

ostream&
operator<<( ostread& dest, MonObject const& source )
{
return source.display( dest ) ;
}

ostream&
monManip1( ostream& dest )
{
dest.iword( MonObject::getIWordIndex() ) = MonObject::disp1 ;
return dest ;
}

ostream&
monManip2( ostream& dest )
{
dest.iword( MonObject::getIWordIndex() ) = MonObject::disp2 ;
return dest ;
}

// ...

(Éventuellement, getIWordIndex pourrait être privée, avec les
manipulateurs des friend.)

À l'utilisation :

cout << monManip2 << un_object ;
cout << monManip1 << un_object ;

Selon tes souhaits, tu pourrais aussi faire que display() remet
à zéro la mode, après s'en être servi.

Dans un environement multi-thread, il faudrait bien entendu
s'arranger pour que getIWordIndex soit appelé au moins une fois
avant le démarrage des threads. (Normalement, un :

int dummyForInitialization = MonObject::getIWordIndex() ;

à la portée namespace dans une module linkée statiquement ferait
l'affaire.)

je crois que un_objet.display est malheureusement du type
std::ostream& (MonObjet::*)(std::ostream&), où un truc du
genre :-)) (je doute de ce que j'écris parfois)


Je crois surtout que le seul opérateur valid sur
« un_object.display », si display est une fonction membre,
c'est (). Le résultat de l'expression, en fait, ne se laisse
pas décrire dans le système de types du C++ ; elle ne peut donc
servir que dans des cas spéciaux documentés.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
Marc G
Merci pour ta réponse détaillée
C'est vrai qu'entre écrire par exemple
cout<<mon_objet.displayHTML où displayHTML serait une méthode
et
cout<<displayHTML(mon_objet) où displayHTML est une structure
la différence est objectivement minime et purement syntaxique !
Je m'excuse si je donne parfois l'impression de poser des questions "cons"
mais je débute un peu en programmation C++ "avancée" (si on peut appeler ça
comme ça)
Nota : J. Kanze vient de me proposer une solution à partir des manipulateurs
de flux
Marc
Avatar
Marc G
c'est "simple" mais il faut quand même avoir l'habitude de manier des
écritures du genre
ostream& (MonObject::* const pf[])( ostream&)
ce qui n'est pas (encore) mon cas :-((
mais je me suis accroché et j'ai compris.
En fait, je ne connaissait pas non plus l'existence de xalloc et iword
Merci encore
Avatar
Marc G
j'essaye de généraliser ta méthode avec des templates

template <class T>
class toHTML {
public :
toHTML(const T &t) : _t(t) {}
friend std::ostream& operator<<(std::ostream&,const toHTML&);
private :
const T &_t;
};

// cette fonction template doit être spécialisée pour les classes
// avec une sortie HTML possible
template <class T>
std::ostream& operator<<(std::ostream &flux,const toHTML<T> &source)
{
flux<<"sortie HTML non définie";
return flux;
}


UnObjet objet;
std::ofstream fout("test.html",std::ios::out);
fout << toHTML<UnObjet >(objet) ; // <--- là, ça coïnce !

Est-ce que tu saurais comment s'y prendre ?
Marc
1 2