OVH Cloud OVH Cloud

cout

11 réponses
Avatar
Cornu Nicolas
Je voudrais quelque chose d'equivalent à hex
cout << hex

Quel est la syntaxe ?


D'avance merci,

Cornu Nicolas

10 réponses

1 2
Avatar
Franck Branjonneau
"Cornu Nicolas" écrivait:

Je voudrais quelque chose d'equivalent à hex


Tu es sur ?

Quel est la syntaxe ?


Quelque chose comme :

template< typename _Traits >
std::basic_ostream< typename _Traits::char_type, _Traits > &
operator<<(
std::basic_ostream< typename _Traits::char_type, _Traits > & os,
std::basic_ostream< typename _Traits::char_type, _Traits > &
(manipulator)
(std::basic_ostream< typename _Traits::char_type, _Traits > &)) {

return manipulator(os);
}


template< typename _Traits >
std::basic_ostream< typename _Traits::char_type, _Traits > &
manipulator(std::basic_ostream< typename _Traits::char_type, _Traits > & os) {

return os << "Je manipule.";
}


int main()
{
std::cout << manipulator << " Tu manipules...n";
return 0;
}


Je crois que c'est la sémantique, plutôt que la syntaxe, qui à un
intérêt. Dis nous ce que tu veux faire.
--
Franck Branjonneau

Avatar
Franck Branjonneau
"Cornu Nicolas" écrivait:

Je voudrais quelque chose d'equivalent à hex


Tu es sur ?

Quel est la syntaxe ?


Quelque chose comme :

template< typename _Traits >
std::basic_ostream< typename _Traits::char_type, _Traits > &
operator<<(
std::basic_ostream< typename _Traits::char_type, _Traits > & os,
std::basic_ostream< typename _Traits::char_type, _Traits > &
(manipulator)
(std::basic_ostream< typename _Traits::char_type, _Traits > &)) {

return (*manipulator)(os);
}


template< typename _Traits >
std::basic_ostream< typename _Traits::char_type, _Traits > &
manipulator(std::basic_ostream< typename _Traits::char_type, _Traits > & os) {

return os << "Je manipule.";
}


int main()
{
std::cout << manipulator << " Tu manipules...n";
return 0;
}


Je crois que c'est la sémantique, plutôt que la syntaxe, qui à un
intérêt. Dis nous ce que tu veux faire.
--
Franck Branjonneau

Avatar
Cornu Nicolas
Je veux ajouter a ma classe Logger qui hérite d'une classe virtuel pure
ILogger une méthod epour indiquer le niveau de sévérité de l'erreur ou même
d'autre informations comme DEBUG.

log << "Socket connécté";
log << DEBUG << "text";
log << WARNING << "text";
log << "Connection accepté:" << ip;
produirait dans le fichier log.txt:

date... Socket connécté
date... DEBUG text
date... Connection accepté: 212.56.12.36
date... WARNING text

Je vais renommer la classe Logger en syslog
sous linux elle utilisera syslogd pour logger et sous windows elle
enregistrera dans un fichier texte.

On m'impose une classe virtuel pure car je doit faire une interface comme
exemple de modularité.
Il est prévu de fair eune classe DBLog : public ILogger qui enregistrerait
toutes les informations dan sune base de donnée.


NC

"Franck Branjonneau" a écrit dans le message de
news:
"Cornu Nicolas" écrivait:

Je voudrais quelque chose d'equivalent à hex


Tu es sur ?

Quel est la syntaxe ?


Quelque chose comme :

template< typename _Traits >
std::basic_ostream< typename _Traits::char_type, _Traits > &
operator<<(
std::basic_ostream< typename _Traits::char_type, _Traits > & os,
std::basic_ostream< typename _Traits::char_type, _Traits > &
(manipulator)
(std::basic_ostream< typename _Traits::char_type, _Traits > &)) {

return (*manipulator)(os);
}


template< typename _Traits >
std::basic_ostream< typename _Traits::char_type, _Traits > &
manipulator(std::basic_ostream< typename _Traits::char_type, _Traits > &
os) {


return os << "Je manipule.";
}


int main()
{
std::cout << manipulator << " Tu manipules...n";
return 0;
}


Je crois que c'est la sémantique, plutôt que la syntaxe, qui à un
intérêt. Dis nous ce que tu veux faire.
--
Franck Branjonneau



Avatar
Cornu Nicolas
Vous me direz je pourrait faire:

