Operadores
Transcrição
Operadores
Entrada e Saída Julia – Tecgraf PUC-Rio Agosto 2010 Exemplo de entrada em arquivo #include <fstream> #include <iostream> using namespace std; classe que representa um stream para um arquivo de saída int main() { ifstream file("exemplo1.txt"); char ch; while(!file.eof()) a função eof() ... { file.get(ch); cout << ch; a função get() ... } file.close(); } o arquivo deve ser fechado após seu uso 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 2 Streams de Entrada e Saída • Abstração que representa uma sequência de bytes – Input: de um dispositivo (disco, teclado, etc) para a memória – Saída: da memória para um dispositivo (impressora, console, etc) • Orientação a objetos – Tipo Abstrato de Dados (Standard I/O, files, blocos de memória, etc) – Redefinição de operadores 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 3 Streams de Entrada e Saída • Low-level I/O – Não formatado – Transferência byte-a-byte – Eficiência para transmissão de grande volume de dados • High-level I/O – Formatado – Bytes agrupados (inteiros, caracteres, strings, etc) – Adequado para a maior parte das necessidades de I/O 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 4 Streams de Entrada e Saída • Em C++, existem diferentes tipos de streams de entrada (istream) e saída (ostream) • Por exemplo: – ifstream e ofstream para arquivos – istrstream e ostrstream para char* – istringstream e ostringstream para objetos String de C++ • Todos os tipos de streams de entrada e saída mantém uma interface comum 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 5 Standard Library: iostream • Possui as funcionalidades para manipulação de entrada/saída em C++ – Basic class templates: classes básicas virtuais – Class template instantiations: implementação de classes básicas para manipular elementos do tipo char (narrow-oriented) e wchar_t (wide oriented) – Standard objects: o header <iostream> define objetos de e/s padrão stdin, stdout e stderr – Manipulators: funções globais (ex: endl, hex, scientific) para uso com os operadores << e >> 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 6 Visão geral das bibliotecas • <ios>, <istream>, <ostream>, <streambuf> e <iosfwd> contém classes bases da hierarquia e não costumam ser incluídos diretamente na maioria dos programas c++ • <iostream> declara objetos usados para entrada e saída padrão • <fstream> declara classes para entrada e saída em arquivos • <sstream> declara classes para manipular strings como streams • <iomanip> declara standard manipulators para uso com << e >> 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 7 Operadores << e >> • Os operadores << e >> são usados para simplificar as operações de entrada e saída formatadas, em todos os tipos de streams << – Inserter Operator – Usado para inserir dados em um dispositivo de saída >> – Extractor Operator – Usado para extrair dados de um dispositivo de entrada 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 8 Exemplo de uso do operador << #include <fstream> using namespace std; Nesse arquivo estão definidas várias classes usadas para file i/o classe que representa um stream int main() para um arquivo de saída { ofstream file("exemplo1.txt"); file << "Esse e' um primeiro exemplo de saida em arquivo"; file.close(); operador << que tem como argumento o conteúdo a ser escrito return 0; } o arquivo deve ser fechado após seu uso 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 9 Output Stream • A classe ostream representa uma sequência de bytes de saída • Suporta saída formatada e não formatada • Instâncias da classe ostream definidas em <iostream> – cout: representa a saída padrão (stdout) – cerr: representa a saída padrão para erros (stderr) – clog: representa a saída padrão para log 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 10 Formatação da saída em ostream • O operador << é usado para formatar os dados enviados a um ostream – Ex: um valor numérico é escrito como uma sequência de caracteres ostream& ostream& ostream& ostream& ostream& ostream& ostream& ostream& ostream& ostream& ostream& 08/09/10 operator<< operator<< operator<< operator<< operator<< operator<< operator<< operator<< operator<< operator<< operator<< (bool& val ); (short& val ); (unsigned short& val ); (int& val ); (unsigned int& val ); (long& val ); (unsigned long& val ); (float& val ); (double& val ); (long double& val ); (const void* val ); POO Avançado - Copyright Tecgraf PUC-Rio 11 Manipulators • São funções especiais usadas em conjunto com os operadores << e >> • Definidos em <iomanip> • Alguns são específicos para entrada ou saída 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 12 Exemplos de manipuladores de saída endl Insere newline ends Insere o caractere null ( '\0') flush Fz flush no buffer usado pelo stream dec Altera a base numérica para decimal hex Altera a base numérica para hexadecimal oct Altera a base numérica para octal scientific Usa notação científica fixed Usa notação em ponto fixo setprecision Altera a precisão das casas decimais (possui parâmetro) setfill Altera o carectere de preenchimento (possui parâmetro) setw Altera o número de caracteres usado como largura (possui parâmetro) 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 13 Exemplos de manipulators de saída cout cout cout cout cout cout cout cout cout cout << << << << << << << << << << 08/09/10 1331 << endl; hex<< 1331 << endl; 1331.123456 << endl; scientific << 1331.123456 << endl; fixed << 1331.123456 << endl; setprecision(3) << 1331.123456 << endl; dec << 1331 << endl; setfill('X') << setw(8) << left << 1331 << endl; true << false << endl; boolalpha << true << false << endl; POO Avançado - Copyright Tecgraf PUC-Rio 14 Saída não formatada • Funções put e write – ostream& put (char c); Escreve o caractere c no buffer de saída – ostream& write (const char* s , streamsize n); Escreve no buffer de saída o bloco de caracteres apontado por s e de tamanho n – Podem ser chamados em cascata – Permitem parâmetros numéricos (ASCII) cout.put('A').put('B').put('C').put('\n'); cout.put(65).put(66).put(67).put('\n'); const char* v = "ABCD"; cout.write (v, 4).put('\n'); 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 15 Ouput em tipos definidos pelo usuário • A classe pode definir o operador << seguindo o mesmo padrão dos tipos primitivos class person { public: int age; string name; person (int _age, string _name) { age = _age; name = _name; } }; ostream& operator<<(ostream &os, const person &p) { return os << p.name << " tem " << p.age << " anos"; } int main() { person ana(10,"ana maria"); cout << ana << endl; } 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 16 Especialização de classe com o operador << class person { public: int age; string name; person (int _age, string _name) { age = _age; name = _name; } }; ostream& operator<<(ostream &os, const person &p) { return os << p.name << " tem " << p.age << " anos"; } class child : public person { public: person& parent; child (int _age, string _name, person& _parent) : person (_age, _name), parent (_parent) { } }; ostream& operator<<(ostream &os, const child &p) { return os << p.name << " tem " << p.age << " anos e seu responsavel" << "é' " << p.parent.name; } 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 17 Especialização de classe com o operador << int main() { person p(35,"ana"); cout << p << endl; child c(10,"pedro", p); cout << c << endl; person* p2 = &c; cout << *p2 << endl; return 0; } > ana tem 35 anos > pedro tem 10 anos e seu responsavel e' ana > pedro tem 10 anos 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 18 Especialização de classe com o operador << class person { public: int age; string name; person (int _age, string _name) { age = _age; name = _name; } virtual ostream& put (ostream& s) const; }; ostream& person::put (ostream& s) const { return s << name << " tem " << age << " anos"; } ostream& operator<<(ostream &os, const person &p) { return p.put(os); } 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 19 Especialização de classe com o operador << class child : public person { public: person& parent; child (int _age, string _name, person& _parent) : person (_age, _name), parent (_parent) { } ostream& put (ostream& s) const; }; ostream& child::put (ostream& s) const { return s << name << " tem " << age << " anos e seu responsavel e' " << parent.name; } int main() { person p(35,"ana"); cout << p << endl; child c(10,"pedro", p); cout << c << endl; person* p2 = &c; cout << *p2 << endl; return 0; } 08/09/10 > ana tem 35 anos > pedro tem 10 anos e seu responsavel e' ana > pedro tem 10 anos e seu responsavel e' ana POO Avançado - Copyright Tecgraf PUC-Rio 20 Input Stream • A class istream é usada para ler e interpretar uma sequência de bytes • Suporta entrada formatada e não formatada • Instância da classe istream definidas em <iostream> – cin: representa a entrada padrão (stdin) 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 21 Formatação da entrada em istream • O operador >> é usado para formatar os dados obtidos de um istream – Ex: uma sequência de caracteres lida é formatada como um valor numérico, booleano, etc. istream& istream& istream& istream& istream& istream& istream& istream& istream& istream& istream& 08/09/10 operator>> operator>> operator>> operator>> operator>> operator>> operator>> operator>> operator>> operator>> operator>> (bool& val ); (short& val ); (unsigned short& val ); (int& val ); (unsigned int& val ); (long& val ); (unsigned long& val ); (float& val ); (double& val ); (long double& val ); (void*& val ); POO Avançado - Copyright Tecgraf PUC-Rio 22 O operador >> para entrada formatada • Não lê espaço em branco • Retorna 0 quando encontra EOF • Suporte a manipuladores de entrada skipws Ignora espaço em branco noskipws Não ignora espaço em branco boolalpha Lê valor booleano com a notação alfanumérica (ex: true e false) noboolapha Lâ valor booleano com a notação 0 e 1 dec Lê valor numérico decimal hex Lê valor numérico hexadecimal ws Extrai os espaços em branco 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 23 Exemplo de entrada formatada int n; char str[10]; bool b; cout << "Entre um numero decimal: "; cin >> n; cout << "O numero digitado e': " << n << endl; cout << "Entre um numero hexadecimal: "; cin >> hex >> n; // manipulador cout << "O numero decimal equivalente e': " << n << endl; cout << "Entre uma palavra: "; cin.width (10); // maximo cin >> str; cout << "Os primeiros 9 caracteres da palavra sao: " << str << endl; cout << "Entre com true ou false: "; cin >> boolalpha >> b; cout << "O valor booleano digitado e': " << b << endl; 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 24 Entrada não formatada • Funções get, getline e read – Lêem caracteres – O espaço em branco é lido como um caractere qualquer – Retorna EOF se o final de arquivo é encontrado (ctr-z ou ctrl-d, dependendo do sistema) • int get(); Extrai e retorna um caractere do stream de entrada (cast para int) int character; cout << "Entre com uma frase seguida de EOF:" << endl; while ( ( character = cin.get() ) != EOF ) { cout.put( character ); } cout << "\nEOF no sistema: " << character << endl; 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 25 Funções get • Não removem o delimitador do stream de entrada • Colocam o terminador null ('\0') no final – istream& get ( char& c ); Extrai um caractere do stream de entrada e coloca no parâmetro c – istream& get (char* s, streamsize n ); Extrai caracteres do stream de entrada e guarda no array apontado pelo parâmetro s. Os caracteres são lidos até a quantidade de n-1 caracteres ou até o delimitador '\n' ser encontrado. – istream& get (char* s, streamsize n, char delim ); O mesmo que o anterior, exceto que o delimitador é especificado no parâmetro delim. 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 26 Funções getline • Removem o delimitador do stream de entrada • Colocam o terminador null ('\0') no final – istream& getline (char* s, streamsize n ); Extrai caracteres do stream de entrada e guarda no array apontado pelo parâmetro s. Os caracteres são lidos até a quantidade de n-1 caracteres ou até o delimitador '\n' ser encontrado. – istream& getline (char* s, streamsize n, char delim ); O mesmo que o anterior, exceto que o delimitador é especificado no parâmetro delim. 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 27 Exemplo de leitura com getline #include <iostream> using namespace std; int main () { char name[256], title[256]; cout << "Entre com seu nome: "; cin.getline (name,256); cout << "Entre com seu filme favorito: "; cin.getline (title,256); cout << "O filme favorito de " << name << " e' " << title << endl; return 0; } 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 28 Função read • stream& read ( char* s, streamsize n ); Lê um bloco de dados de tamanho n e guarda no parâmetro s. Se EOF for encontrado, guarda os caracteres lidos antes. Não coloca o terminador null ao final do bloco. int main() { char buf[10]; cin.read(buf,10); cout << "Lidos " << cin.gcount() << " caracteres: " << buf << endl; return 0; } 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 29 Outras funções membros de istream • istream& ignore(streamsize n=1, int delim=EOF) Extrai caracteres do stream de entrada e não guarda em lugar algum • istream& putback ( char c ); Coloca um caractere no stream de entrada • int peek ( ) Lê e retorna o próximo caractere sem removê-lo de stream de entrada • streamsize gcount ( ) const; Retorna o número de caracteres lidos na última leitura não formatada 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 30 Outros exemplos de leitura de dados char first, last; cout << "Entre com seu primeiro e ultimo nomes: "; first=cin.get(); cin.ignore(256,' '); last=cin.get(); cout << "Suas iniciais sao " << first << last << endl; > Entre com seu primeiro e ultimo nomes: Joao Pedro > Suas iniciais sao JP 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 31 Input em tipos definidos pelo usuário • A classe pode definir o operador >> seguindo o mesmo padrão dos tipos primitivos • Se for lido algum dado não previsto: – A implementação do operador pode alterar os bits de erro 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 32 Input em tipos definidos pelo usuário istream& operator>>(istream &is, person &p) { char c; char name[256]; int age=10; is >> c; if (c=='(') { is.getline (name, 256, ','); is >> age >> c; if (c!=')') is.clear (ios_base::badbit); } else { is.putback (c); is >> name; } p = person(age, name); return is; } int main() { person aPerson; cout << "Entre com uma pessoa: " << endl; cin >> aPerson; } 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 33 Estado de Stream • Todo stream (istream ou ostream) possui um estado associado • Erros e condições anormais são tratados alterando e testando esse estado, indicados por bits de estado – iostate rdstate ( ) const; 08/09/10 eofbit EOF lido de um inputstream failbit A última operação de leitura falhou badbit Erro devido a uma falha na leitura ou na escrita goodbit Sem erro. Corresponde ao valor zero. POO Avançado - Copyright Tecgraf PUC-Rio 34 Estado de Stream • Ao invés de testar usando operações sobre bits, as seguintes funções estão disponíveis: – bool eof ( ) const; – bool fail ( ) const; – bool bad ( ) const; – bool good ( ) const; • Para alterar o estado de um stream – void clear ( iostate state = goodbit ); – Ex: cin.clear( ios::failbit ) 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 35 Exemplo dos estados de streams cout << "Antes de entrar com um valor invalido:" << endl << "cin.rdstate(): " << cin.rdstate() << endl << "cin.eof(): " << cin.eof() << endl << "cin.fail(): " << cin.fail() << endl << "cin.bad(): " << cin.bad() << endl << "cin.good(): " << cin.good() << endl << "Espera um inteiro, porem, entre com um caractere: "; cin >> integerValue; cout << endl; cout << "Apos a entrada invalida:" << endl << "cin.rdstate(): " << cin.rdstate() << endl << "cin.eof(): " << cin.eof() << endl << "cin.fail(): " << cin.fail() << endl << "cin.bad(): " << cin.bad() << endl << "cin.good(): " << cin.good() << endl; cin.clear(); // limpa o estado do stream cout << endl; cout << "Apos cin.clear()" << endl << "cin.fail(): " << cin.fail() << endl << "cin.good(): " << cin.good() << endl; 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 36 File Streams • As classes ifstream, ofstream e fstream são usadas para manipulação de arquivos como sequência de caracteres, de forma similar ao que foi visto até aqui – ifstream é um istream – ofstream é um ostream – fstream é um iostream que herda de istream e de ostream, servindo, portanto, para arquivos de leitura e escrita • Estão definidas em <fstream> 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 37 Exemplo de cópia de um arquivo #include <iostream> #include <fstream> using namespace std; void error (const char* p, const char* p2="") { cerr << p << ' ' << p2 << endl; exit(1); } int main(int argc, char* argv[]) { if (argc!=3) error("Numero de argumentos invalido"); ifstream from (argv[1]); if (!from) error("Nao pode abrir o arquivo de entrada"); ofstream to (argv[2]); if (!to) error("Nao pode abrir o arquivo de saida"); char c; while (from.get(c)) to.put(c); if (!from.eof() || !to) error("Houve erro na copia do arquivo"); } 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 38 Abrindo arquivos • Os construtores das classes abrem o arquivo quando recebem o nome como parâmetro • A função membro open também pode ser usada para abrir arquivo – void open ( const char * filename, ios_base::openmode mode = ios_base::in ); • Parâmetro opcional para o modo de abertura app (append) Coloca o cursor no final do arquivo após operações output ate (at end) Abre com a cursor no final do arquivo binary (binary) Binário ao invés de texto in (input) Permite operações de entrada out (output) Permite operações de saída trunc (truncate) Apaga o conteúdo corrente 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 39 Fechando arquivos • Por default, arquivos são fechados nos seus destrutores • Opcionalmente, arquivos podem ser fechados usado a função close() • Pode ser útil para fechar um arquivo antes de terminar o escopo do bloco onde ele é usado int main () { ifstream infile; infile.open ("test.txt", ifstream::in); while (infile.good()) cout << infile.get(); infile.close(); return 0; } 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 40 Processando String como Stream • Objetos da classe stringstream permitem que strings possam ser manipulados da mesma forma que streams – stringstream: permite entrada e saída – istringstream: permite apenas entrada – ostringstream: permite apenas saída • Classes definidas no arquivo <sstream> 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 41 Exemplo de StringStream #include <iostream> #include <sstream> using namespace std; void word_per_line (const string& s) { istringstream ist(s); string w; while (ist>>w) cout << w << endl; } int main() { word_per_line ("Voce acha c++ dificil?"); } 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 42 Buffering • Streams de entrada e saída usam buffer para armazenar os dados antes de descarregá-los no dispositivo associado ao stream – A classe Streambuf definida em <streambuf> usada como tipo genérico para buffers de streams • Unbuffered I/O são streams cujo streambuf descarrega imediatamente cada caractere, sem acumulá-los para uma operação de transferência mais eficiente 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 43 Streambuf • Podem ser compartilhados entre diferentes streams – streams não podem ser copiados e nem atribuídos, porém um stringbuf pode int main(int argc, char* argv[]) { ofstream fil; if (argc > 1) { fil.open(argv[1]); cout = fil; // Erro de compilação!!! } cout << "Ola mundo!" << endl; } 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 44 Redirecionando o cout usando streambuf #include <iostream> #include <fstream> using namespace std; Repare que, enviar dados para o cout, passou a ser o mesmo que enviar dados para o arquivo “test.txt” int main () { streambuf *psbuf, *backup; ofstream filestr; filestr.open ("test.txt"); backup = cout.rdbuf(); // ponteiro para o buffer do cout psbuf = filestr.rdbuf(); // ponteiro para o buffer do file cout.rdbuf(psbuf); cout << "Escrevendo esse conteudo no arquivo"; cout.rdbuf(backup); filestr.close(); return 0; } 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 45 Compartilhando o streambuf Note que file1 e file2 compartilham o mesmo buffer. Portanto, enviar dados para um ou para o outro, escreve no mesmo arquivo. As propriedades de formatação de cada stream, no entanto, são preservadas. #include <fstream> #include <iostream> #include <iomanip> using namespace std; int main() { ofstream file1("test1.txt"); ostream file2(file1.rdbuf()); file1.setf(ios_base::fixed, ios_base::floatfield); file1.precision(5); file2.setf(ios_base::scientific, ios_base::floatfield); file2.precision(3); file1 << setw(10) << 47.11 << '\n'; file2 << setw(10) << 47.11 << '\n'; } > cat test1.txt 47.11000 4.711e+01 08/09/10 POO Avançado - Copyright Tecgraf PUC-Rio 46