Manipuladores de Formatos Todas as especificações de manipuladores predefinidos na linguagem foram incluídas no ficheiro iomanip.h. Se for necessário usar os manipuladores o ficheiro iomanip.h deve ser incluído no programa. Existem os manipuladores simples (sem argumentos) e os manipuladores com argumentos. Os manipuladores simples são os seguintes: oct - o valor octal; dec - o valor decimal; hex - o valor hexadecimal; endl - ‘\n’ e apagar o buffer; ends - ‘\0’ e apagar o buffer só para saída ; flush - apagar o buffer só para saída ; ws - eliminação de espaços entre símbolos Os manipuladores com argumentos são seguintes: ----a 0X--A 0XA A 12.1 setfill(int caracter); setprecision(int pr); setw(int w); resetiosflags(long n); setiosflags(long n); etc. cout << setw(5) << setfill('-') << hex << 10 << endl; cout << setiosflags(ios::uppercase|ios::internal|ios::showbase) << setfill('-') << hex << setw(5) << 10 << endl; cout << 10 << endl; cout << resetiosflags(ios::showbase) << 10 << endl; cout << setiosflags(ios::fixed) << setprecision(1) << 12.12345 << endl; A área de acção para cada manipulador começa com o aparecimento do manipulador e acaba depois de cancelado por outro manipulador cout << hex << a << b << c << dec << d; Vamos considerar como podemos definir manipuladores novos. class my_f {}; ostream& operator<<(ostream& s,my_f) { s.width(5); s.fill('-'); s.flags(ios::showpos); return s; } my_f MF; cout << MF << 47 << endl; --+47 Podemos também definir os manipuladores novos com argumentos. Vamos considerar, por exemplo, o manipulador wp(n,m) que especifica a largura do campo n e precisão m para os valores com vírgula flutuante. class my_manip { int n,m; ostream& (*f)(ostream&,int,int); public: my_manip(ostream& (*F)(ostream&,int,int),int N, int M) : f(F), n(N), m(M) {} friend ostream& operator<<(ostream& s,my_manip& my) { return my.f(s,my.n,my.m); } }; ostream& wi_pre(ostream& s, int n, int m) { s.width(n); s.flags(ios::fixed); s.precision(m); return s; } my_manip wp(int n, int m) { return my_manip(wi_pre,n,m); } int main(int argc, char* argv[]) { cout << 12.8765 << endl << wp(10,2) << 12.8765 << endl; return 0; } 12.8765 12.88 Ficheiros e Strings Strings e Ficheiros - Classes (1) • Existem classes específicas para trabalhar com strings e ficheiros em C++ • As operações I/O efectuam-se através de streams Strings e Ficheiros - Classes (2) • Existem 3 tipos de streams – streams de leitura – streams de escrita – streams de leitura/escrita Strings e Ficheiros - Classes (3) • Classes de leitura para ficheiros e strings: – ifstream – istrstream • Classes de escrita para ficheiros e strings: – ofstream – ostrstream Strings e Ficheiros - Classes (4) • Classes de leitura/escrita para ficheiros e strings: – fstream – strstream Strings e Ficheiros - Classes (5) • Todas estas classes são derivadas da classe ios STRINGS Strings - Construção (1) • Classe istrstream – o objecto istrstream pode ser construído da seguinte forma: – istrstream in_str(char* psz); – o objecto in_str irá ficar associado a uma string apontada por psz Strings - Construção (2) • Classe istrstream – o objecto istrstream também pode ser construído da seguinte forma: – istrstream in_str(char* pch, int nLength); – o objecto in_str irá ficar associado a um array de caracteres normal com nLength caracteres Strings - Construção (3) • Classe ostrstream – o objecto ostrstream pode ser construído da seguinte forma: – ostrstream out_str; – é criado um objecto out_str para escrita com reserva dinâmica de memória para novos caracteres Strings - Construção (4) • Classe ostrstream – o objecto ostrstream também pode ser construído da seguinte forma: – ostrstream out_str(char* pos, int Len, int OpenMode); – OpenMode pode especificar ios::app ou ios::ate – pos aponta para uma string Strings - Construção (5) • Classe strstream = istrstream + ostrstream – o objecto strstream pode ser construído da seguinte forma: – strstream io_str; – objecto io_str criado com buffer interno e dinâmico, inicialmente vazio Strings - Construção (6) • Classe strstream = istrstream + ostrstream – o objecto strstream também pode ser construído da seguinte forma: – strstream io_str(char* pos, int Len, int OpenMode); – pos aponta para uma string já existente com Len caracteres Strings - Construção (7) • Sempre que possível deve deixar-se o objecto efectuar a reserva dinâmica do buffer interno. Strings - Construção (7) char* a_str = "Ola"; // 3 caracteres ostrstream str(a_str, 10); str << "nova string"; – Irá ocorrer um erro pois a_str só tem reservados 3 caracteres Strings - Construção (8) • A construção aconselhada seria: ostrstream str; str << "Ola"; str << "nova string"; OK - memória reservada dinamicamente FICHEIROS 1. #include <fstream.h> 2. fstream source; o nome lógico o nome do ficheiro 3. source.open(”my.txt", ios::in | ios::nocreate); if(!source.good()) { cerr << "Nao foi possivel abrir o ficheiro fonte" << endl; exit(1); // pode usar controlo de excepções } 4. template <class Type> fstream& operator>>(fstream& source, set<Type> &S) {................................ return source; } 5. source.close(); Ficheiros - Construção (1) • Classe ifstream – o objecto ifstream pode ser construído da seguinte forma: – ifstream in_file; – o objecto in_file é criado mas nenhum ficheiro é aberto Ficheiros - Construção (2) • Classe ifstream – o objecto ifstream também pode ser construído da seguinte forma: – ifstream in_file("file.dat"); – o objecto in_file é criado e o ficheiro file.dat é aberto em modo de texto para leitura Ficheiros - Construção (3) • Qualquer construtor para objectos do tipo ficheiro, constrói apenas o objecto ficheiro sem abrir o ficheiro “físico” se não for dado o nome do ficheiro aquando da construção Ficheiros - Construção (4) • Classe ofstream – o objecto ofstream pode ser construído da seguinte forma: – ofstream out_file("file.dat", ios::binary); – o objecto out_file quando criado, é associado ao ficheiro file.dat. Este é aberto em modo binário para escrita Ficheiros - Construção (5) • O objecto na construção aceita os seguintes parâmetros: Flag ios::app ios::ate ios::in ios::out ios:.binary Significado os dados são escritos no fim do ficheiro o apontador vai para o fim do ficheiro quando este é aberto o ficheiro é aberto para leitura o ficheiro é aberto para escrita o ficheiro é aberto em modo binário. Se ausente o ficheiro é aberto em modo texto. ios::trunc apaga o conteúdo de um ficheiro quando este é aberto para escrita ios::nocreate falha a abertura do ficheiro se este não existir (apenas para ficheiro de escrita) ios::noreplace não substitui um ficheiro existente. Se este existir, falha a abertura Ficheiros - Construção (6) • Classe fstream = ifstream + ofstream – o objecto fstream pode ser criado da seguinte forma: – fstream io_file("file.dat", ios::in | ios::out | ios::binary); – é criado o objecto io_file para leitura/escrita em modo binário, associado ao ficheiro file.dat Ficheiros - Verificação (1) • A verificação da abertura efectiva de um ficheiro deve ser sempre realizada antes de efectuar qualquer operação I/O sobre este Ficheiros - Verificação (2) • Exemplos para verificação da abertura de um ficheiro if(in_file.bad()) { cerr << "o ficheiro nao foi aberto" << endl; exit(1); } if(!in_file) { cerr << "o ficheiro nao foi aberto" << endl; exit(1); } if(in_file.is_open() == 0) { cerr << "o ficheiro nao foi aberto" << endl; exit(1); } Ficheiros - Verificação (3) • O método eof() permite saber se foi atingido o fim do ficheiro while(!io_file.eof()) { // lê ficheiro // … } LEITURA / ESCRITA Streams - Leitura/Escrita (1) • A leitura de strings e ficheiros é efectuada de forma semelhante • As suas classes derivam de uma classe I/O comum - classe ios Streams - Leitura/Escrita (2) char str[10]; istrstream in_str("Ola"); ifstream in_file("file.dat"); in_str >> str; in_file >> str; in_str.read(str, 3); in_file.read(str, 3); in_str.getline(str,3); in_file.getline(str, 3); • Leituras de uma string e de um ficheiro para str efectuadas de forma idêntica Streams - Leitura/Escrita (3) char str1[] = "PP1"; strstream out_str; fstream out_file("file2.dat", ios::out); out_str << str1; out_file << str1; out_str.write(str1, 6); out_file.write(str1, 6); • Escrita efectuada, numa string e num ficheiro, de forma idêntica int main(int argc, char* argv[]) Aveiro { char str[10]; istrstream in_str("Ola"); ifstream in_file("file.dat"); // Aveiro in_file.getline(str, 5); cout << str << endl; // O resultado: Avei in_str >> str; cout << str << endl; // O resultado: Ola in_file >> str; // O resultado: ro cout << str << endl; char str1[10] = "PP1"; strstream out_str; fstream out_file("file2.dat", ios::out); out_str << str1; PP1 out_file << str1; out_str.read(str, 1); cout << str << endl; // O resultado: Po ...................... Destrutores (1) • Todos os objectos têm destrutores que libertam o espaço reservado para o objecto Destrutores (2) • No caso de ficheiros é boa política efectuar o fecho do objecto (ficheiro) assim que este já não seja necessário. Desta forma são libertados recursos do sistema mais cedo int main(int argc, char* argv[]) { fstream source,destination; source.open("source.txt", ios::in | ios::nocreate); if(!source.good()) { cerr << "Nao foi possivel abrir o ficheiro fonte" << endl; exit(1); } destination.open("out1.txt", ios::out); if(!destination) { cerr << "Nao foi possivel abrir o ficheiro out1" << endl; exit(1); } } char str[50]; source >> str; cout << str << endl; destination.write(str,7); source >> str; cout << str << endl; destination.write(str,7); source >> str; cout << str << endl; destination.write(str,7); source >> str; cout << str << endl; destination.write(str,7); source.close(); destination.close(); return 0; Aveiro Lisboa Porto Coimbra Faro Braga Aveiro Lisboa Porto Coimbra int main(int argc, char* argv[]) { fstream source,destination; StrString my_str; int no_of_caracteres = 0, no_of_words = 0; /////////////////////////////////////////////////////////////////// // Abertura dos ficheiros /////////////////////////////////////////////////////////////////// source.open("source.txt", ios::in | ios::nocreate); if(!source.good()) { cerr << "Nao foi possivel abrir o ficheiro fonte" << endl; exit(1); } destination.open("out1.txt", ios::out); if(!destination) { cerr << "Nao foi possivel abrir o ficheiro out1" << endl; exit(1); } source >> my_str; // leitura da linha no_of_caracteres = my_str.length(); // incrementa // o nº de caracteres no_of_words = my_str.words(); // incrementa o nº de palavras cout << my_str << endl; // escreve a linha destination << my_str << endl; // escreve a linha // em destination my_str = " ------------- Estatistica --------------:"; cout << my_str << endl; cout << "Numero de caracteres = " << no_of_caracteres << endl; cout << "Numero de palavras = " << no_of_words << endl; source.close(); destination.close(); return 0; }