stdin, stdout e stderror

por Fabio A. Mazzarino

Em C e C++ temos três streams padrão, um de entrada, stdin, e dois de saída, stdout e stderr, respectivamente saída e erro. Cada um pode ser redirecionado individualmente facilitando muito as coisas. Vamos aprender a redirecionar as saídas, e como utilizá-las da melhor forma.

Linguagem C

Para utilizar stdin e stdout basta utilizar as funções de entrada e saída padrão, tais como scanf, ou printf. Automaticamente os dados serão recuperados da entrada padrão, ou da redirecionados pra saída padrão, respectivamente.

Adicionalmente é possível utilizar as variáveis stdin, stdout e stderr declaradas em stdio.h como do tipo FILE*. Portanto:

#include <stdio.h>
int main() {
    char phone[20] = "";
    fgets(phone, 19, stdin);
    fprintf(stdout, "Hello stdout\n");
    fprintf(stderr, "Hello stderr\n");
}

Irá aceitar ler até 19 caracteres da entrada padrão e armazenar na string phone, escrever Hello stdout na saída padrão, e Hello stderr na saída de erro padrão.

C++

Em C++ existem três streams padrão declarados no iostream: cin, cout e cerr, entrada padrão, saída padrão e saída de erro padrão, respectivamente. E sua utilização é ainda mais simples:


#include <iostream>
#include <string>
int main() {
    std::string str = "";
    std::cin >> str;
    std::cout << "Hello, stdout" << std::endl;
    std::cerr << "Hello, stderr" << std::endl;
}

Que irá gerar uma saída idêntica ao programa em C, com a diferença que não há limite de caracteres de entrada.

Um Pra Lá, Outro Pra Cá

Uma das grandes vantagens de separar stdout de stderr é poder definir duas saídas genéricas deixando a critério do usuário como e qual deseja utilizar. Assim é possível separar, por exemplo, saída do processamento, do log de execução. Assim é possível utilizar a seguinte linha de comando:

retrievedata | processdata > processdata.output.txt 2> processdata.log

Considerando que retrievedata recupera dados e envia para stdout, processdata recupera os dados de stdin, envia os dados processados para stdout, e utiliza stderr para os logs. O resultado final serão os dados processados em processdata.output.txt, e o log em processdata.log.