• Nenhum resultado encontrado

6.4 Try, Throw e Catch

6.4.1 Exemplo

Os códigos 6.3 e 6.4 exemplificam o uso. Código 6.3: Exceções #include <iostream>

using namespace std ;

// c l a s s e para o tratamento de uma excecao de d i v i s a o por zero

c l a s s DivideByZeroException

{

public:

DivideByZeroException ( ) : message ( " voce tentou d i v i d i r por zero " ) { }

const char∗ what ( ) const

{ return message ; }

private:

const char∗ message ;

} ; // funcao que lanca a excecao

double q u o t i e n t ( int numerador , int denominador )

{

// momento em que a e x c e eh lancada ! ! !

i f ( denominador == 0) throw DivideByZeroException ( ) ; return ( double ) numerador / denominador ;

}

Note que o comando throw chama o construtor da classe DivideByZeroEx- ception criando, dessa forma, um objeto dessa classe. Este objeto será lançado pelo comando throw, e quando o erro for detectado pelo bloco try o comando catch capturará este objeto e irá tratar adequadamente a exceção. O comando throw pode lançar objetos, ou mesmo tipos primitivos. E será este tipo que definirá qual bloco catch tratará da exceção em questão.

Código 6.4: Exceções funcionando #include " e x c e c o e s . cpp "

// programa t e s t e para t r a t a r uma excecao

i n t main ( )

{

i n t x , y ;

double r e s u l t a d o ;

cout << " D i g i t e d o i s numeros para serem d i v i d i d o s (CTRL + Z para acabar ) : " ; while ( c i n >> x >> y ) { try { r e s u l t a d o = q u o t i e n t ( x , y ) ;

cout << "O qu ocie nt e eh " << r e s u l t a d o << endl ; }

catch ( DivideByZeroException ex )

{

cout << " Ocorreu uma excecao : " << ex . what ( ) ; cout << endl ;

} cout << " D i g i t e d o i s numeros para serem d i v i d i d o s (CTRL + Z para acabar ) : " ; } return 0 ; } c a t c h ( i n t x ) { . . . } c a t c h ( double y ) { . . . }

Estes são blocos sintaticamente corretos, contudo, costuma-se escolher ob- jetos, pois estes podem transportar alguma informação útil para o tratamento da exceção. Caso se deseje capturar todas as exceções, de qualquer tipo, utiliza-se reticências entre os parênteses que sucedem o catch:

c a t c h( . . . ) {}

Se nenhum bloco catch for capaz de capturar uma determinada exceção, o programa é abortado. Caso contrário, ele continua com a primeira instrução após o último bloco catch (logo, qualquer parte do bloco try que não tenha sido executada antes do lançamento da exceção é ignorada).

Cabe ainda ressaltar que os efeitos colaterais do polimorfismo valem aqui também. Caso o tipo de alguma exceção seja uma classe mãe, qualquer classe derivada desta será capturada pelo respectivo bloco catch da classe mãe.

6.4.2 Exercício

1) Crie uma situação semelhante ao exemplo em que ocorra um erro por estouro (overflow). Utilize variáveis que estouram mais comumente, como short int ou byte.

Processamento de Arquivos

As variáveis de programas são temporárias, isto é, serão armazenadas na memória do seu computador e, assim que seu programa finalizar, elas serão perdidas. Contudo, existem diversas situações em que pode ser bem interes- sante guardar algumas informações para a próxima vez que o programa executar (imagine não poder salvar seu jogo no meio e continuá-lo depois), ou mesmo para utilizar estas informações de alguma outra forma.

Para fazer isto utilizamos arquivos, que são armazenados em dispositivos secundários de armazenamento, como o disco rígido do seu computador, e, desta forma, torna-se bem mais difícil perder os dados. E neste capítulo examinaremos a manipulação de arquivos em C++.

7.0.3 Arquivos em C++

Para realizar o processamento de arquivos em C++, devem ser incluídos os arquivos de cabeçalho <iostream> e <fstream>. O cabeçalho <iostream> inclui objetos e estruturas que são utilizados na entrada e saída padrão de dados, mas que também são válidos para manipular arquivos.

Já o cabeçalho <fstream> inclui as definições das classes ifstream (para realizar a entrada de um arquivo), ofstream (para realizar a saída para um arquivo) e fstream (para entrada e saída de um arquivo). Todas essas classes herdam das classes definidas em <iostream> de acordo com o esquema abaixo.

7.0.4 Arquivo Seqüencial

