1 Востаннє редагувалося М18х00 (26.09.2017 18:27:03)

Тема: Будь ласка, поясніть виключення, надайте прикладів

Не зрозумію як діють винятки. Наприклад в мене в прозі трапляється десь ділення на нуль.
Звісно я бажаю щоб вийняток якось мені повидомив, а якщо все в порядку то щоб прога продовжувала роботу.
Будь ласка покажить на прикладах, які ці винятки бувають і як їх ловити та обробляти.
Цей код падає при діленні на нуль, й припиняє роботу якщо все гаразд.

#include <iostream>
#include <cstring>
#include <string>

int main()
{
    int A=25, B=5, C=0;
    std::cout<<"A "<<std::endl;
    std::cin>>A;
    std::cout<<"B "<<std::endl;
    std::cin>>B;


    try
    {
      C = A/B;
      throw "Error";
    }
    catch( const char* e)
     {
         std::cout<<e<<std::endl;
     }
return 0;
}
Подякували: 0x9111A1

2

Re: Будь ласка, поясніть виключення, надайте прикладів

"Правильно поставлене питання містить половину відповіді"

Подякували: koala1

3 Востаннє редагувалося М18х00 (26.09.2017 18:46:15)

Re: Будь ласка, поясніть виключення, надайте прикладів

Та я бажаю кодити навчітися.  Ну а якшо трохи щось плутаю, саме питання здається ж ясне.



Тобто я чекав що це саме try{} зловить ділення на нууль і передасть throw в catch( const char* e)
А тут що?

4

Re: Будь ласка, поясніть виключення, надайте прикладів

Ділення на нуль існувало в C (а відтак, внаслідок сумісності, і в C++) до виняткових ситуацій, а відтак, виняткової ситуації не створює. Якщо ви хочете, щоб тут була виняткова ситуація, коли c==0, вам треба в try це перевіряти if-ом і робити throw (а ви чого очікували?).
Якщо ви хочете просто перехопити виняткову ситуацію, то візьміть, скажімо, vector::at і дайте неправильний індекс:

vector<int> x(9);
try{ 
  for(int i =0;i<10;++i){
    x.at(i)=i;
  }
  cout<<"Все гаразд"<<endl;
} 
catch(out_of_range exception) {
  cout<<exception.what();
}

Які винятки бувають - в C++ що завгодно можна кидати як виняток: число, рядок, посилання.

Подякували: Betterthanyou, P.Y., leofun013

5

Re: Будь ласка, поясніть виключення, надайте прикладів

Треба перевіряти умову, чи знаменник == 0. У вашому прикладі throw відбувається при будь-якій ситуації, а потрібно щоби виключення генерувалося тільки тоді, коли робиться щось, що не повинно робитися.
Запустіть цей код і переконайтеся що при присвоєнні В нуля, програма все одно продовжить виконання, але згенерує повідомлення про помилку:

код 1
#include <iostream>
#include <cstring>
#include <string>

int main()
{
    int A = 25, B = 5, C = 0;
    std::cout << "A " << std::endl;
    std::cin >> A;
    std::cout << "B " << std::endl;
    std::cin >> B;


    try
    {
        if (B == 0)
            throw "Error";
        C = A / B;
    }
    catch (const char* e)
    {
        std::cout << e << std::endl;
    }
    std::cout << "Result is " << C << std::endl;

    return 0;
}

І запустіть наступний код. Програма буде крашитись якщо В буде 0.

код 2
#include "stdafx.h"
#include <iostream>
#include <cstring>
#include <string>

int main()
{
    int A = 25, B = 5, C = 0;
    std::cout << "A " << std::endl;
    std::cin >> A;
    std::cout << "B " << std::endl;
    std::cin >> B;


    try
    {
        //if (B == 0)
        //    throw "Error";
        C = A / B;
    }
    catch (const char* e)
    {
        std::cout << e << std::endl;
    }
    std::cout << "Result is " << C << std::endl;

    return 0;
}
Подякували: М18х00, Betterthanyou, leofun013

6

Re: Будь ласка, поясніть виключення, надайте прикладів

Дуже дякую!!!!

7 Востаннє редагувалося М18х00 (26.09.2017 19:11:52)

Re: Будь ласка, поясніть виключення, надайте прикладів

