iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 27
0
自我挑戰組

30 Days 如何把 C 語言偽裝成高階語言 OWO /系列 第 28

Day 27: 例外處理系列:研究進行中 :大量優化、黑魔法

▌第一次閱讀本系列的,可以先看:

本系列的大綱 傳送門


▌第一次閱讀例外處理系列,可以先看:

例外處理系列 開始第一篇 傳送門


本例外處理系列為【實驗性質】,研究進行中......。

  • 可以在拋出錯誤處定義錯誤類型,這意味一個函式不再只能拋出一種錯誤。
  • try 不需顯式地指出錯誤類型,默認為函式拋出的錯誤,有需要時亦可加上。
  • 連續的 back 巨集可以改為 catch_end ,但 catch_end 最多容納五個參數。
  • ......
    優化、更改的地方太多了,用了超多黑魔法,
    直接上代碼、之後再繼續優化和解釋吧:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

char *error_place;
char *error_code;
int isItError = 0;

/*try$*/
#define try$(back_point, args) \
\
if(isItError){ \
	error_place = #back_point; \
	if(strcmp(args, "")) \
		error_code = args; \
	goto catch_start;\
} \
back_point:

/*try*/
#define try(back_point, ...) try$(back_point, "" #__VA_ARGS__)

/*catch_start*/
#define catch_start(...) \
\
catch_start: \
if(!isItError) return __VA_ARGS__;

/*catch*/
#define catch(ex_name) \
\
if(!strcmp(error_code, #ex_name))

/*back*/
#define back(back_point) \
\
if(!strcmp(error_place, #back_point)){ \
	goto back_point; \
}

/*get_args_6*/
#define get_args_6(arg1, arg2, arg3, arg4, arg5, arg6, ...) arg6

/*black_magic_left_bracket*/
#define black_magic_left_bracket(...) (__VA_ARGS__

/*back2 - 5*/
#define back2(arg1, arg2) back(arg1) back(arg2)
#define back3(arg1, arg2, arg3) back2(arg1, arg2) back(arg3)
#define back4(arg1, arg2, arg3, arg4) back3(arg1, arg2, arg3) back(arg4)
#define back5(arg1, arg2, arg3, arg4, arg5) back4(arg1, arg2, arg3, arg4) back(arg5)

/*catch_end*/
#define catch_end(...) \
\
isItError = 0; \
get_args_6 black_magic_left_bracket(__VA_ARGS__), back5, back4, back3, back2, back, )(__VA_ARGS__)

/*check*/
#define check(...) \
\
if(isItError){ \
	return __VA_ARGS__; \
}

/*throw*/
#define throw(ex_name, ...) \
\
isItError = 1; \
error_code = #ex_name; \
return __VA_ARGS__;


void can_not_be_negative(double input) {
	if (input < 0) {
		throw(ex_neg);
	}
}

double my_sqrt(double input) {
	can_not_be_negative(input); check(0.0);
	return sqrt(input);
}


int main() {

	my_sqrt(-10); try(ex1);
	my_sqrt(20); try(ex2);
	my_sqrt(-30); try(ex3, anthor_ex);

	/*... any things ...*/

	system("pause");

	catch_start(0);
	catch (ex_neg) {
		printf("[ex_neg] exception is happened!\n");
		printf("Input can't no be negative.\n");
	}
	catch (anthor_ex) {
		printf("[anthor_ex] exception is happened!\n");
	}
	catch_end(ex1, ex2, ex3);
}
[ex_neg] exception is happened!
Input can't no be negative.
[anthor_ex] exception is happened!
Press any key to continue . . .

這段
#define black_magic_left_bracket(...) (__VA_ARGS__
真的是黑魔法,太瘋狂了。


try 不需顯式地指出錯誤類型,默認為函式拋出的錯誤。
不過為了實現這個,就需要加上 catch_start


至少 try 的參數數量少了很多。


大綱提到的 多參數、默認參數、任意類型var......,

看來是沒時間了說的了~~下年再見(可能)~~


如果有心繼續寫下去的話,我會放在剛開沒多久的blog。~


繼續研究!~~


上一篇
Day 26: 例外處理系列:研究進行中 :優化:不再需要【回傳值必須作錯誤碼處理的約定】
下一篇
Day 28: 例外處理系列:研究結束中 :finally() 、進行封裝、巨集優化
系列文
30 Days 如何把 C 語言偽裝成高階語言 OWO /31

尚未有邦友留言

立即登入留言