Try catch statements in C

前端 未结 13 1518
眼角桃花
眼角桃花 2020-11-27 10:06

I was thinking today about the try/catch blocks existent in another languages. Googled for a while this but with no result. From what I know, there is not such a thing as tr

13条回答
  •  心在旅途
    2020-11-27 10:35

    Warning: the following is not very nice but it does the job.

    #include 
    #include 
    
    typedef struct {
        unsigned int  id;
        char         *name;
        char         *msg;
    } error;
    
    #define _printerr(e, s, ...) fprintf(stderr, "\033[1m\033[37m" "%s:%d: " "\033[1m\033[31m" e ":" "\033[1m\033[37m" " ‘%s_error’ " "\033[0m" s "\n", __FILE__, __LINE__, (*__err)->name, ##__VA_ARGS__)
    #define printerr(s, ...) _printerr("error", s, ##__VA_ARGS__)
    #define printuncaughterr() _printerr("uncaught error", "%s", (*__err)->msg)
    
    #define _errordef(n, _id) \
    error* new_##n##_error_msg(char* msg) { \
        error* self = malloc(sizeof(error)); \
        self->id = _id; \
        self->name = #n; \
        self->msg = msg; \
        return self; \
    } \
    error* new_##n##_error() { return new_##n##_error_msg(""); }
    
    #define errordef(n) _errordef(n, __COUNTER__ +1)
    
    #define try(try_block, err, err_name, catch_block) { \
        error * err_name = NULL; \
        error ** __err = & err_name; \
        void __try_fn() try_block \
        __try_fn(); \
        void __catch_fn() { \
            if (err_name == NULL) return; \
            unsigned int __##err_name##_id = new_##err##_error()->id; \
            if (__##err_name##_id != 0 && __##err_name##_id != err_name->id) \
                printuncaughterr(); \
            else if (__##err_name##_id != 0 || __##err_name##_id != err_name->id) \
                catch_block \
        } \
        __catch_fn(); \
    }
    
    #define throw(e) { *__err = e; return; }
    
    _errordef(any, 0)
    

    Usage:

    errordef(my_err1)
    errordef(my_err2)
    
    try ({
        printf("Helloo\n");
        throw(new_my_err1_error_msg("hiiiii!"));
        printf("This will not be printed!\n");
    }, /*catch*/ any, e, {
        printf("My lovely error: %s %s\n", e->name, e->msg);
    })
    
    printf("\n");
    
    try ({
        printf("Helloo\n");
        throw(new_my_err2_error_msg("my msg!"));
        printf("This will not be printed!\n");
    }, /*catch*/ my_err2, e, {
        printerr("%s", e->msg);
    })
    
    printf("\n");
    
    try ({
        printf("Helloo\n");
        throw(new_my_err1_error());
        printf("This will not be printed!\n");
    }, /*catch*/ my_err2, e, {
        printf("Catch %s if you can!\n", e->name);
    })
    

    Output:

    Helloo
    My lovely error: my_err1 hiiiii!
    
    Helloo
    /home/naheel/Desktop/aa.c:28: error: ‘my_err2_error’ my msg!
    
    Helloo
    /home/naheel/Desktop/aa.c:38: uncaught error: ‘my_err1_error’ 
    

    Keep on mind that this is using nested functions and __COUNTER__. You'll be on the safe side if you're using gcc.

提交回复
热议问题