Quelle est la différence entre cout, cerr, clog of iostream header en C ++? Quand utiliser lequel?

98

J'ai essayé des recherches sur la différence entre cout, cerret clogsur Internet , mais ne pouvait pas trouver une réponse parfaite. Je ne sais toujours pas quand utiliser lequel. Quelqu'un peut-il m'expliquer, à travers des programmes simples et illustrer une situation parfaite sur quand utiliser lequel?

J'ai visité ce site qui montre un petit programme sur cerret clog, mais la sortie obtenue là-bas peut également être obtenue en utilisant cout. Donc, je suis confus sur l'utilisation exacte de chacun.

Arlene Batada
la source
6
Chacun a un flux reconnu par l' ordinateur, stdout, stdin(pour cin), et stderrqu'il utilise par défaut. Je crois que clogc'est juste cerravec un changement de tampon.
chris

Réponses:

48

stdoutet stderrsont des flux différents, même s'ils font tous deux référence à la sortie de la console par défaut. Rediriger (canaliser) l'un d'entre eux (par exemple program.exe >out.txt) n'affecterait pas l'autre.

Généralement, stdoutdoit être utilisé pour la sortie réelle du programme, tandis que toutes les informations et tous les messages d'erreur doivent être imprimés stderr, de sorte que si l'utilisateur redirige la sortie vers un fichier, les messages d'information sont toujours imprimés à l'écran et non vers le fichier de sortie.

riv
la source
131

Généralement, vous l'utilisez std::coutpour la sortie normale, std::cerrpour les erreurs et std::clogpour la "journalisation" (ce qui peut signifier ce que vous voulez que cela signifie).

La principale différence est qu'elle std::cerrn'est pas tamponnée comme les deux autres.


Par rapport à l'ancien C stdoutet stderr, std::coutcorrespond à stdout, tandis que std::cerret les std::clogdeux correspondent à stderr(sauf que std::clogc'est tamponné).

Un mec programmeur
la source
J'ai lu que les clogsorties vers cerr. Alors, sur cette base, lequel choisissez-vous? Si clogc'est normalement pour la "journalisation", pourquoi voudrais-je que cela aille dans le flux d'erreur? Les journaux ressemblent plus à des "journaux normaux" (aka cout) qu'à des erreurs.
void.pointer
@ void.pointer Comme je l'ai dit dans ma réponse, à la fois cerret clogutilise la sortie standard "error", mais clogest mis en mémoire tampon, ce qui pourrait expliquer pourquoi cela ressemble plus à cout. Lequel choisir pour la sortie d'erreur? Cela dépend, je suppose, de plus de raisons que je ne peux énumérer et cela doit être décidé au cas par cas.
Un mec programmeur du
3
qu'entendez-vous par «tamponné»?
simple
5
@simplename La sortie n'est pas écrite directement, elle est stockée dans un tampon jusqu'à ce que le tampon soit vidé . La sortie vers un fichier ou un terminal est historiquement lente (les terminaux ou les consoles sont encore lents), l'écriture caractère par caractère est inefficace, l'écriture d'un bloc d'octets est beaucoup plus efficace.
Un mec programmeur le
15

Flux de sortie standard (cout): cout est l'instance de la ostreamclasse. coutest utilisé pour produire une sortie sur le périphérique de sortie standard qui est généralement l'écran d'affichage. Les données devant être affichées à l'écran sont insérées dans le flux de sortie standard ( cout) à l'aide de l'opérateur d'insertion ( <<).

Flux d'erreurs standard non tamponné (cerr): cerr est le flux d'erreurs standard qui est utilisé pour générer les erreurs. Ceci est également une instance de la ostreamclasse. Tel qu'il cerrn'est pas mis en mémoire tampon , il est utilisé lorsque nous devons afficher le message d'erreur immédiatement. Il n'a pas de tampon pour stocker le message d'erreur et l'afficher plus tard.

Flux d'erreur standard tamponné (sabotage): Il s'agit également d'une instance de ostreamclasse et utilisé pour afficher les erreurs, mais contrairement à cerrl'erreur, elle est d'abord insérée dans un tampon et stockée dans la mémoire tampon jusqu'à ce qu'elle ne soit pas complètement remplie.

Lectures supplémentaires: basic-input-output-c

roottraveller
la source
11