log << " WARNING " << "text";

Mais je prefere utiliser un mot clef WARNING car il y aura peut-être d'autre
spécificités.

CN
Avatar
kanze
Cornu Nicolas wrote:
Je voudrais quelque chose d'equivalent à hex
cout << hex

Quel est la syntaxe ?


ios&
fnc( ios& stream )
{
stream.setf( ... ) ;
return stream ;
}

D'après tes autres postings, j'imagine que c'est pour des flags
qui n'existent pas encore. Dans ce cas-là, jette un coup d'oeil
aux fonctions ios::xalloc et ios::pword, pour trouver de la
place pour mettre les valeurs.

Si ton seul but, c'est de générer des chaînes fixes, je me
démande si des objets globaux ne ferait pas mieux l'affaire.
Voire simplement un enum (avec un surcharge de l'operator<< pour
l'enum).

Enfin, dans le cas d'un log, je le trouve toujours mieux de
passer la sévérité à une fonction, qui lui renvoie le flux à
utiliser ; de cette façon, tu peux facilement supprimer des logs
des sévérités moindre si tu veux. Quelque chose du genre :

class LogStreamWrapper
{
public :
LogStreamWrapper( std::ostream* stream )
: myStream( stream )
{
}

template< typename T >
LogStreamWrapper&
operator<<( T const& value )
{
if ( myStream != NULL ) {
*myStream << value ;
}
return *this ;
}

private:
std::ostream* myStream ;
} ;

et quelque part une fonction libre log qui le renvoie (en
collaboration avec ta classe Logger) :

inline LogStreamWrapper
log( Logger::Severity severity )
{
return LogStreamWrapper( tcurrentLogger->getStream( severity )
) ;
}

La fonction getWrapperStream régarde si on loggue réelement à
cette sévérité, et renvoi un NULL sinon, ou le flux qu'il faut.
Après avoir y insérer du text comme un timestamp, si c'est ce
qu'on veut.

--
James Kanze GABI Software
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
nico
Salut,

log << " WARNING " << "text";

Mais je prefere utiliser un mot clef WARNING car il y aura peut-être
d'autre spécificités.


Tu t'embetes bien, pour du débogage autant utiliser des macros...

#define WARNING " WARNING "

--
nico

Avatar
Cornu Nicolas
En faite s'est dans le cadre d'un porjet universitaire et y'a un aspect
pédagogique.

Je n'ai pas encre tester la proposition Franck mais je le ferait demain.

Nicolas

"nico" a écrit dans le message de
news:425ae391$0$6820$
Salut,

log << " WARNING " << "text";

Mais je prefere utiliser un mot clef WARNING car il y aura peut-être
d'autre spécificités.


Tu t'embetes bien, pour du débogage autant utiliser des macros...

#define WARNING " WARNING "

--
nico



Avatar
kanze
Cornu Nicolas wrote:

[...]
On m'impose une classe virtuel pure car je doit faire une
interface comme exemple de modularité.


Surtout puisqu'il s'agit d'un exercise d'école : il n'existe pas
quelque chose qui s'appelle une « classe virtuelle pûre ». Il y
a des fonctions virtuelle pûre, et il y a des classes
abstraites. Un classe abstraite est une classe qui contient une
ou plusieurs fonctions virtuelles pûres (éventuellement par
héritage).

Quand on parle d'une interface en C++, on parle en général du
modèle de conception interface, qui s'implémente bien en C++ au
moyen d'une classe abstraite qui n'a pas de code
d'implémentation ni de variables d'état. Ce qui ne veut pas
forcément dire qu'elle n'a pas du code de tout. Un idiome
consacré en C++ pour définir une interface consiste à faire des
fonctions publiques non-virtuelles qui renvoient à des fonctions
virtuelles privées ou protégées. En les encapsulant des
vérifications des pré- et post-conditions et des invariantes.

Dans ton cas de log, je ne crois pas que cet idiome s'applique,
mais honnêtement, j'ai mes doutes sur la convenance d'une
interface. Typiquement, je verais plutôt soit le modèle de
template (à ne pas confondre des templates C++ -- je parle ici
du modèle de conception), ou de la délégation. En ce qui
concerne l'école, je crois que la délégation conviendrait bien
aussi, parce que la classe de base du délégué serait bien une
interface, implémentée dans le langage au moyen d'une classe
abstraite sans autre chose que des fonctions pûres virtuelles.
C-à-d l'idiome de l'interface tel que le veut le professeur.

Il est prévu de fair eune classe DBLog : public ILogger qui
enregistrerait toutes les informations dan sune base de
donnée.


Mais comme on t'a expliqué, le formattage des données est
indépendant de la destination. On ne veut en aucun cas le mettre
dans les classes dérivées.

Étant vue le but pédégogique, je ne suis pas sûr jusqu'où tu
veux aller. Dans les logs professionnels, la notion
d'enregistrement (typiqueme une ligne) joue une rôle
importante : on ajoute du texte (au moins la date et l'heure)
automatiquement en tête de chaque enregistrement ; on flushe
implicitement à la fin, et dans un environemment multi-thread,
on s'assure que l'écriture de chaque enregistrement et atomique.

Tout ce qui suppose des complexités supplémentaires qui ne sont
peut-être pas le but de l'exercise. J'utilise beaucoup la durée
de vie des temporaires pour gérer l'atomicité, par exemple. Mais
c'est une technique très C++ ; surtout, c'est une technique, et
non un principe qu'il faut apprendre et comprendre pour être bon
informaticien. AMHA, l'apprentissage des techniques propre à un
langage, comme celle-ci, ne doit avoir lieu qu'une fois on a
bien maîtriser les principes. Comme la principe d'une
interface:-).

--
James Kanze GABI Software
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
Cornu Nicolas
Il est prévu de fair eune classe DBLog : public ILogger qui
enregistrerait toutes les informations dan sune base de
donnée.


Mais comme on t'a expliqué, le formattage des données est
indépendant de la destination. On ne veut en aucun cas le mettre
dans les classes dérivées.

Étant vue le but pédégogique, je ne suis pas sûr jusqu'où tu
veux aller. Dans les logs professionnels, la notion
d'enregistrement (typiqueme une ligne) joue une rôle
importante : on ajoute du texte (au moins la date et l'heure)
automatiquement en tête de chaque enregistrement ; on flushe
implicitement à la fin, et dans un environemment multi-thread,
on s'assure que l'écriture de chaque enregistrement et atomique.


Le prof aime bien le sinterfaces et dans ce cas s'est assez pratique.
DBLog est un exemple qui ne sera pas implémenté.
La seule différence aurait été le stockage de la date dans une colone la
sévérité dans une autre
et enfin le message.

Pour l'instant j'ai une classe Syslog qui log avec syslog quand la librairie
est compilé sus linux
et dans un fichier texte quand s'est sur windows.
J'ai également implémenté une classe ConsoleLogger qui redirige tout sur le
flux cerr.

NC


Avatar
kanze
Cornu Nicolas wrote:
Il est prévu de fair eune classe DBLog : public ILogger qui
enregistrerait toutes les informations dan sune base de
donnée.


Mais comme on t'a expliqué, le formattage des données est
indépendant de la destination. On ne veut en aucun cas le
mettre dans les classes dérivées.

Étant vue le but pédégogique, je ne suis pas sûr jusqu'où tu
veux aller. Dans les logs professionnels, la notion
d'enregistrement (typiqueme une ligne) joue une rôle
importante : on ajoute du texte (au moins la date et
l'heure) automatiquement en tête de chaque enregistrement ;
on flushe implicitement à la fin, et dans un environemment
multi-thread, on s'assure que l'écriture de chaque
enregistrement et atomique.


Le prof aime bien le sinterfaces et dans ce cas s'est assez
pratique. DBLog est un exemple qui ne sera pas implémenté.


Moi aussi je les aime bien ; je m'en sers beaucoup dans mes
applications. Mais ça ne veut pas dire que tout doit être une
interface ; une interface n'a de sens que quand on conçoit la
possibilité de plusieurs implémentations sans rien en commun
sauf qu'elles implémentent l'interface. Ici, ce n'est pas le
cas ; comment formatter un int, par exemple, doit être commun à
toutes les implémentations, et dupliquer le code dans chaque
implémentation serait une erreur de conception aussi.

Il existe plusieurs modèles de conception pour traiter le cas où
une partie de l'implémentation doit être commune, et une partie
non : le modèle template, le modèle stratégie, etc.

La seule différence aurait été le stockage de la date dans une
colone la sévérité dans une autre et enfin le message.


Exactement. « La seule différence ». Ça crie modèle template ou
modèle stratégie. (Ton prof t'a présenté les modèles de
conception, j'espère.)

Note bien que si tu adopte le modèle stratégie, il y aurait une
interface. Seulement, l'utilisateur ne le voit pas ; il sert
dans l'implémentation. (Quand tu décides de réelement écrire les
données, par exemple.)

Enfin, en passant, je te signale que l'implémentation de DBLog
n'est pas si évidente que ça. Parce qu'il te faut absolument la
notion d'enrégistrement pour le faire. Tu ne peux pas écrire une
enrégistrement par opérateur << ; il te faut donc gerer un autre
critère. Dans mon implémentation, je joue sur la durée de vie
d'un temporaire, mais il y a des subtilités en plus parce qu'il
y a des copies supplémentaires lorsqu'une fonction renvoie par
valeur. Pour commencer, une solution simple serait de déclarer
le caractère `n' comme fin d'enrégistrement.

En somme, comme exemple simple :

-- J'implémenterais un streambuf spécial, qui collectionnait
les caractères dans un string jusqu'au 'n', puis les
écrivait au moyen d'un délégué. C'est au niveau du délégu é
que l'interface entre en jeu.

-- Un objet (global) de type Log, qui est initialisé (ou qui
s'initialise) avec un pointeur à un ostream, qui serait ou
NULL, ou un ostream initialisé avec le streambuf ci-dessus
(et le streambuf, évidemment, serait initialisé avec un
pointeur à l'interface du délégué). Cet objet aurait une
fonction qui prend la sévérité, le nom du fichier et le
numéro de ligne, et qui renvoie un objet wrapper du ostream,
comme on l'a déjà présenté ; c'est ce wrapper qu'utilise
l'utilisateur pour ces propres sorties.

-- L'interface aurait deux fonctions (virtuelles pûres) :
void setParams( Severity severity,
std::string const& filename,
int lineNumber ) ;
void write( std::string const& message ) ;
La fonction getStream de l'objet de type Log en appelera le
premier, avec ces paramètres ; le streambuf en appelera la
deuxième, chaque fois qu'il voit un 'n'.

-- Finalement, je définirais un macro pour en facilité
l'utilisation :
#define log( severity )
globalLogObject.getStream( severity, __FILE__, __LINE__ )
Simplement parce que c'est extrèmement utile d'avoir le nom
du fichier et le numéro de la ligne dans le log, et c'est
chiant d'avoir à taper __FILE__, __LINE__ chaque fois.

En tant qu'exercise pédégogique, le seul point où j'aurais des
hestiations, c'est le premier -- typiquement, j'imagine qu'on
présente le concepte d'une interface bien avant d'entre dans les
détails de iostream. Mais le seul alternatif que je vois, c'est
d'utiliser un ostringstream, et de jouer sur les subtilités de
la durée de vie des temporaires pour en déclencher la lecture et
l'envoie du texte à l'interface. Si on ne considère que le
sous-ensemble du streambuf nécessaire à des écritures
non-bufferisées et ne supportant pas de seek, c'est vraiment
assez simple (une seule fonction : overflow), et le pair
ostream/streambuf est en fait un assez bon exemple du modèle
stratégie, et donc pourrait jouer même un rôle d'exemple.

Pour l'instant j'ai une classe Syslog qui log avec syslog
quand la librairie est compilé sus linux et dans un fichier
texte quand s'est sur windows.

J'ai également implémenté une classe ConsoleLogger qui
redirige tout sur le flux cerr.


C'est à peu près classique. Habituellement, j'utilise un fichier
de configuration de log, du genre : <sévérité> <action>. Selon
la sévérité, je fais une ou plusieurs choses : syslog, fichier
classique, email à un administrateur... Dans de grosses
applications, j'ajoute un colonne pour le sous-système : je peux
alors mettre des traces d'info dans des fichiers différents
selon le sous-système, ou plus souvent, n'activer les traces
d'info que dans le sous-système qui m'intéresse.

Dans la pratique, le vrai problème ici, c'est la performance
dans le cas où le log est inhibé. Tu veux que ça coûte le moins
possible, afin de pouvoir mettre le plus de traces
informationnelles possibles (qui sont normalement inhibé), afin
d'avoir le plus d'informations possibles en cas d'anomalie.

Mais tout ça, ce sont des problèmes propre à une utilisation
industrielle, qui ne doit pas te concerner dans un premier
temps.

--
James Kanze GABI Software
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



1 2