Вирішив почітати книгу, C++ Templates: The Complete Guide, а там ціх винятків хоч греблю гати.
Я якось пропускав їх завжди раніш.
А воно хоч здається й зрозуміле, але ж якщо я не можу сам їх використати, то деж там зрозуміло.

if (elems.empty()) {
 throw std::out_of_range("Stack<>::top(): empty stack");
 }
 return elems.back(); // return copy of last element
}
As you can see, the class template is implemented by using a class template of the C++ standard library: vector<>.
As a result, we don't have to implement memory management, copy constructor, and assignment operator, so we can
concentrate on the interface of this class template

8

Re: Будь ласка, поясніть виключення, надайте прикладів

Уточню: throw загалом не призначене для використання в блоці try (хоча його і можна туди запхати). throw має використовуватися в функції, яка буде викликана в блоці try (чи іншій функції, яка, своєю чергою буде викликана в try чи іншій функції ad infinitum). Тобто щось погане стається в одному місці, а обробка відбувається в зовсім іншому.

Подякували: М18х00, LoganRoss, leofun013

9

Re: Будь ласка, поясніть виключення, надайте прикладів

Якщо ви програмуєте під Windows, то можете спробувати цей код https://msdn.microsoft.com/uk-ua/librar … s.85).aspx
Він обробить виняток ділення на нуль

#include <iostream>
#include <cstring>
#include <string>
#include <Windows.h>

BOOL SafeDiv(INT32 dividend, INT32 divisor, INT32 *pResult)
{
    __try
    {
        *pResult = dividend / divisor;
    }
    __except (GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO ?
        EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
    {
        std::cerr << "Error! Integer division by zero\n";
        return FALSE;
    }
    return TRUE;
}


int main()
{
    int A = 25, B = 5, C = 0;
    std::cout << "A " << std::endl;
    std::cin >> A;
    std::cout << "B " << std::endl;
    std::cin >> B;

    if(SafeDiv(A, B, &C))
        std::cout << "A/B="<<C<<std::endl;
    return 0;
}

А також зверніть увагу на ще один спосіб https://msdn.microsoft.com/ru-ru/library/5z4bw5h5.aspx

// crt_settrans.cpp  
// compile with: /EHa  
#include <stdio.h>  
#include <windows.h>  
#include <eh.h>  
  
void SEFunc();  
void trans_func( unsigned int, EXCEPTION_POINTERS* );  
  
class SE_Exception  
{  
private:  
    unsigned int nSE;  
public:  
    SE_Exception() {}  
    SE_Exception( unsigned int n ) : nSE( n ) {}  
    ~SE_Exception() {}  
    unsigned int getSeNumber() { return nSE; }  
};  
int main( void )  
{  
    try  
    {  
        _set_se_translator( trans_func );  
        SEFunc();  
    }  
    catch( SE_Exception e )  
    {  
        printf( "Caught a __try exception with SE_Exception.\n" );  
    }  
}  
void SEFunc()  
{  
    __try  
    {  
        int x, y=0;  
        x = 5 / y;  
    }  
    __finally  
    {  
        printf( "In finally\n" );  
    }  
}  
void trans_func( unsigned int u, EXCEPTION_POINTERS* pExp )  
{  
    printf( "In trans_func.\n" );  
    throw SE_Exception();  
}  
Подякували: М18х00, leofun012

10

Re: Будь ласка, поясніть виключення, надайте прикладів

Так, дуже дякую!!!

11

Re: Будь ласка, поясніть виключення, надайте прикладів

Так, надзвичайно цікаво, справді дякую.

Але в мене не працює error: expected 'catch' before '__except'|

12

Re: Будь ласка, поясніть виключення, надайте прикладів

У мене компілятор gcc не пам'ятаю якої моделі, чі можливо до нього якось прикрутити ці виключення?

13 Востаннє редагувалося Betterthanyou (26.09.2017 20:08:50)

Re: Будь ласка, поясніть виключення, надайте прикладів

Може погугліть, бо я не працював з gcc

російськомовний ресурс

14

Re: Будь ласка, поясніть виключення, надайте прикладів

Якщо у вас gcc на лінуксі, то http://rosettacode.org/wiki/Detect_division_by_zero#C++

Подякували: Betterthanyou, leofun012