La différence de ces 3 flux est la mise en mémoire tampon.

  1. Avec cerr, la sortie affleure
    • immédiatement (car cerr n'utilise pas de tampon).
  2. En cas de sabotage, la sortie rince
    • après avoir terminé votre fonction actuelle.
    • appeler explicitement la fonction flush.
  3. Avec cout, la sortie affleure
    • après avoir appelé tous les flux de sortie (cout, cerr, clog).
    • après avoir terminé votre fonction actuelle.
    • appeler explicitement la fonction flush.

Veuillez vérifier le code suivant et exécutez DEBUG sur 3 lignes: f (std :: clog), f (std :: cerr), f (std :: out), puis ouvrez 3 fichiers de sortie pour voir ce qui s'est passé. Vous pouvez échanger ces 3 lignes pour voir ce qui va se passer.

#include <iostream>
#include <fstream>
#include <string>

void f(std::ostream &os)
{
    std::cin.clear(); // clear EOF flags
    std::cin.seekg(0, std::cin.beg); // seek to begin

    std::string line;
    while(std::getline(std::cin, line))   //input from the file in.txt
        os << line << "\n";   //output to the file out.txt
}

void test()
{
    std::ifstream in("in.txt");
    std::ofstream out("out.txt"), err("err.txt"), log("log.txt");
    std::streambuf *cinbuf = std::cin.rdbuf(), *coutbuf = std::cout.rdbuf(), *cerrbuf = std::cerr.rdbuf(),
                    *clogbuf = std::clog.rdbuf();

    std::cin.rdbuf(in.rdbuf()); //redirect std::cin to in.txt!
    std::cout.rdbuf(out.rdbuf()); //redirect std::cout to out.txt!
    std::cerr.rdbuf(err.rdbuf());
    std::clog.rdbuf(log.rdbuf());


    f(std::clog);
    f(std::cerr);
    f(std::cout);

    std::cin.rdbuf(cinbuf);
    std::cout.rdbuf(coutbuf);
    std::cerr.rdbuf(cerrbuf);
    std::clog.rdbuf(clogbuf);
}

int main()
{
    test();
    std::cout << "123";
}
Duc-Viet Ha
la source
10
  • Utilisez cout pour la sortie standard.
  • Utilisez cerr pour afficher les erreurs.
  • Utilisez le sabot pour la journalisation.
David Vargas
la source
6
Faux, cerr est plus lent que cout à cause du non-buffer! Tout comme write vs printf
陳 力
4

À partir d'un projet de document standard C ++ 17:

30.4.3 Objets de flux étroits [narrow.stream.objects]

istream cin;

1 L'objet cincontrôle l'entrée d'un tampon de flux associé à l'objet stdin, déclaré dans <cstdio>(30.11.1).

2 Une fois l'objet cininitialisé, cin.tie()retourne &cout. Son état est par ailleurs le même que celui requis pour basic_ios<char>::init(30.5.5.2).

ostream cout;

3 L'objet coutcontrôle la sortie vers un tampon de flux associé à l'objet stdout, déclaré dans <cstdio>(30.11.1).

ostream cerr;

4 L'objet cerrcontrôle la sortie vers un tampon de flux associé à l'objet stderr, déclaré dans<cstdio> (30.11.1).

5 Une fois l'objet cerrinitialisé, il cerr.flags() & unitbufest différent de zéro et cerr.tie()revient &cout. Son état est par ailleurs le même que celui requis pour basic_ios<char>::init(30.5.5.2).

ostream clog;

6 L'objet clogcontrôle la sortie vers un tampon de flux associé à l'objetstderr , déclaré dans <cstdio>(30.11.1).

Discussion...

coutécrit à stdout; cerretclog àstderr

Sortie standard (stdout ) est destiné à recevoir une sortie sans erreur et sans diagnostic du programme, telle que la sortie d'un traitement réussi qui peut être affichée à l'utilisateur final ou diffusée dans une étape de traitement supplémentaire.

Erreur standard (stderr ) est destinée à la sortie de diagnostic, comme les messages d'avertissement et d'erreur indiquant que le programme n'a pas ou n'a peut-être pas produit la sortie attendue par l'utilisateur. Cette entrée peut être affichée à l'utilisateur final même si les données de sortie sont acheminées vers une étape de traitement supplémentaire.

cinet cerrsont liés àcout

Ils sont tous deux vidés coutavant de gérer eux-mêmes les opérations d'E / S. Cela garantit que les invites envoyées à coutsont visibles avant que le programme ne bloque l'entrée à partir de cin, et que la sortie précédente vers coutest vidée avant d'écrire une erreur viacerr desquels , ce qui maintient les messages dans l'ordre chronologique de leur génération lorsque les deux sont dirigés vers le même terminal / fichier / etc..

Cela contraste avec clog- si vous y écrivez, il ne sera pas mis en mémoire tampon et n'est lié à rien, il mettra donc en mémoire tampon des quantités de journalisation de taille décente avant le vidage. Cela donne le débit de messages le plus élevé, mais signifie que les messages peuvent ne pas être rapidement visibles pour un consommateur potentiel qui lit le terminal ou qui suit le journal.

Tony Delroy
la source
1

Les deux Cout et saboterie sont mises en mémoire tampon , mais cerr est un tampon et tous ces éléments sont des objets prédéfinis qui sont des instances de ostream de classe. L'utilisation de base de ces trois éléments est que cout est utilisé pour l'entrée standard tandis que sabot et cerr sont utilisés pour afficher les erreurs. Le point principal pour lequel cerr n'est pas tamponné est peut-être parce que supposons que vous ayez plusieurs sorties dans le tampon et qu'une exception d'erreur soit mentionnée dans le code, vous devez alors afficher cette erreur immédiatement, ce qui peut être fait par cerr efficacement.

S'il vous plait corrigez moi si je me trompe.

Kashif Faraz Shamsi
la source