Em C++, a biblioteca padrão fornece um sistema robusto para lidar com operações de entrada e saída (I/O) através de fluxos (streams). Esses fluxos facilitam a comunicação entre o programa e diversos dispositivos, como o console, arquivos e buffers de memória.
Saída de Dados com ostream
O objeto std::cout é a interface principal para a saída padrão. Além da exibição simples de dados, o C++ oferece manipuladores que alteram o estado do fluxo e formatam como os dados são apresentados.
Manipuladroes de Base Numérica
Ao enviar manipuladores para o cout, a alteração persiste para as próximas saídas até que um novo manipulador seja definido.
#include <iostream>
int main() {
int valor = 255;
std::cout << "Decimal: " << std::dec << valor << std::endl;
std::cout << "Octal: " << std::oct << valor << std::endl;
std::cout << "Hexadecimal: " << std::hex << valor << std::endl;
return 0;
}
Formatação Avançada com <iomanip>
Para um controle mais refinado, utilizamos a biblioteca <iomanip>, que permite definir larguras, precisão e preenchimento.
| Manipulador | Descrição | Biblioteca |
|---|---|---|
| std::setw(n) | Define a largura do campo de saída para n caracteres. | <iomanip> |
| std::setfill(c) | Define o caractere de preenchimento. | <iomanip> |
| std::setprecision(n) | Define a precisão de casas decimais para pontos flutuantes. | <iomanip> |
| std::fixed | Exibe números decimais em formato de ponto fixo. | <iostream> |
| std::boolalpha | Exibe valores booleanos como "true" ou "false". | <iostream> |
Funções de Membro do cout
- cout.put(char): Escreve um único caractere no fluxo.
- cout.write(buffer, n): Escreve um bloco de n caracteres a partir de um array.
- cout.flush(): Força o esvaziamento do buffer de saída, garantindo que os dados sejam enviados ao destino imediatamente.
const char* mensagem = "Exemplo de escrita";
std::cout.write(mensagem, 7); // Saída: Exemplo
std::cout.put('\n');
Fluxos de Erro e Log
O C++ distingue entre a saída padrão (stdout) e a saída de erro (stderr):
- std::cerr: Fluxo de erro padrão. Por padrão, não possui buffer, o que significa que as mensagens são exibidas imediatamente.
- std::clog: Fluxo de log padrão. Possui buffer, sendo ideal para registrar informações de depuração que não exigem exibição instantânea.
Redirecionamento em Linha de Comando
No terminal, é possível separar a saída normal dos erros:
# Redireciona a saída normal para log.txt e erros para erro.txt
./meu_programa > log.txt 2> erro.txt
# Redireciona ambos para o mesmo arquivo
./meu_programa > output.txt 2>&1
Entrada de Dados com istream
O std::cin é utilizado para capturar dados do usuário. No entanto, o operador >> interrompe a leitura ao encontrar espaços em branco. Para capturar linhas inteiras, utilizamos getline.
#include <string>
#include <iostream>
std::string nomeCompleto;
std::getline(std::cin, nomeCompleto);
Tratamento de Falhas na Entrada
Quando o usuário fornece um tipo de dado inesperado (ex: texto em um campo numérico), o cin entra em um estado de falha. É necessário limpar o erro e ignorar os caracteres inválidos no buffer.
int idade;
while (!(std::cin >> idade)) {
std::cout << "Entrada inválida. Digite um número: ";
std::cin.clear(); // Limpa o estado de erro
std::cin.ignore(1000, '\n'); // Descarta o conteúdo incorreto no buffer
}
Manipulação de Strings com stringstream
A classe std::stringstream da biblioteca <sstream> permite tratar strings como fluxos, sendo extremamente útil para conversões de tipos e formatação de texto dinâmica.
#include <sstream>
std::stringstream formatador;
formatador << "Preço: " << 19.99 << " ID: " << 101;
std::string resultado = formatador.str();
Gerenciamento de Arquivos com fstream
Para persistência de dados, utilizamos ifstream (leitura), ofstream (escrita) ou fstream (ambos).
Modos de Abertura Comuns
- ios::out: Abre para escrita (sobrescreve o conteúdo).
- ios::app: Modo append (adiciona ao final do arquivo).
- ios::binary: Abre o arquivo em modo binário.
- ios::ate: Abre e move o ponteiro de leitura/escrita para o final.
Escrita e Leitura de Arquivos
#include <fstream>
// Escrevendo em um arquivo
std::ofstream arquivoSaida("dados.bin", std::ios::binary);
if (arquivoSaida.is_open()) {
int num = 12345;
arquivoSaida.write(reinterpret_cast<char*>(&num), sizeof(num));
arquivoSaida.close();
}
// Lendo o tamanho de um arquivo
std::ifstream arquivoEntrada("dados.bin", std::ios::binary | std::ios::ate);
std::streamsize tamanho = arquivoEntrada.tellg();
std::cout << "Tamanho do arquivo: " << tamanho << " bytes" << std::endl;
Sempre verifique se o arquivo foi aberto corretamente com is_open() e feche o fluxo com close() para garantir a integridade dos dados e liberar recursos do sistema operacional.