Como o nome já diz, um arquivo seqüencial é simplesmente um arquivo de acesso seqüencial, isto é, para acessar um dado no fim do arquivo é preciso percorrer todo o arquivo antes. Para criar um arquivo seqüencial, é preciso criar um objeto ’ofstream’ chamando o seu construtor com dois parâmetros: o nome do arquivo e o modo como este aquivo será aberto.

7.0.5 Modos de Abertura

ios::app Grava toda saída no fim do arquivo.

ios::ate Abre um arquivo para saída e avança até o fim do arquivo. ios::in Abre um arquivo para entrada.

ios::out Abre um arquivo para saída.

ios::trunc Abre um novo arquivo, eliminando antigo se este já existir. ios::binary Abre um arquivo para entrada ou saída binária.

Em seguida, a entrada para o arquivo é idêntica a entrada padrão de dados. Observe o código 7.1 de exemplo, que realiza um cadastro de filmes com os seguintes campos: Código, Nome e Nota.

Agora, quando criamos um arquivo seqüencial, é bem provável que queiramos abri-lo em uma próxima oportunidade. Para realizar isso, o procedimento é anál- ogo ao de criação de um arquivo seqüencial. Primeiro, deve-se criar um objeto ifstream chamando o seu construtor com os seus parâmetros: nome do arquivo

Código 7.1: Escrevendo em Arquivos #include <c s t d l i b > #include <iostream> #include <ofstream> i n t main ( ) {

// c o n s t r u t o r de ofstream abre o arquivo

ofstream f i l e ( " Movie . dat " , i o s : : out ) ;

i f ( ! f i l e )

// operador ! sobrecarregado

{

c e r r << " Arquivo nao encontrado . . . " << endl ; e x i t ( 1 ) ;

}

cout << " D i g i t e o codigo do filme , o nome e a nota . \ n " << endl " ;

i n t cod ;

char nome [ 50 ] ; i n t nota ;

while ( c i n >> cod >> nome >> nota ) {

f i l e << cod << ’ ’ << nome << ’ ’ << nota << ’\ n ’ ; cout << " ? " ;

}

return 0 ; }

e modo de abertura do arquivo. Em seguida, basta ler os valores do arquivo do mesmo modo que se faz com a entrada de dados padrão, trocando cin pelo objeto criado.

’objeto criado’ » ’variáveis que armazenarão os valores lidos do ar- quivo’

Exercício:

Primeiramente, utilize o código dado para criar um arquivo seqüencial de filmes. Em seguida, faça um programa que leia deste arquivo seqüencial e escreva na tela apenas o nome dos filmes com nota acima de 6.

7.1

Arquivo Aleatório

Um arquivo seqüencial resolve muitas vezes o nosso problema, contudo, apresenta um grave problema de tempo: seu mecanismo é pouco eficiente. Imagine-se na frente de um caixa eletrônico, querendo realizar uma retirada de dinheiro, e o sistema verificando seqüencialmente num arquivo de todas as contas do banco, se sua conta possui o saldo suficiente. É bem provável que você desista de retirar o dinheiro. Para resolver este tipo de problema, utilizam- se arquivos de acesso aleatório.

A idéia básica consiste em saber de antemão onde se encontra a infor- mação desejada, e buscá-la diretamente no local apropriado. Isto pode ser feito utilizando-se estruturas de tamanho fixo. Dessa forma, é possível calcular de forma rápida que o registro de chave 5 iniciará na posição 5 vezes o tamanho da estrutura (considerando iniciar na chave 0).

Implementar este tipo de arquivo em C++ também não impõe muitas difi- culdades. Os próprios objetos ostream e istream possuem métodos write e read, respectivamente, nos quais é possível especificar um offset para ir direto para determinado ponto do arquivo. Entretanto, foge um pouco do escopo do curso detalhar todas as técnicas e métodos de manipulação de arquivos.

Standard Template Library

A STL é uma parte extremamente importante da biblioteca padrão do C++. Na prática, programadores passam a maior parte do tempo programando so- mente com a STL, usando pouco as outras facilidades oferecidas pela biblioteca padrão completa. Na STL, estão declaradas estruturas de dados muito versáteis e diversos algoritmos úteis, de forma a facilitar a programação.

O uso dessa biblioteca evita que seja necessário, por exemplo, implementar e depurar listas encadeadas.Além disso, houve uma grande preocupação com o desempenho das classes e funções, de modo que dificilmente uma implemen- tação própria pode oferecer vantagens consistentes de performance, sem falar nas facilidades que a STL provê.

No documento C++ e Orientação a Objetos (páginas 61-69)

Documentos relacionados