Mostrando postagens com marcador Exceções. Mostrar todas as postagens
Mostrando postagens com marcador Exceções. Mostrar todas as postagens

segunda-feira, 10 de dezembro de 2012

EOF


Alguns problemas do spoj especificam o final da entrada da seguinte maneira:
A entrada é terminada por fim de arquivo (EOF). EOF é End Of File (Fim de Arquivo).

Como detectar o fim de arquivo em um programa C?

Na linguagem C, a maneira utilizada para indicar condições excepcionais durante a execução do programa é funções que retornam um "funny values" ou um status code. 

Mais sobre exceções em C :
http://marathoncode.blogspot.com.br/2012/11/excecoes-em-c.html

Sobre outros "problemas" da linguagem C:
http://marathoncode.blogspot.com.br/2012/07/porque-c-nao-e-minha-linguagem-de.html

Todo bug lo suficientemente avanzado es indistinguible de una feature.
– Rich Kulawiec


Em caso de sucesso, a função scanf retorna o número de itens da lista de argumentos  lidos com sucesso. Esta contagem pode igualar o número esperado de itens ou ser menos (mesmo zero) devido a uma falha de correspondência, um erro de leitura,  ou o alcance do fim de arquivo.

Se um erro de leitura acontece ou o fim-de-arquivo é atingido durante a leitura,  um indicador adequado é sinalizado. E, se acontece alguma coisa antes de um dado pode ser lido com sucesso, EOF é retornado.

Geralmente, EOF é uma definição de macro do tipo int que se expande em uma constante inteira negativa (geralmente, -1).

http://www.cplusplus.com/reference/cstdio/scanf/

Tratamento do fim de arquivo em C
while( scanf("%d",&t) != EOF ){
}
ou
while( scanf("%d",t) > 0  ){
}
Tratamento do fim de arquivo em C++
while( cin >> t){
}
ou
cin >> t;
while( !cin.eof()  ){
}
http://www.cplusplus.com/reference/ios/ios/eof/

Existem vários exemplos na diferença do tratamento de erros entre C e C++.

Tratamento de falha de alocação em C
#include <stdlib.h>
#include <stdio.h>

int main(){

 int size = 1000000000;
 int *p;
 
 p = (int*)malloc(size*sizeof(int));
 
 if(p==NULL){
  printf("Memoria insuficiente");
  system("PAUSE");
  exit(1);
 }

 system("PAUSE");
 return 0;

}
Tratamento de falha de alocação em C++
#include <iostream>
#include <new>

using namespace std;

int main(){

 int size = 1000000000;
 int *p;
 
 try{
  p = new int[size];
 }catch( bad_alloc& ba){
  cerr << "bad_alloc caught: " << ba.what() << endl;
 }
 system("PAUSE");
 return 0;
}
#include <iostream>
#include < new >

using namespace std;

int main(){

 int size = 1000000000;
 int *p;
 
 
 p = new (nothrow) int[size];
 
 if(p==0){
  cerr << "bad_alloc caught" << endl;
  system("PAUSE");
  
 }
 return 0;
}
http://www.cplusplus.com/reference/new/bad_alloc/

Checagem de índice fora da faixa
#include 
#include 
#include 
using namespace std;

int main(){
 
 int v1[10];
 v1[11] = 5;//C não tem tratamento para índice fora da faixa
 
 //C++ verifica os indices fora da faixa do vector com a função at 
 vector  v2(10); 
 try{
  v2.at(11) = 6;
 }catch (out_of_range& oor) {
    cerr << "Out of Range error: " << oor.what() << endl;
 } 
 
 system("PAUSE");
 

}

http://www.cplusplus.com/reference/vector/vector/at/
http://www.cplusplus.com/reference/stdexcept/out_of_range/

quarta-feira, 28 de novembro de 2012

Exceções em C



Uma exceção é um sinal que indica que algum tipo de condição excepcional ocorreu durante a execução do programa. Assim, exceções estão associadas a condições de erro que não tinham como ser verificadas durante a compilação do programa.

Algumas linguagem possuem facilidades de tratamento de exceção, como por exemplo, Java, ADA,
Python e Ruby. A linguagem C carece dessa facilidade de tratamento de exceção.

Na linguagem C, outros métodos pode ser usado para indicar exceções e tratá-las. Uns dos métodos mais utilizados é funções que retornam status code ou "funny values" para indicar condições excepcionais.


#include

int main(){
 int * p;

 p = (int * )malloc(10*sizeof(int));

 if(!p){
  printf("Memória insuficiente\n");
 }else{
  printf("Memória alocada com sucesso\n");
 }

}


Esse método não permite detectar e tratar outros tipos de exceções, como por exemplo, divisão por zero.
Para detectar e tratar esse tipo de exceção, vamos utilizar os UNIX Signal. Para isso, precisamos definir tratador de exceção que vai ser invocado quando um sinal do sistema for recebido.

Ponteiro para um função de tratamento do sinal. A função de tratamento recebe um sinal int que é o sinal que ela trata
typedef void (*__p_sig_fn_t)(int);  


Associa ao sinal int a uma função que trata o sinal __p_sig_fn_t.
_CRTIMP __p_sig_fn_t __cdecl signal(int, __p_sig_fn_t);


Sinais que podem ser detectados

#define SIGINT 2 /* Interactive attention */
#define SIGILL 4 /* Illegal instruction */
#define SIGFPE 8 /* Floating point error */
#define SIGSEGV 11 /* Segmentation violation */
#define SIGTERM 15 /* Termination request */
#define SIGBREAK 21 /* Control-break */
#define SIGABRT 22 /* Abnormal termination (abort) */

Exemplo
#include <stdio.h> 
#include <stdlib.h>
#include <signal.h>

void float_error(int i){
 signal(SIGFPE, float_error);
 printf("You have raised a floating point error\n"); 
 exit(0);
}

int main(){
  int a,b;
    
  signal(SIGFPE, float_error );

  scanf("%d %d",&a,&b);
  
  printf("%d\n",a/b); 

  return 0;
}



Entrada
2 0

Saída
2 0
You have raised a floating point error
Pressione qualquer tecla para continuar. . .

Entrada
4 2
Saída
2


Tratamento de Exceção

Para realizar o tratamento de exceção, precisamos usar setjmp salvar o ambiente no ponto que  ocorreu a exceção e usar longjmp (non-local goto) para realizar seu trabalho do mal.

/*
 * The buffer used by setjmp to store the information used by longjmp
 * to perform it's evil goto-like work. The size of this buffer was
 * determined through experimentation; it's contents are a mystery.
 * NOTE: This was determined on an i386 (actually a Pentium). The
 *       contents could be different on an Alpha or something else.
 */
#define _JBLEN 16
#define _JBTYPE int
typedef _JBTYPE jmp_buf[_JBLEN];


/*
 * The function provided by CRTDLL which appears to do the actual work
 * of setjmp.
 */
_CRTIMP int __cdecl _setjmp (jmp_buf);


/*
 * Return to the last setjmp call and act as if setjmp had returned
 * nVal (which had better be non-zero!).
 */
_CRTIMP void __cdecl longjmp (jmp_buf, int) __MINGW_ATTRIB_NORETURN;

Exemplo

#include
#include
#include
#include
int a,b;
jmp_buf env;


int main(){
  
  void float_error(int);
  
  signal(SIGFPE, float_error );

  setjmp(env);

  scanf("%d %d",&a,&b);
  
  printf("%d\n",a/b); 

  return 0;
}

void float_error(int i){
 signal(SIGFPE, float_error);
 printf("You have raised a floating point error\n"); 
 printf("Entre com novos valores:\n");
 longjmp(env,0);
}

Execução

2 0
You have raised a floating point error
Entre com novos valores:
4 2
2

Outras referências:
http://www.vivaolinux.com.br/artigo/Tratamento-de-excecoes-na-linguagem-C?pagina=1 

http://sergioprado.org/tratamento-de-erros-em-linguagem-c/ 

http://www.vivaolinux.com.br/script/Excecoes-em-C-atraves-de-trythrowcatch